def create_forest(comm, depth, htarget): """ Create an initial forest for analysis and optimization. This code loads in the model, sets names, meshes the geometry and creates an OctForest from the mesh. The forest is populated with octrees with the specified depth. Args: comm (MPI_Comm): MPI communicator depth (int): Depth of the initial trees htarget (float): Target global element mesh size Returns: OctForest: Initial forest for topology optimization """ # Load the geometry model geo = TMR.LoadModel('../cantilever/cantilever.stp') # Mark the boundary condition faces verts = geo.getVertices() edges = geo.getEdges() faces = geo.getFaces() volumes = geo.getVolumes() faces[3].setName('fixed') faces[4].setSource(volumes[0], faces[5]) verts[4].setName('pt1') verts[3].setName('pt2') # Set the boundary conditions for the problem bcs = TMR.BoundaryConditions() bcs.addBoundaryCondition('fixed') # Create the mesh mesh = TMR.Mesh(comm, geo) # Set the meshing options opts = TMR.MeshOptions() # Create the surface mesh mesh.mesh(args.htarget, opts) # Create a model from the mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model topo = TMR.Topology(comm, model) # Create the quad forest and set the topology of the forest forest = TMR.OctForest(comm) forest.setTopology(topo) # Create the trees forest.createTrees(depth) return forest
def create_forest(comm, depth, htarget): """ Create an initial forest for analysis. and optimization This code loads in the model, sets names, meshes the geometry and creates a QuadForest from the mesh. The forest is populated with quadtrees with the specified depth. Args: comm (MPI_Comm): MPI communicator depth (int): Depth of the initial trees htarget (float): Target global element mesh size Returns: QuadForest: Initial forest for topology optimization """ # Load the geometry model geo = TMR.LoadModel('biclamped_traction.stp') # Mark the boundary condition faces verts = geo.getVertices() edges = geo.getEdges() faces = geo.getFaces() edges[1].setName('fixed') edges[9].setName('fixed') edges[4].setName('traction') # Create the mesh mesh = TMR.Mesh(comm, geo) # Set the meshing options opts = TMR.MeshOptions() # Create the surface mesh mesh.mesh(htarget, opts) # Create a model from the mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model topo = TMR.Topology(comm, model) # Create the quad forest and set the topology of the forest forest = TMR.QuadForest(comm) forest.setTopology(topo) # Set parameters for later usage forest.createTrees(depth) return forest
else: verts = [v1, v2, v3, v4] edges = [edge1, edge2, edge3, edge4] faces = [face] # Create the TMRModel geo = TMR.Model(verts, edges, faces) return geo geo = create_panel(100.0, 100.0, use_hole=True) # Create the mesh comm = MPI.COMM_WORLD mesh = TMR.Mesh(comm, geo) # Mesh the part opts = TMR.MeshOptions() opts.num_smoothing_steps = 20 opts.write_mesh_quality_histogram = 1 # Mesh the geometry with the given target size htarget = 10.0 mesh.mesh(htarget, opts=opts) mesh.writeToVTK('surface-mesh.vtk') # Create a model from the mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model
raise ValueError('File %s does not exist' % (filename)) # Set the value of the target length scale in the mesh htarget = args.htarget # Load the geometry model geo = TMR.LoadModel(filename) geo.writeModelToTecplot('tecplot_surfaces.dat') # Create a model by discarding the volumes verts = geo.getVertices() edges = geo.getEdges() faces = geo.getFaces() geo_new = TMR.Model(verts, edges, faces) # Create the new mesh mesh = TMR.Mesh(comm, geo_new) # Set the meshing options opts = TMR.MeshOptions() opts.frontal_quality_factor = 1.25 opts.num_smoothing_steps = 10 opts.write_mesh_quality_histogram = 1 opts.triangularize_print_iter = 50000 # Create the surface mesh mesh.mesh(htarget, opts) # Write the surface mesh to a file mesh.writeToVTK(args.output)
def create_3d_unstruct_mesh(n, AR, prob, ratio1, ratio2, hole_r, forced_portion, force_magnitude, MBB_bc_portion, loaded_thickness, ly): comm = MPI.COMM_WORLD # Create the egads context ctx = egads.context() # dimensions Lx = ly * AR Ly = ly h = ly parts = [] if prob == 'lbracket': # Create base x0 = [0, 0, 0] x1 = [Lx * ratio1, Ly * ratio2, h] B0 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1]) parts.append(ctx.makeTopology(egads.MODEL, children=[B0])) # Create arm 1 x0 = [0, Ly * ratio2, 0] x1 = [Lx * ratio1, Ly * (1 - ratio2), h] B1 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1]) parts.append(ctx.makeTopology(egads.MODEL, children=[B1])) # Create arm 2 x0 = [Lx * ratio1, 0, 0] x1 = [Lx * (1 - ratio1), Ly * ratio2, h] B2 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1]) # Create the cylinder cutout xc = Lx * (ratio1 + 1) * 0.5 yc = Ly * ratio2 * 0.5 x0 = [xc, yc, 0] x1 = [xc, yc, h] r = hole_r * Ly * ratio2 C1 = ctx.makeSolidBody(egads.CYLINDER, rdata=[x0, x1, r]) parts.append(B2.solidBoolean(C1, egads.SUBTRACTION)) else: # Create the box x0 = [0, 0, 0] x1 = [Lx, Ly, h] B1 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1]) # Create the cylinder cutout xc = Lx / 2 yc = Ly / 2 x0 = [xc, yc, 0] x1 = [xc, yc, h] r = hole_r * Ly C1 = ctx.makeSolidBody(egads.CYLINDER, rdata=[x0, x1, r]) # parts.append(ctx.makeTopology(egads.MODEL, children=[B1])) parts.append(B1.solidBoolean(C1, egads.SUBTRACTION)) # Create all of the models geos = [] for p in parts: geos.append(TMR.ConvertEGADSModel(p)) # Create the full list of vertices, edges, faces and volumes verts = [] edges = [] faces = [] vols = [] for geo in geos: verts.extend(geo.getVertices()) edges.extend(geo.getEdges()) faces.extend(geo.getFaces()) vols.extend(geo.getVolumes()) # Set all of the matching faces TMR.setMatchingFaces(geos) # Create the geometry geo = TMR.Model(verts, edges, faces, vols) # Create the new mesh mesh = TMR.Mesh(comm, geo) # Set the meshing options opts = TMR.MeshOptions() # opts.mesh_type_default = TMR.UNSTRUCTURED opts.write_mesh_quality_histogram = 1 opts.triangularize_print_iter = 50000 # Create the surface mesh htarget = ly / n mesh.mesh(htarget, opts) # Write the surface mesh to a file # mesh.writeToVTK('block.vtk', 'hex') # Create the model from the unstructured volume mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model topo = TMR.Topology(comm, model) # Create the quad forest and set the topology of the forest forest = TMR.OctForest(comm) forest.setTopology(topo) forest.createTrees() forest.balance(1) # Create the nodes forest.createNodes() # Get the mesh connectivity conn = forest.getMeshConn() nnodes = np.max(conn) + 1 nelems = len(conn) # Get the node locations X = forest.getPoints() # Set boundary conditions dof = -np.ones((nnodes, 3), dtype=int) geo_bc_tol = 1e-6 if prob == 'cantilever' or prob == 'michell': bc_x_max = geo_bc_tol bc_x_min = -geo_bc_tol bc_y_max = Ly + geo_bc_tol bc_y_min = -geo_bc_tol bc_z_max = h + geo_bc_tol bc_z_min = -geo_bc_tol ndof = 0 for i in range(nnodes): if (bc_x_min <= X[i, 0] <= bc_x_max and bc_y_min <= X[i, 1] <= bc_y_max and bc_z_min <= X[i, 2] <= bc_z_max): # This is the bc node pass else: dof[i, 0] = ndof ndof += 1 dof[i, 1] = ndof ndof += 1 dof[i, 2] = ndof ndof += 1 elif prob == 'MBB': bc1_x_max = geo_bc_tol bc1_x_min = -geo_bc_tol bc1_y_max = Ly + geo_bc_tol bc1_y_min = -geo_bc_tol bc1_z_max = h + geo_bc_tol bc1_z_min = -geo_bc_tol bc2_x_max = Lx + geo_bc_tol bc2_x_min = Lx * (1 - MBB_bc_portion) - geo_bc_tol bc2_y_max = geo_bc_tol + geo_bc_tol bc2_y_min = -geo_bc_tol bc2_z_max = h + geo_bc_tol bc2_z_min = -geo_bc_tol ndof = 0 for i in range(nnodes): if (bc1_x_min <= X[i, 0] <= bc1_x_max and bc1_y_min <= X[i, 1] <= bc1_y_max and bc1_z_min <= X[i, 2] <= bc1_z_max): # This is the bc node dof[i, 1] = ndof ndof += 1 elif (bc2_x_min <= X[i, 0] <= bc2_x_max and bc2_y_min <= X[i, 1] <= bc2_y_max and bc2_z_min <= X[i, 2] <= bc2_z_max): # This is also bc node dof[i, 0] = ndof ndof += 1 else: dof[i, 0] = ndof ndof += 1 dof[i, 1] = ndof ndof += 1 dof[i, 2] = ndof ndof += 1 elif prob == 'lbracket': bc_x_max = Lx * ratio1 + geo_bc_tol bc_x_min = -geo_bc_tol bc_y_max = Ly + geo_bc_tol bc_y_min = Ly - geo_bc_tol bc_z_max = h + geo_bc_tol bc_z_min = -geo_bc_tol ndof = 0 for i in range(nnodes): if (bc_x_min <= X[i, 0] <= bc_x_max and bc_y_min <= X[i, 1] <= bc_y_max and bc_z_min <= X[i, 2] <= bc_z_max): # This is the bc node pass else: dof[i, 0] = ndof ndof += 1 dof[i, 1] = ndof ndof += 1 dof[i, 2] = ndof ndof += 1 # Set loading force = np.zeros(ndof) geo_tol = 1e-6 if prob == 'cantilever': load_x_max = Lx + geo_tol load_x_min = Lx - geo_tol load_y_max = Ly * forced_portion + geo_tol load_y_min = -geo_tol load_z_max = 0.5 * h * (1 + loaded_thickness) load_z_min = 0.5 * h * (1 - loaded_thickness) force_dir = 1 force_scal = -1.0 elif prob == 'MBB': load_x_max = Lx * MBB_bc_portion + geo_tol load_x_min = -geo_tol load_y_max = Ly + geo_tol load_y_min = Ly - geo_tol load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol force_dir = 1 force_scal = -1.0 elif prob == 'michell': load_x_max = Lx + geo_tol load_x_min = Lx - geo_tol load_y_max = 0.5 * Ly * (1 + forced_portion) + geo_tol load_y_min = 0.5 * Ly * (1 - forced_portion) - geo_tol load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol force_dir = 1 force_scal = -1.0 elif prob == 'lbracket': load_x_max = Lx + geo_tol load_x_min = Lx - geo_tol load_y_max = Ly * ratio2 + geo_tol load_y_min = Ly * ratio2 * (1 - forced_portion) - geo_tol load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol force_dir = 1 force_scal = -1.0 nforce = 0 for i in range(nnodes): if (load_x_min <= X[i, 0] <= load_x_max and load_y_min <= X[i, 1] <= load_y_max and load_z_min <= X[i, 2] <= load_z_max): force[dof[i, force_dir]] = force_scal * force_magnitude nforce += 1 force /= nforce # for n in range(X.shape[0]): # print('node:{:4d} x:{:6f} y:{:6f} z:{:6f}'.format(n, X[n, 0], X[n, 1], X[n, 2])) # for ne in range(conn.shape[0]): # print('elem:{:4d} conn = [{:3d} {:3d} {:3d} {:3d}]'.format(ne, conn[ne,0], conn[ne,1], conn[ne,2], conn[ne,3])) return nelems, nnodes, ndof, conn, X, dof, force
def create_mesh(n, AR, prob, ratio1, ratio2, forced_portion, MBB_bc_portion, force_magnitude, use_concentrated_force, use_hole, hole_radius): Ly = 1.0 Lx = Ly*AR # Create tmr geometry object geo = create_geo(AR, prob, forced_portion, MBB_bc_portion, ratio1, ratio2, use_hole, hole_radius) # Create the mesh comm = MPI.COMM_WORLD mesh = TMR.Mesh(comm, geo) # Mesh the part opts = TMR.MeshOptions() opts.frontal_quality_factor = 1.25 opts.num_smoothing_steps = 20 opts.write_mesh_quality_histogram = 1 # Mesh the geometry with the given target size htarget = Ly / n mesh.mesh(htarget, opts=opts) # Create a model from the mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model topo = TMR.Topology(comm, model) # Create the quad forest and set the topology of the forest forest = TMR.QuadForest(comm) forest.setTopology(topo) # Create random trees and balance the mesh. Print the output file forest.createTrees() forest.balance(1) # Create the nodes forest.createNodes() # Get the mesh connectivity conn = forest.getMeshConn() # Get the node locations X = forest.getPoints() # Set the nodal positions using only the x and y locations X = np.array(X[:,:2]) # Get the nodes with the specified name if prob == 'cantilever': bcs = forest.getNodesWithName('5') elif prob == 'MBB': bc1 = forest.getNodesWithName('6') bc2 = forest.getNodesWithName('2') elif prob == 'michell': bcs = forest.getNodesWithName('6') elif prob == 'lbracket': bcs = forest.getNodesWithName('6') # Create the vars array with the number of nodes nnodes = np.max(conn)+1 dof = np.zeros((nnodes, 2), dtype=int) # Set the vars to a negative index where we have a constraint if prob == 'MBB': # If it is MBB problem, we only fix x degree of freedom at left edge dof[bc1, 0] = -1 dof[bc2, 1] = -1 else: dof[bcs, :] = -1 # Assign variables to the nodes ndof = 0 for i in range(nnodes): if dof[i,0] >= 0: dof[i,0] = ndof ndof += 1 if dof[i,1] >= 0: dof[i,1] = ndof ndof += 1 # Set up the force vector force = np.zeros(ndof) # Assign the force vector if prob == 'cantilever': if use_concentrated_force: south_east_corner_node = -1 xpos = X[0, 0] ypos = X[0, 0] for i in range(nnodes): if X[i, 0] >= xpos and X[i, 1] <= ypos: south_east_corner_node = i xpos = X[i, 0] ypos = X[i, 1] force[dof[south_east_corner_node, 1]] = -force_magnitude else: quads_on_edge = forest.getQuadsWithName('2') for q in quads_on_edge: if q.info < 2: n1 = q.info n2 = q.info + 2 else: n1 = q.info//2 n2 = n1 + 1 v1 = dof[conn[q.face, n1], 1] v2 = dof[conn[q.face, n2], 1] force[v1] = -force_magnitude force[v2] = -force_magnitude force[:] /= np.count_nonzero(force) elif prob == 'michell': if use_concentrated_force: distance = Lx**2 + Ly**2 xtarget = Lx ytarget = Ly / 2 middle_node = -1 for i in range(nnodes): xpos = X[i, 0] ypos = X[i, 1] if (xpos-xtarget)**2 + (ypos-ytarget)**2 <= distance: middle_node = i distance = (xpos-xtarget)**2 + (ypos-ytarget)**2 force[dof[middle_node, 1]] = -force_magnitude else: quads_on_edge = forest.getQuadsWithName('3') for q in quads_on_edge: if q.info < 2: n1 = q.info n2 = q.info + 2 else: n1 = q.info//2 n2 = n1 + 1 v1 = dof[conn[q.face, n1], 1] v2 = dof[conn[q.face, n2], 1] force[v1] = -force_magnitude force[v2] = -force_magnitude force[:] /= np.count_nonzero(force) elif prob == 'MBB': if use_concentrated_force: distance = Lx**2 + Ly**2 xtarget = 0 ytarget = Ly north_west_node = -1 for i in range(nnodes): xpos = X[i, 0] ypos = X[i, 1] if (xpos-xtarget)**2 + (ypos-ytarget)**2 <= distance: north_west_node = i distance = (xpos-xtarget)**2 + (ypos-ytarget)**2 force[dof[north_west_node, 1]] = -force_magnitude else: quads_on_edge = forest.getQuadsWithName('5') for q in quads_on_edge: if q.info < 2: n1 = q.info n2 = q.info + 2 else: n1 = q.info//2 n2 = n1 + 1 v1 = dof[conn[q.face, n1], 1] v2 = dof[conn[q.face, n2], 1] force[v1] = -force_magnitude force[v2] = -force_magnitude force[:] /= np.count_nonzero(force) elif prob == 'lbracket': if use_concentrated_force: distance = Lx**2 + Ly**2 xtarget = Lx ytarget = Ly*ratio2 middle_node = -1 for i in range(nnodes): xpos = X[i, 0] ypos = X[i, 1] if (xpos-xtarget)**2 + (ypos-ytarget)**2 <= distance: middle_node = i distance = (xpos-xtarget)**2 + (ypos-ytarget)**2 force[dof[middle_node, 1]] = -force_magnitude else: quads_on_edge = forest.getQuadsWithName('3') for q in quads_on_edge: if q.info < 2: n1 = q.info n2 = q.info + 2 else: n1 = q.info//2 n2 = n1 + 1 v1 = dof[conn[q.face, n1], 1] v2 = dof[conn[q.face, n2], 1] force[v1] = -force_magnitude force[v2] = -force_magnitude force[:] /= np.count_nonzero(force) nelems = len(conn) return nelems, nnodes, ndof, conn, X, dof, force
def create_forest(comm, depth, htarget): ''' Load the 3D step file and convert it to a 2D model ''' geo = TMR.LoadModel('battery_3d.step') verts = [] edges = [] faces = [] all_faces = geo.getFaces() # Select only the facs on one face faces.append(all_faces[3]) # The structure's face faces.extend(all_faces[(len(all_faces) - 9):len(all_faces)]) # The face of the 9 batteries # Add only the verts and edges associated with the faces that we selected vert_ids = [] edge_ids = [] for f in faces: num_loops = f.getNumEdgeLoops() for i in range(num_loops): el = f.getEdgeLoop(i) edge_list, _ = el.getEdgeLoop() for e in edge_list: if e.getEntityId() not in edge_ids: edges.append(e) edge_ids.append(e.getEntityId()) v1, v2 = e.getVertices() if v1.getEntityId() not in vert_ids: verts.append(v1) vert_ids.append(v1.getEntityId()) if v2.getEntityId() not in vert_ids: verts.append(v2) vert_ids.append(v2.getEntityId()) # Create the new 2D geometry model geo = TMR.Model(verts, edges, faces) # Name the faces that we need to use faces[7].setName('battery_0') # Corner battery face faces[8].setName('battery_1') # Adjacent battery faces[1].setName('battery_2') # Diagonal battery faces[2].setName('battery') # All the other batteries faces[3].setName('battery') faces[4].setName('battery') faces[5].setName('battery') faces[6].setName('battery') faces[9].setName('battery') faces[0].setName('aluminum') # Create the mesh object mesh = TMR.Mesh(comm, geo) # Mesh the part opts = TMR.MeshOptions() opts.write_mesh_quality_histogram = 1 # Mesh the geometry with the given target size mesh.mesh(htarget, opts=opts) # mesh.writeToVTK('battery_mesh.vtk') # Create a model from the mesh model = mesh.createModelFromMesh() # Create the corresponding mesh topology from the mesh-model topo = TMR.Topology(comm, model) # Create the quad forest and set the topology of the forest forest = TMR.QuadForest(comm) forest.setTopology(topo) forest.createTrees(depth) return forest