def _initialize_transfer(self, transfer_options): """ Initialize the transfer scheme Parameters ---------- transfer_options: dictionary or list of dictionaries options for the load and displacement transfer scheme for the bodies """ # If the user did not specify a transfer scheme default to MELD if transfer_options is None: transfer_options = [] for body in self.model.bodies: transfer_options.append({'scheme': 'meld', 'isym': -1, 'beta': 0.5, 'npts': 200}) # if the user gave a dictionary instead of a list of # dictionaries, assume all bodies use the same settings if type(transfer_options) is dict: transfer_options = len(self.model.bodies) * [ transfer_options ] for ibody, body in enumerate(self.model.bodies): body.transfer = None body_analysis_type = 'aeroelastic' if 'analysis_type' in transfer_options[ibody]: body_analysis_type = transfer_options[ibody]['analysis_type'].lower() # Set up the transfer schemes based on the type of analysis set for this body if body_analysis_type == 'aeroelastic' or body_analysis_type == 'aerothermoelastic': # Set up the load and displacement transfer schemes if transfer_options[ibody]['scheme'].lower() == 'hermes': body.transfer = HermesTransfer(self.comm, self.struct_comm, self.aero_comm) elif transfer_options[ibody]['scheme'].lower() == 'rbf': basis = TransferScheme.PY_THIN_PLATE_SPLINE if 'basis function' in transfer_options[ibody]: if transfer_options[ibody]['basis function'].lower() == 'thin plate spline': basis = TransferScheme.PY_THIN_PLATE_SPLINE elif transfer_options[ibody]['basis function'].lower() == 'gaussian': basis = TransferScheme.PY_GAUSSIAN elif transfer_options[ibody]['basis function'].lower() == 'multiquadric': basis = TransferScheme.PY_MULTIQUADRIC elif transfer_options[ibody]['basis function'].lower() == 'inverse multiquadric': basis = TransferScheme.PY_INVERSE_MULTIQUADRIC else: print('Unknown RBF basis function for body number', ibody) quit() body.transfer = TransferScheme.pyRBF(self.comm, self.struct_comm, self.struct_root, self.aero_comm, self.aero_root, basis, 1) elif transfer_options[ibody]['scheme'].lower() == 'meld': # defaults isym = -1 # No symmetry beta = 0.5 # Decay factor num_nearest = 200 # Number of nearest neighbours if 'isym' in transfer_options[ibody]: isym = transfer_options[ibody]['isym'] if 'beta' in transfer_options[ibody]: beta = transfer_options[ibody]['beta'] if 'npts' in transfer_options[ibody]: num_nearest = transfer_options[ibody]['npts'] body.transfer = TransferScheme.pyMELD(self.comm, self.struct_comm, self.struct_root, self.aero_comm, self.aero_root, isym, num_nearest, beta) elif transfer_options[ibody]['scheme'].lower() == 'linearized meld': # defaults isym = -1 beta = 0.5 num_nearest = 200 if 'isym' in transfer_options[ibody]: isym = transfer_options[ibody]['isym'] if 'beta' in transfer_options[ibody]: beta = transfer_options[ibody]['beta'] if 'npts' in transfer_options[ibody]: num_nearest = transfer_options[ibody]['npts'] body.transfer = TransferScheme.pyLinearizedMELD(self.comm, self.struct_comm, self.struct_root, self.aero_comm, self.aero_root, isym, num_nearest, beta) elif transfer_options[ibody]['scheme'].lower()== 'beam': conn = transfer_options[ibody]['conn'] nelems = transfer_options[ibody]['nelems'] order = transfer_options[ibody]['order'] ndof = transfer_options[ibody]['ndof'] body.xfer_ndof = ndof body.transfer = TransferScheme.pyBeamTransfer(self.comm, self.struct_comm, self.struct_root, self.aero_comm, self.aero_root, conn, nelems, order, ndof) else: print("Error: Unknown transfer scheme for body", ibody) quit() # Set up the transfer schemes based on the type of analysis set for this body if body_analysis_type == 'aerothermal' or body_analysis_type == 'aerothermoelastic': # Set up the load and displacement transfer schemes if transfer_options[ibody]['thermal_scheme'].lower()== 'meld': # defaults isym = -1 beta = 0.5 num_nearest = 200 if 'isym' in transfer_options[ibody]: isym = transfer_options[ibody]['isym'] if 'beta' in transfer_options[ibody]: beta = transfer_options[ibody]['beta'] if 'npts' in transfer_options[ibody]: num_nearest = transfer_options[ibody]['npts'] body.thermal_transfer = TransferScheme.pyMELDThermal(self.comm, self.struct_comm, self.struct_root, self.aero_comm, self.aero_root, isym, num_nearest, beta) else: print("Error: Unknown thermal transfer scheme for body", ibody) quit() # Load structural and aerodynamic meshes into FUNtoFEM # Only want real part for the initialization if body.transfer is not None: if TransferScheme.dtype == np.complex128 or TransferScheme.dtype == complex: if self.struct_comm != MPI.COMM_NULL: body.transfer.setStructNodes(body.struct_X.real + 0.0j) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.transfer.setAeroNodes(body.aero_X.real + 0.0j) else: body.aero_nnodes = 0 else: if self.struct_comm != MPI.COMM_NULL: body.transfer.setStructNodes(body.struct_X) body.transfer.setStructNodes(body.struct_X) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.transfer.setAeroNodes(body.aero_X) else: body.aero_nnodes = 0 # Initialize FUNtoFEM body.transfer.initialize() # Load structural and aerodynamic meshes into FUNtoFEM if TransferScheme.dtype == np.complex128 or TransferScheme.dtype == complex: if self.struct_comm != MPI.COMM_NULL: body.transfer.setStructNodes(body.struct_X) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.transfer.setAeroNodes(body.aero_X) else: body.aero_nnodes = 0 # Initialize the thermal problem if body.thermal_transfer is not None: if TransferScheme.dtype == np.complex128 or TransferScheme.dtype == complex: if self.struct_comm != MPI.COMM_NULL: body.thermal_transfer.setStructNodes(body.struct_X.real + 0.0j) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.thermal_transfer.setAeroNodes(body.aero_X.real + 0.0j) else: body.aero_nnodes = 0 else: if self.struct_comm != MPI.COMM_NULL: body.thermal_transfer.setStructNodes(body.struct_X) body.thermal_transfer.setStructNodes(body.struct_X) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.thermal_transfer.setAeroNodes(body.aero_X) else: body.aero_nnodes = 0 # Initialize FUNtoFEM body.thermal_transfer.initialize() # Load structural and aerodynamic meshes into FUNtoFEM if TransferScheme.dtype == np.complex128 or TransferScheme.dtype == complex: if self.struct_comm != MPI.COMM_NULL: body.thermal_transfer.setStructNodes(body.struct_X) else: body.struct_nnodes = 0 if self.aero_comm != MPI.COMM_NULL: body.thermal_transfer.setAeroNodes(body.aero_X) else: body.aero_nnodes = 0
(bpts * cpts, 1))), axis=1) translated = bent + translation struct_disps = translated.flatten() - struct_X """ -------------------------------------------------------------------------------- Running TransferScheme -------------------------------------------------------------------------------- """ # Creating transfer scheme comm = MPI.COMM_SELF isymm = -1 num_nearest = 40 beta = 0.5 meld = TransferScheme.pyMELD(comm, comm, 0, comm, 0, isymm, num_nearest, beta) linmeld = TransferScheme.pyLinearizedMELD(comm, comm, 0, comm, 0, num_nearest, beta) rbf_type = TransferScheme.PY_THIN_PLATE_SPLINE sampling_ratio = 2 rbf = TransferScheme.pyRBF(comm, comm, 0, comm, 0, rbf_type, sampling_ratio) # Set nodes into transfer scheme meld.setStructNodes(struct_X) meld.setAeroNodes(aero_X) linmeld.setStructNodes(struct_X) linmeld.setAeroNodes(aero_X)
alpha = 1.0 beta = 0.0 gamma = 0.0 tacs.assembleJacobian(alpha, beta, gamma, res, mat) pc.factor() """ -------------------------------------------------------------------------------- Set up MELD and transfer loads -------------------------------------------------------------------------------- """ # Creating MELD comm = MPI.COMM_WORLD isymm = -1 num_nearest = 100 beta = 0.5 meld = TransferScheme.pyMELD(comm, comm, 0, comm, 0, isymm, num_nearest, beta) # Set nodes into transfer scheme meld.setStructNodes(struct_X) meld.setAeroNodes(aero_X) # Initialize transfer scheme meld.initialize() # Transfer loads init_disps = np.zeros(struct_X.shape, dtype=TransferScheme.dtype) aero_disps = np.zeros(3 * aero_nnodes, dtype=TransferScheme.dtype) struct_loads = np.zeros(3 * struct_nnodes, dtype=TransferScheme.dtype) meld.transferDisps(init_disps, aero_disps) meld.transferLoads(aero_loads, struct_loads)
plate_surface = np.array(plate_surface) X = np.array(X) # Create the vectors/matrices res = assembler.createVec() ans = assembler.createVec() mat = assembler.createSchurMat() pc = TACS.Pc(mat) # Assemble the heat conduction matrix assembler.assembleJacobian(1.0, 0.0, 0.0, res, mat) pc.factor() gmres = TACS.KSM(mat, pc, 20) # initialize MELDThermal meld = TransferScheme.pyMELDThermal(comm, comm, 0, comm, 0, -1, 10, 0.5) #axis of symmetry, num nearest, beta meld.setStructNodes(plate_surface) meld.setAeroNodes(X) meld.initialize() # allocate some storage arrays normal_flux = np.zeros(nVertex_CHTMarker) theta = np.zeros(nVertex_CHTMarker) temp_check = np.zeros(nVertex_CHTMarker) res_holder = np.zeros(len(mapping)) ans_holder = np.zeros(len(mapping)) Iter = 0 MaxIter = 500 # right now iterating for a fixed number of iterations # so far, this is the best way I've found to make sure both the
(struct_nnodes, 1))), axis=1) translated = bent + translation struct_disps = translated.flatten() - struct_X """ -------------------------------------------------------------------------------- Running TransferScheme -------------------------------------------------------------------------------- """ # Creating transfer scheme comm = MPI.COMM_SELF isymm = -1 num_nearest = 20 beta = 0.5 meld = TransferScheme.pyMELD(comm, comm, 0, comm, 0, scheme, isymm) # Set nodes into transfer scheme meld.setStructNodes(struct_X) meld.setAeroNodes(aero_X) # Initialize funtofem meld.initialize() # Transfer displacements aero_disps = np.zeros(3 * aero_nnodes, dtype=TransferScheme.dtype) meld.transferDisps(struct_disps) # Write meshes to file struct_elem_type = 1 aero_elem_type = 1
X_hmg = np.hstack((X, np.ones((4,1), dtype=TransferScheme.dtype))) disps_hmg = X_hmg.dot(T.T) disps_hmg -= X_hmg disps = disps_hmg[:,:-1] + e return T, disps _, aero_disps = computeTransformAndDisps(R, t, e, aero_X) # Create TransferScheme comm = MPI.COMM_WORLD beta = 0.5 num_nearest = 4 isymm = -1 meld = TransferScheme.pyMELD(comm, comm, 0, comm, 0, isymm, num_nearest, beta) # Load data into TransferScheme aero_nnodes = aero_X.shape[0] meld.setAeroNodes(aero_X.flatten(order='C')) # Decompose displacements R = np.zeros(9, dtype=TransferScheme.dtype) t = np.zeros(3, dtype=TransferScheme.dtype) e = np.zeros(3*aero_nnodes, dtype=TransferScheme.dtype) meld.transformEquivRigidMotion(aero_disps.flatten(order='C'), R, t, e) # Compare the original and decomposed displacements R = R.reshape((3,3), order='F') e = e.reshape((-1,3)) _, decomp_disps = computeTransformAndDisps(R, t, e, aero_X)
r_mat = r_assembler.createSchurMat() r_pc = TACS.Pc(r_mat) # Assemble the heat conduction matrix r_assembler.assembleJacobian(1.0, 0.0, 0.0, r_res, r_mat) r_pc.factor() r_gmres = TACS.KSM(r_mat, r_pc, 20) right_surface = np.array(right_surface) left_surface = np.array(left_surface) right_mapping = np.array(right_mapping) left_mapping = np.array(left_mapping) # initialize MELDThermal meld = TransferScheme.pyMELDThermal( comm, comm, 0, comm, 0, -1, 10, 0.5 ) #axis of symmetry, num nearest neighbors, beta (distance weighting parameter) # set left nodes as aero, right nodes as structure meld.setStructNodes(right_surface) meld.setAeroNodes(left_surface) meld.initialize() # assign an initial thermal BC to right edge of left plate # (don't make this the correct answer) res_arr = l_res.getArray() l_assembler.setBCs(l_res) if len(left_mapping) > 0: res_arr[left_mapping] = 400.0 # initialize the right plate - isothermal BC makes all temps 400.0 # (this is not actually necessary)
# Load points/forces from data file XF = np.loadtxt('funtofemforces.dat') # Get the points/forces aero_X = XF[:, :3].flatten().astype(TransferScheme.dtype) aero_loads = (251.8 * 251.8 / 2 * 0.3) * XF[:, 3:].flatten().astype( TransferScheme.dtype) aero_nnodes = aero_X.shape[0] / 3 # Create TransferScheme object isymm = -1 num_nearest = 20 beta = 0.5 meld = TransferScheme.pyMELD(tacs_comm, tacs_comm, 0, tacs_comm, 0, isymm, num_nearest, beta) # Load structural and aerodynamic meshes into TransferScheme meld.setStructNodes(struct_X) meld.setAeroNodes(aero_X) # Initialize TransferScheme meld.initialize() # Set and apply zero structural displacements (initial conditions) struct_disps = np.zeros(len(struct_X), dtype=TransferScheme.dtype) aero_disps = np.zeros(len(aero_X), dtype=TransferScheme.dtype) meld.transferDisps(struct_disps, aero_disps) # Transfer loads from fluid and get loads on structure struct_loads = np.zeros(len(struct_X), dtype=TransferScheme.dtype)