def __init__(self, comm, tacs_comm, model, n_tacs_procs): super(wedgeTACS,self).__init__(comm, tacs_comm, model) assembler = None mat = None pc = None gmres = None self.T_ref = 300.0 if comm.Get_rank() < n_tacs_procs: # Set constitutive properties rho = 4540.0 # density, kg/m^3 E = 118e9 # elastic modulus, Pa nu = 0.325 # poisson's ratio ys = 1050e6 # yield stress, Pa kappa = 6.89 specific_heat=463.0 thickness = 0.015 volume = 25 # need tacs volume for TACSAverageTemperature function # Create the constitutvie propertes and model props = constitutive.MaterialProperties(rho=4540.0, specific_heat=463.0, kappa = 6.89, E=118e9, nu=0.325, ys=1050e6) con = constitutive.SolidConstitutive(props, t=1.0, tNum=0) # Set the model type = linear thermoelasticity elem_model = elements.LinearThermoelasticity3D(con) # Create the basis class basis = elements.LinearHexaBasis() # Create the element element = elements.Element3D(elem_model, basis) varsPerNode = elem_model.getVarsPerNode() # Load in the mesh mesh = TACS.MeshLoader(tacs_comm) mesh.scanBDFFile('tacs_aero.bdf') # Set the element mesh.setElement(0, element) # Create the assembler object assembler = mesh.createTACS(varsPerNode) # Create the preconditioner for the corresponding matrix mat = assembler.createSchurMat() pc = TACS.Pc(mat) # Create GMRES object for structural adjoint solves nrestart = 0 # number of restarts before giving up m = 30 # size of Krylov subspace (max # of iterations) gmres = TACS.KSM(mat, pc, m, nrestart) self._initialize_variables(assembler, mat, pc, gmres) self.initialize(model.scenarios[0], model.bodies) return
def addFaceTraction(order, assembler, load): # Create the surface traction aux = TACS.AuxElements() # Get the element node locations nelems = assembler.getNumElements() for i in range(nelems): # Get the information about the given element elem, Xpt, vars0, dvars, ddvars = assembler.getElementData(i) # Loop over the nodes and create the traction forces in the # x/y/z directions nnodes = order*order tx = np.zeros(nnodes, dtype=TACS.dtype) ty = np.zeros(nnodes, dtype=TACS.dtype) tz = np.zeros(nnodes, dtype=TACS.dtype) # Set the components of the surface traction for j in range(nnodes): x = Xpt[3*j] y = Xpt[3*j+1] z = Xpt[3*j+2] theta = -R*np.arctan2(y, x) p = -load*np.sin(beta*z)*np.sin(alpha*theta) tx[j] = p*Xpt[3*j]/R ty[j] = p*Xpt[3*j+1]/R tz[j] = 0.0 trac = elements.ShellTraction(order, tx, ty, tz) aux.addElement(i, trac) return aux
def createTACS(self, options, model, ndof=8): """ Set up TACS and TACSIntegator. """ # grab the tacs instance from the builder self.tacs = self.builder.getTACS(options['ordering'], TACS.PY_DIRECT_SCHUR, ndof=ndof) # Things for configuring time marching self.integrator = {} for scenario in model.scenarios: self.integrator[scenario.id] = self.createIntegrator( self.tacs, options) # Control F5 output if self.builder.rigid_viz == 1: flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.EXTRAS) rigidf5 = TACS.ToFH5(self.tacs, TACS.PY_RIGID, flag) self.integrator[scenario.id].setRigidOutput(rigidf5) if self.builder.shell_viz == 1: flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS | TACS.ToFH5.STRESSES | TACS.ToFH5.EXTRAS) shellf5 = TACS.ToFH5(self.tacs, TACS.PY_SHELL, flag) self.integrator[scenario.id].setShellOutput(shellf5) if self.builder.beam_viz == 1: flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS | TACS.ToFH5.STRESSES | TACS.ToFH5.EXTRAS) beamf5 = TACS.ToFH5(self.tacs, TACS.PY_BEAM, flag) self.integrator[scenario.id].setBeamOutput(beamf5) if self.builder.solid_viz == 1: flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS | TACS.ToFH5.STRESSES | TACS.ToFH5.EXTRAS) solidf5 = TACS.ToFH5(self.tacs, TACS.PY_SOLID, flag) self.integrator[scenario.id].setSolidOutput(solidf5) # store the reference to body list after initializations are complete self.tacs_body_list = self.builder.body_list return
def post_export_f5(self): flag = (TACS.OUTPUT_CONNECTIVITY | TACS.OUTPUT_NODES | TACS.OUTPUT_DISPLACEMENTS | TACS.OUTPUT_STRAINS) f5 = TACS.ToFH5(self.assembler, TACS.SOLID_ELEMENT, flag) filename_struct_out = "tets" + ".f5" f5.writeToFile(filename_struct_out)
def createAuxElements(self, assembler, order=3): aux = TACS.AuxElements() tx = np.zeros(order * order) ty = np.zeros(order * order) tz = -np.ones(order * order) trac = elements.ShellTraction(order, tx, ty, tz) for i in range(assembler.getNumElements()): aux.addElement(i, trac) return aux
def post_export_f5(self): flag = (TACS.OUTPUT_CONNECTIVITY | TACS.OUTPUT_NODES | TACS.OUTPUT_DISPLACEMENTS | TACS.OUTPUT_EXTRAS) f5 = TACS.ToFH5(self.assembler, TACS.BEAM_OR_SHELL_ELEMENT, flag) file_out = "onera_struct_out.f5" f5.writeToFile(file_out) return
def computeTractionLoad(name, forest, assembler, trac): """ Add a surface traction to all quadrants or octants that touch a face or edge with the given name. The assembler must be created from the provided forest. The list trac must have a traction for each face (6) for octants or each edge (4) for quadrants. Note: This code uses the fact that the getOctsWithName or getQuadsWithName returns the local face or edge index touching the surface or edge in the info member. Args: name (str): Name of the surface where the traction will be added forest (QuadForest or OctForest): Forest for the finite-element mesh assembler (Assembler): TACSAssembler object for the finite-element problem trac (list): List of tractions, one for each possible face/edge orientation Returns: Vec: A force vector containing the traction """ if isinstance(forest, TMR.OctForest): octants = forest.getOctants() face_octs = forest.getOctsWithName(name) elif isinstance(forest, TMR.QuadForest): octants = forest.getQuadrants() face_octs = forest.getQuadsWithName(name) # Create the force vector and zero the variables in the assembler force = assembler.createVec() assembler.zeroVariables() # Create the auxiliary element class aux = TACS.AuxElements() for i in range(len(face_octs)): index = face_octs[i].tag if index is not None: aux.addElement(index, trac[face_octs[i].info]) # Keep auxiliary elements already set in the assembler # aux_tmp = assembler.getAuxElements() assembler.setAuxElements(aux) # Compute the residual where force = -residual assembler.assembleRes(force) force.scale(-1.0) # Reset the auxiliary elements assembler.setAuxElements(None) # (aux_tmp) return force
def addFaceTraction(order, forest, attr, assembler, tr): trac = [] for findex in range(6): trac.append(elements.Traction3D(order, findex, tr[0], tr[1], tr[2])) # Retrieve octants from the forest octants = forest.getOctants() face_octs = forest.getOctsWithAttribute(attr) aux = TACS.AuxElements() for i in range(len(face_octs)): aux.addElement(face_octs[i].tag, trac[face_octs[i].info]) return aux
def setAssembler(self, assembler, ksfunc): # Create tacs assembler object from mesh loader self.assembler = assembler # Create the list of functions self.funcs = [functions.StructuralMass(self.assembler), ksfunc] # Set up the solver self.ans = self.assembler.createVec() self.res = self.assembler.createVec() self.adjoint = self.assembler.createVec() self.dfdu = self.assembler.createVec() self.mat = self.assembler.createFEMat() self.pc = TACS.Pc(self.mat) self.gmres = TACS.KSM(self.mat, self.pc, 10) # For visualization flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS | TACS.ToFH5.EXTRAS) self.f5 = TACS.ToFH5(self.assembler, TACS.PY_PLANE_STRESS, flag) return
def rectangular_domain(nx, ny, Ly=100.0): # Set the y-dimension based on a unit aspect ratio Lx = (nx*Ly)/ny # Compute the total area area = Lx*Ly # Set the number of elements/nodes in the problem nnodes = (nx+1)*(ny+1) nelems = nx*ny nodes = np.arange(nnodes).reshape((nx+1, ny+1)) # Set the node locations xpts = np.zeros((nnodes, 3)) x = np.linspace(0, Lx, nx+1) y = np.linspace(0, Ly, ny+1) for j in range(ny+1): for i in range(nx+1): xpts[nodes[i,j],0] = x[i] xpts[nodes[i,j],1] = y[j] # Set the connectivity and create the corresponding elements conn = np.zeros((nelems, 4), dtype=np.intc) for j in range(ny): for i in range(nx): # Append the first set of nodes n = i + nx*j conn[n,0] = nodes[i, j] conn[n,1] = nodes[i+1, j] conn[n,2] = nodes[i, j+1] conn[n,3] = nodes[i+1, j+1] bcs = np.array(nodes[0,:], dtype=np.intc) # Create the tractions and add them to the surface surf = 1 # The u=1 positive surface tx = np.zeros(2) ty = -100*np.ones(2) trac = elements.PSQuadTraction(surf, tx, ty) # Create the auxiliary element class aux = TACS.AuxElements() for j in range(int(ny/8)): num = nx-1 + nx*j aux.addElement(num, trac) return xpts, conn, bcs, aux, area
def addEdgeTraction(order, forest, attr, assembler, tr): trac = [] for findex in range(4): trac.append(elements.PSQuadTraction(findex, tr[0]*np.ones(2), \ tr[1]*np.ones(2))) # Retrieve octants from the forest quadrants = forest.getQuadrants() edge_quads = forest.getQuadsWithAttribute(attr) aux = TACS.AuxElements() for i in range(len(edge_quads)): index = quadrants.findIndex(edge_quads[i]) if index is not None: aux.addElement(index, trac[edge_quads[i].tag]) return aux
def __init__(self, tacs, f5): # Set the communicator pointer self.comm = MPI.COMM_WORLD self.rank = self.comm.Get_rank() self.size = self.comm.Get_size() self.nvars = num_components / self.size if num_components % self.size != 0 and self.rank == self.size - 1: self.nvars += num_components % self.size self.ncon = 1 # Initialize the base class super(CRMSizing, self).__init__(self.comm, self.nvars, self.ncon) self.tacs = tacs self.f5 = f5 self.res = self.tacs.createVec() self.ans = self.tacs.createVec() self.mat = self.tacs.createFEMat() self.pc = TACS.Pc(self.mat) # Create list of required TACS functions (mass, ksfailure) self.mass = functions.StructuralMass(self.tacs) ksweight = 50.0 alpha = 1.0 self.ksfailure = functions.KSFailure(self.tacs, ksweight, alpha) self.ksfailure.setLoadFactor(1.5) self.funclist = [self.mass, self.ksfailure] self.svsens = self.tacs.createVec() self.adj = self.tacs.createVec() self.adjSensProdArray = np.zeros(num_components) self.tempdvsens = np.zeros(num_components) # Get initial mass for scaling self.initmass = self.tacs.evalFunctions([self.funclist[0]]) self.xscale = 0.0025 # Keep track of the number of gradient evaluations self.gevals = 0 return
def addFaceTraction(order, assembler): # Create the surface traction aux = TACS.AuxElements() # Get the element node locations nelems = assembler.getNumElements() # Loop over the nodes and create the traction forces in the x/y/z # directions nnodes = order * order tx = np.zeros(nnodes, dtype=TACS.dtype) ty = np.zeros(nnodes, dtype=TACS.dtype) tz = np.zeros(nnodes, dtype=TACS.dtype) tz[:] = 5.0 # Create the shell traction trac = elements.ShellTraction(order, tx, ty, tz) for i in range(nelems): aux.addElement(i, trac) return aux
def addFaceTraction(order, forest, assembler): # Get the quadrilaterals of interest quads = forest.getQuadsWithName('traction') # Create the surface traction aux = TACS.AuxElements() # Loop over the nodes and create the traction forces in the x/y/z # directions nnodes = order tx = np.zeros(nnodes, dtype=TACS.dtype) ty = np.zeros(nnodes, dtype=TACS.dtype) ty[:] = 10.0 # Create the shell traction surf = 1 trac = elements.PSQuadTraction(surf, tx, ty) for q in quads: aux.addElement(q.tag, trac) return aux
def createIntegrator(self, tacs, options): """ Create the Integrator (solver) and configure it """ end_time = options['steps'] * options['step_size'] # Create an integrator for TACS if options['integrator'] == 'BDF': integrator = TACS.BDFIntegrator(tacs, options['start_time'], end_time, options['steps'], options['integration_order']) # Set other parameters for integration integrator.setRelTol(options['solver_rel_tol']) integrator.setAbsTol(options['solver_abs_tol']) integrator.setMaxNewtonIters(options['max_newton_iters']) integrator.setUseFEMat(options['femat'], options['ordering']) #integrator.setPrintLevel(options['print_level']) integrator.setOutputFrequency(options['output_freq']) return integrator
def interpolateDesignVec(orig_filter, orig_vec, new_filter, new_vec): """ This function interpolates a design vector from the original design space defined on an OctForest or QuadForest and interpolates it to a new OctForest or QuadForest. This function is used after a mesh adaptation step to get the new design space. Args: orig_filter (OctForest or QuadForest): Original filter Oct or QuadForest object orig_vec (PVec): Design variables on the original mesh in a ParOpt.PVec new_filter (OctForest or QuadForest): New filter Oct or QuadForest object new_vec (PVec): Design variables on the new mesh in a ParOpt.PVec (set on ouput) """ # Convert the PVec class to TACSBVec orig_x = TMR.convertPVecToVec(orig_vec) if orig_x is None: raise ValueError( 'Original vector must be generated by TMR.TopoProblem') new_x = TMR.convertPVecToVec(new_vec) if new_x is None: raise ValueError('New vector must be generated by TMR.TopoProblem') if orig_x.getVarsPerNode() != new_x.getVarsPerNode(): raise ValueError('Number of variables per node must be consistent') orig_varmap = orig_x.getVarMap() new_varmap = new_x.getVarMap() vars_per_node = orig_x.getVarsPerNode() # Create the interpolation class interp = TACS.VecInterp(orig_varmap, new_varmap, vars_per_node) new_filter.createInterpolation(orig_filter, interp) interp.initialize() # Perform the interpolation interp.mult(orig_x, new_x) return
def createAssembler(m=5.0, c=0.5, k=5.0, u0=-0.5, udot0=1.0, pc=None): num_disps = 1 num_nodes = 1 # Spring element #spr = SpringMassDamper(num_disps, num_nodes, m, c, k) dspr = PSPACE.PySMD(m, c, k, u0, udot0) sprcb = SMDUpdate(dspr) sspr = PSPACE.PyStochasticElement(dspr, pc, sprcb) dforce = ForcingElement(num_disps, num_nodes, amplitude=1.0, omega=10.0) forcecb = ForceUpdate(dforce) sforce = PSPACE.PyStochasticElement(dforce, pc, forcecb) ndof_per_node = 1 * pc.getNumBasisTerms() num_owned_nodes = 1 num_elems = 1 # Add user-defined element to TACS comm = MPI.COMM_WORLD assembler = TACS.Assembler.create(comm, ndof_per_node, num_owned_nodes, num_elems) ptr = np.array([0, 1], dtype=np.intc) conn = np.array([0], dtype=np.intc) assembler.setElementConnectivity(ptr, conn) # Set elements assembler.setElements([sspr]) # set Auxiliary elements aux = TACS.AuxElements() aux.addElement(0, sforce) assembler.setAuxElements(aux) assembler.initialize() return assembler
assembler = TACS.Assembler.create(comm, 1, 1, 1) conn = np.array([0], dtype=np.intc) ptr = np.array([0, 1], dtype=np.intc) assembler.setElementConnectivity(conn, ptr) assembler.setElements([spr]) assembler.initialize() # Create instance of integrator t0 = 0.0 dt = 0.01 num_steps = 1000 tf = num_steps * dt order = 2 bdf = TACS.BDFIntegrator(assembler, t0, tf, num_steps, order) # Integrate governing equations #bdf.integrate() bdf.iterate(0) for step in range(1, num_steps + 1): bdf.iterate(step) _, uvec, _, _ = bdf.getStates(num_steps) u = uvec.getArray() print "f = ", u print "df/dx, approx = ", u.imag / 1e-30 # Write out solution bdf.writeRawSolution('spring.dat', 0)
Input aerodynamic surface mesh and forces -------------------------------------------------------------------------------- """ XF = np.loadtxt('funtofemforces.dat') aero_X = XF[:, :3].flatten().astype(TransferScheme.dtype) aero_loads = (251.8 * 251.8 / 2 * 0.3) * XF[:, 3:].flatten().astype( TransferScheme.dtype) / float(tacs_comm.Get_size()) aero_nnodes = aero_X.shape[0] / 3 """ -------------------------------------------------------------------------------- Initialize TACS -------------------------------------------------------------------------------- """ # Load structural mesh from bdf file struct_mesh = TACS.MeshLoader(tacs_comm) struct_mesh.scanBDFFile("CRM_box_2nd.bdf") # Set constitutive properties rho = 2500.0 # density, kg/m^3 E = 70e9 # elastic modulus, Pa nu = 0.3 # poisson's ratio kcorr = 5.0 / 6.0 # shear correction factor ys = 350e6 # yield stress, Pa min_thickness = 0.001 max_thickness = 0.020 thickness = 0.005 # Loop over components, creating stiffness and element object for each num_components = struct_mesh.getNumComponents() for i in range(num_components):
def __init__(self, comm, bdf_name): self.comm = comm struct_mesh = TACS.MeshLoader(self.comm) struct_mesh.scanBDFFile(bdf_name) # Set constitutive properties rho = 2500.0 # density, kg/m^3 E = 70e9 # elastic modulus, Pa nu = 0.3 # poisson's ratio kcorr = 5.0 / 6.0 # shear correction factor ys = 350e6 # yield stress, Pa min_thickness = 0.002 max_thickness = 0.20 thickness = 0.02 # Loop over components, creating stiffness and element object for each num_components = struct_mesh.getNumComponents() for i in range(num_components): descriptor = struct_mesh.getElementDescript(i) # Set the design variable index design_variable_index = i stiff = constitutive.isoFSDT(rho, E, nu, kcorr, ys, thickness, design_variable_index, min_thickness, max_thickness) element = None # Create the element object if descriptor in ["CQUAD", "CQUADR", "CQUAD4"]: element = elements.MITCShell(2, stiff, component_num=i) struct_mesh.setElement(i, element) # Create tacs assembler object from mesh loader self.assembler = struct_mesh.createTACS(6) # Create the KS Function ksWeight = 50.0 self.funcs = [ functions.StructuralMass(self.assembler), functions.KSFailure(self.assembler, ksWeight) ] # Create the forces self.forces = self.assembler.createVec() force_array = self.forces.getArray() force_array[2::6] += 100.0 # uniform load in z direction self.assembler.applyBCs(self.forces) # Set up the solver self.ans = self.assembler.createVec() self.res = self.assembler.createVec() self.adjoint = self.assembler.createVec() self.dfdu = self.assembler.createVec() self.mat = self.assembler.createFEMat() self.pc = TACS.Pc(self.mat) subspace = 100 restarts = 2 self.gmres = TACS.KSM(self.mat, self.pc, subspace, restarts) # Scale the mass objective so that it is O(10) self.mass_scale = 1e-3 # Scale the thickness variables so that they are measured in # mm rather than meters self.thickness_scale = 1000.0 # The number of thickness variables in the problem self.nvars = num_components # The number of constraints (1 global stress constraint that # will use the KS function) self.ncon = 1 # Initialize the base class - this will run the same problem # on all processors super(uCRM_VonMisesMassMin, self).__init__(MPI.COMM_SELF, self.nvars, self.ncon) # Set the inequality options for this problem in ParOpt: # The dense constraints are inequalities c(x) >= 0 and # use both the upper/lower bounds self.setInequalityOptions(dense_ineq=True, use_lower=True, use_upper=True) # For visualization flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS | TACS.ToFH5.EXTRAS) self.f5 = TACS.ToFH5(self.assembler, TACS.PY_SHELL, flag) self.iter_count = 0 return
# initialize TACS for left plate # Create the constitutvie propertes and model left_kappa = 230.0 props = constitutive.MaterialProperties(kappa=left_kappa) con = constitutive.PlaneStressConstitutive(props) heat = elements.HeatConduction2D(con) # Create the basis class quad_basis = elements.LinearQuadBasis() # Create the element element = elements.Element2D(heat, quad_basis) # Load in the mesh mesh = TACS.MeshLoader(comm) mesh.scanBDFFile('left_plate.bdf') # Set the element mesh.setElement(0, element) # Create the assembler object varsPerNode = heat.getVarsPerNode() l_assembler = mesh.createTACS(varsPerNode) # get structures nodes left_pts = l_assembler.createNodeVec() l_assembler.getNodes(left_pts) left_pts_array = left_pts.getArray() # get mapping of shared edge
# The volumes of the elements in the filter mesh filtr_volumes = None # Set the values of the objective array obj_array = [1.0e2] for ite in range(max_iterations): # Create the TACSAssembler and TMRTopoProblem instance nlevs = mg_levels[ite] assembler, problem, filtr, varmap = createTopoProblem(forest, nlevels=nlevs) # Write out just the mesh - for visualization flag = (TACS.ToFH5.NODES) f5 = TACS.ToFH5(assembler, TACS.PY_PLANE_STRESS, flag) f5.writeToFile(os.path.join(args.prefix, 'plate_mesh%d.f5' % (ite))) # Set the constraint type funcs = [functions.StructuralMass(assembler)] # Add the point loads to the vertices force1 = addVertexLoad(comm, order, forest, 'pt1', assembler, [0.0, -1000.]) force1.scale(-1.0) # Set the load cases forces = [force1] problem.setLoadCases(forces) # Set the mass constraint problem.addConstraints(0, funcs, [-m_fixed], [-1.0 / m_fixed])
conn = np.array([0], dtype=np.intc) ptr = np.array([0, 1], dtype=np.intc) assembler.setElementConnectivity(conn, ptr) assembler.setElements([spr]) assembler.initialize() # Time marching setup tinit = 0.0 tfinal = 1000.0 # Create integrators for implicit time marching of system sizes = [1250, 2500, 5000, 10000] for nsteps in sizes: # BDF solution bdf_orders = [1, 2, 3] for order in bdf_orders: bdf = TACS.BDFIntegrator(assembler, tinit, tfinal, nsteps, order) bdf.setPrintLevel(0) bdf.integrate() bdf.writeRawSolution( 'smd-bdf' + str(order) + '-' + str(nsteps) + '.dat', 0) # DIRK solution dirk_orders = [2, 3, 4] for order in dirk_orders: dirk = TACS.DIRKIntegrator(assembler, tinit, tfinal, nsteps, order - 1) dirk.setPrintLevel(0) dirk.integrate() dirk.writeRawSolution( 'smd-dirk' + str(order) + '-' + str(nsteps) + '.dat', 0)
def __init__(self, integrator_options, comm, tacs_comm, model, n_tacs_procs): self.tacs_proc = False if comm.Get_rank() < n_tacs_procs: self.tacs_proc = True # Set constitutive properties T_ref = 300.0 rho = 4540.0 # density, kg/m^3 E = 118e9 # elastic modulus, Pa nu = 0.325 # poisson's ratio ys = 1050e6 # yield stress, Pa kappa = 6.89 specific_heat = 463.0 thickness = 0.015 volume = 25 # need tacs volume for TACSAverageTemperature function # Create the constitutvie propertes and model props_plate = constitutive.MaterialProperties(rho=4540.0, specific_heat=463.0, kappa=6.89, E=118e9, nu=0.325, ys=1050e6) #con_plate = constitutive.ShellConstitutive(props_plate,thickness,1,0.01,0.10) #model_plate = elements.ThermoelasticPlateModel(con_plate) con_plate = constitutive.PlaneStressConstitutive(props_plate, t=1.0, tNum=0) model_plate = elements.HeatConduction2D(con_plate) # Create the basis class quad_basis = elements.LinearQuadBasis() # Create the element #element_shield = elements.Element2D(model_shield, quad_basis) #element_insulation = elements.Element2D(model_insulation, quad_basis) element_plate = elements.Element2D(model_plate, quad_basis) varsPerNode = model_plate.getVarsPerNode() # Load in the mesh mesh = TACS.MeshLoader(tacs_comm) mesh.scanBDFFile('tacs_aero.bdf') # Set the element mesh.setElement(0, element_plate) # Create the assembler object #varsPerNode = heat.getVarsPerNode() assembler = mesh.createTACS(varsPerNode) # Create distributed node vector from TACS Assembler object and # extract the node locations nbodies = 1 struct_X = [] struct_nnodes = [] for body in range(nbodies): self.struct_X_vec = assembler.createNodeVec() assembler.getNodes(self.struct_X_vec) struct_X.append(self.struct_X_vec.getArray()) struct_nnodes.append(len(struct_X) / 3) assembler.setNodes(self.struct_X_vec) # Initialize member variables pertaining to TACS self.T_ref = T_ref self.vol = volume self.assembler = assembler self.struct_X = struct_X self.struct_nnodes = struct_nnodes self.struct_rhs_vec = assembler.createVec() #self.psi_T_S_vec = assembler.createVec() #psi_T_S = self.psi_T_S_vec.getArray() #self.psi_T_S = np.zeros((psi_T_S.size,self.nfunc),dtype=TACS.dtype) self.ans = self.assembler.createVec() self.bvec_heat_flux = self.assembler.createVec() # Things for configuring time marching self.integrator = {} for scenario in model.scenarios: self.integrator[scenario.id] = self.createIntegrator( self.assembler, integrator_options) super(wedgeTACS, self).__init__(integrator_options, comm, tacs_comm, model) self.initialize(model.scenarios[0], model.bodies)
def __init__(self, comm, tacs_comm, model, n_tacs_procs): super(wedgeTACS, self).__init__(comm, tacs_comm, model) self.tacs_proc = False if comm.Get_rank() < n_tacs_procs: self.tacs_proc = True #mesh = TACS.MeshLoader(tacs_comm) #mesh.scanBDFFile("tacs_aero.bdf") # Set constitutive properties T_ref = 300.0 rho = 4540.0 # density, kg/m^3 E = 118e9 # elastic modulus, Pa nu = 0.325 # poisson's ratio ys = 1050e6 # yield stress, Pa kappa = 6.89 specific_heat = 463.0 thickness = 0.015 volume = 25 # need tacs volume for TACSAverageTemperature function # Create the constitutvie propertes and model props_plate = constitutive.MaterialProperties(rho=4540.0, specific_heat=463.0, kappa=6.89, E=118e9, nu=0.325, ys=1050e6) #con_plate = constitutive.ShellConstitutive(props_plate,thickness,1,0.01,0.10) #model_plate = elements.ThermoelasticPlateModel(con_plate) con_plate = constitutive.PlaneStressConstitutive(props_plate, t=1.0, tNum=0) model_plate = elements.HeatConduction2D(con_plate) # Create the basis class quad_basis = elements.LinearQuadBasis() # Create the element #element_shield = elements.Element2D(model_shield, quad_basis) #element_insulation = elements.Element2D(model_insulation, quad_basis) element_plate = elements.Element2D(model_plate, quad_basis) varsPerNode = model_plate.getVarsPerNode() # Load in the mesh mesh = TACS.MeshLoader(tacs_comm) mesh.scanBDFFile('tacs_aero.bdf') # Set the element mesh.setElement(0, element_plate) # Create the assembler object #varsPerNode = heat.getVarsPerNode() assembler = mesh.createTACS(varsPerNode) res = assembler.createVec() ans = assembler.createVec() mat = assembler.createSchurMat() # Create distributed node vector from TACS Assembler object and # extract the node locations nbodies = 1 struct_X = [] struct_nnodes = [] for body in range(nbodies): self.struct_X_vec = assembler.createNodeVec() assembler.getNodes(self.struct_X_vec) struct_X.append(self.struct_X_vec.getArray()) struct_nnodes.append(len(struct_X) / 3) assembler.setNodes(self.struct_X_vec) # Create the preconditioner for the corresponding matrix pc = TACS.Pc(mat) alpha = 1.0 beta = 0.0 gamma = 0.0 assembler.assembleJacobian(alpha, beta, gamma, res, mat) pc.factor() # Create GMRES object for structural adjoint solves nrestart = 0 # number of restarts before giving up m = 30 # size of Krylov subspace (max # of iterations) gmres = TACS.KSM(mat, pc, m, nrestart) # Initialize member variables pertaining to TACS self.T_ref = T_ref self.vol = volume self.assembler = assembler self.res = res self.ans = ans self.mat = mat self.pc = pc self.struct_X = struct_X self.struct_nnodes = struct_nnodes self.gmres = gmres self.svsens = assembler.createVec() self.struct_rhs_vec = assembler.createVec() self.psi_T_S_vec = assembler.createVec() psi_T_S = self.psi_T_S_vec.getArray() self.psi_T_S = np.zeros((psi_T_S.size, self.nfunc), dtype=TACS.dtype) self.ans_array = [] self.svsenslist = [] self.dvsenslist = [] for func in range(self.nfunc): self.svsenslist.append(self.assembler.createVec()) self.dvsenslist.append(self.assembler.createDesignVec()) for scenario in range(len(model.scenarios)): self.ans_array.append(self.ans.getArray().copy()) self.initialize(model.scenarios[0], model.bodies)
#---------------------------------------------------------------------! rho = 2500.0 # density, kg/m^3 E = 70.0e9 # elastic modulus, Pa nu = 0.30 # poisson's ratio kcorr = 5.0/6.0 # shear correction factor ys = 350.0e6 # yield stress, Pa min_thickness = 0.01 # minimum thickness of elements in m max_thickness = 0.10 # maximum thickness of elemetns in m thickness = 0.05 # currrent thickness of elements in m #---------------------------------------------------------------------! # Load input BDF, set properties and create TACS #---------------------------------------------------------------------! mesh = TACS.MeshLoader(comm) mesh.setConvertToCoordinate(convert_mesh) mesh.scanBDFFile(bdfFileName) num_components = mesh.getNumComponents() for i in range(num_components): descriptor = mesh.getElementDescript(i) stiff = constitutive.isoFSDT(rho, E, nu, kcorr, ys, thickness, i, min_thickness, max_thickness) element = None if descriptor in ["CQUAD"]: element = elements.MITC(stiff, gravity, v0, w0) mesh.setElement(i, element) tacs = mesh.createTACS(8)
aux = creator.createAuxElements(assembler, order=order) assembler.setAuxElements(aux) # Create a solution vector ans = assembler.createVec() res = assembler.createVec() alpha = 1.0 beta = 0.0 gamma = 0.0 mg.assembleJacobian(alpha, beta, gamma, res) # Factor the preconditioner mg.factor() subspace = 100 gmres = TACS.KSM(mg.getMat(), mg, subspace, isFlexible=1) gmres.setMonitor(comm, 'GMRES', 1) gmres.solve(res, ans) ans.scale(-1.0) assembler.setVariables(ans) # Output for visualization flag = (TACS.ToFH5.NODES | TACS.ToFH5.DISPLACEMENTS | TACS.ToFH5.STRAINS) f5 = TACS.ToFH5(assembler, TACS.PY_SHELL, flag) f5.writeToFile('visualization.f5') # Duplicate the forest and refine it uniformly forest_refined = forest.duplicate() forest_refined.setMeshOrder(4) forest_refined.balance(1) assembler_refined = creator.createTACS(forest_refined)
]) # initialize TACS # Create the constitutvie propertes and model props = constitutive.MaterialProperties() con = constitutive.PlaneStressConstitutive(props) heat = elements.HeatConduction2D(con) # Create the basis class quad_basis = elements.LinearQuadBasis() # Create the element element = elements.Element2D(heat, quad_basis) # Load in the mesh mesh = TACS.MeshLoader(comm) mesh.scanBDFFile('plate_bump.bdf') # Set the element mesh.setElement(0, element) # Create the assembler object varsPerNode = heat.getVarsPerNode() assembler = mesh.createTACS(varsPerNode) # get structures nodes Xpts = assembler.createNodeVec() assembler.getNodes(Xpts) Xpts_array = Xpts.getArray() # get mapping of flow edge
def __init__(self, comm, tacs_comm, model, n_tacs_procs): super(OneraPlate, self).__init__(comm, tacs_comm, model) assembler = None mat = None if comm.Get_rank() < n_tacs_procs: # Set the creator object ndof = 6 creator = TACS.Creator(tacs_comm, ndof) if tacs_comm.rank == 0: # Create the elements nx = 10 ny = 10 # Set the nodes nnodes = (nx+1)*(ny+1) nelems = nx*ny nodes = np.arange(nnodes).reshape((nx+1, ny+1)) conn = [] for j in range(ny): for i in range(nx): # Append the node locations conn.append([nodes[i, j], nodes[i+1, j], nodes[i, j+1], nodes[i+1, j+1]]) # Set the node pointers conn = np.array(conn, dtype=np.intc).flatten() ptr = np.arange(0, 4*nelems+1, 4, dtype=np.intc) elem_ids = np.zeros(nelems, dtype=np.intc) creator.setGlobalConnectivity(nnodes, ptr, conn, elem_ids) # Set the boundary conditions - fixed on the root bcnodes = np.array(nodes[:, 0], dtype=np.intc) creator.setBoundaryConditions(bcnodes) root_chord = 0.8 semi_span = 1.2 taper_ratio = 0.56 sweep = 26.7 # degrees # Set the node locations Xpts = np.zeros(3*nnodes) x = np.linspace(0, 1, nx+1) y = np.linspace(0, 1, ny+1) for j in range(ny+1): for i in range(nx+1): c = root_chord*(1.0 - y[j]) + root_chord*taper_ratio*y[j] xoff = 0.25*root_chord + semi_span*y[j]*np.tan(sweep*np.pi/180.0) Xpts[3*nodes[i,j]] = xoff + c*(x[i] - 0.25) Xpts[3*nodes[i,j]+1] = semi_span*y[j] # Set the node locations creator.setNodes(Xpts) # Set the material properties props = constitutive.MaterialProperties(rho=2570.0, E=70e9, nu=0.3, ys=350e6) # Set constitutive properties t = 0.025 tnum = 0 maxt = 0.015 mint = 0.015 con = constitutive.IsoShellConstitutive(props, t=t, tNum=tnum) # Create a transformation object transform = elements.ShellNaturalTransform() # Create the element object element = elements.Quad4Shell(transform, con) # Set the elements elems = [ element ] creator.setElements(elems) # Create TACS Assembler object from the mesh loader assembler = creator.createTACS() # Create distributed matrix mat = assembler.createSchurMat() # stiffness matrix self._initialize_variables(assembler, mat) self.initialize(model.scenarios[0], model.bodies) return
def _initialize_variables(self, assembler=None, mat=None, pc=None, gmres=None, struct_id=None, thermal_index=0): """ Initialize the variables required for analysis and optimization using TACS. This initialization takes in optional TACSMat, TACSPc and TACSKsm objects for the solution procedure. The assembler object must be defined on the subset of structural processors. On all other processors it must be None. """ self.tacs_proc = False self.assembler = None self.res = None self.ans = None self.ext_force = None self.update = None self.mat = None self.pc = None self.gmres = None self.thermal_index = thermal_index self.struct_id = struct_id self.struct_X_vec = None self.struct_nnodes = None self.struct_X = None self.dvsenslist = [] self.svsenslist = [] self.xptsenslist = [] self.struct_rhs_vec = None self.psi_S = None self.ans_array = None self.func_grad = None self.vol = 1.0 if assembler is not None: self.tacs_proc = True self.mat = mat self.pc = pc self.gmres = gmres if mat is None: self.mat = assembler.createSchurMat() self.pc = TACS.Pc(self.mat) self.gmres = TACS.KSM(self.mat, self.pc, 30) elif pc is None: self.mat = mat self.pc = TACS.Pc(self.mat) self.gmres = TACS.KSM(self.mat, self.pc, 30) elif gmres is None: self.mat = mat self.pc = pc self.gmres = TACS.KSM(self.mat, self.pc, 30) self.assembler = assembler self.res = assembler.createVec() self.ans = assembler.createVec() self.ext_force = assembler.createVec() self.update = assembler.createVec() # Get and set the structural node locations self.struct_X_vec = assembler.createNodeVec() assembler.getNodes(self.struct_X_vec) self.struct_nnodes = len(self.struct_X_vec.getArray()) // 3 self.struct_X = np.zeros(3 * self.struct_nnodes, dtype=TACS.dtype) self.struct_X[:] = self.struct_X_vec.getArray()[:] self.dvsenslist = [] self.svsenslist = [] self.xptsenslist = [] for i in range(self.nfunc): self.dvsenslist.append(assembler.createDesignVec()) self.svsenslist.append(assembler.createVec()) self.xptsenslist.append(assembler.createNodeVec()) self.struct_rhs_vec = assembler.createVec() self.psi_S = [] for ifunc in range(self.nfunc): self.psi_S.append(self.assembler.createVec()) self.ans_array = assembler.createVec() self.func_grad = None # required for AverageTemp function, not sure if needed on # body level self.vol = 1.0 return