def test_fuse_boxes2(): """ Test of fusion function. It makes union of three face-adjacent boxes. Possibly it can make union of two non-intersecting boxes. """ mesh_name = "box_fuse_2" gen = gmsh.GeometryOCC(mesh_name, verbose=True) # create inner box box_1 = gen.box([20, 20, 20]) box_2 = gen.box([20, 20, 20]) box_3 = gen.box([20, 20, 20]) box_2.translate([0, 20, 0]) box_3.translate([0, 40, 0]) # make union of two non-intersecting boxes # box_fused = box_1.fuse(box_3) box_fused = box_1.fuse(box_2, box_3) assert box_fused.regions[0] == gmsh.Region.default_region[3] box_fused.set_region("box") # box_fused.mesh_step(1) all_obj = [box_fused] mesh_all = [*all_obj] gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_fracture(): # layer geometry object lg = LayerGeometry() # create interfaces top_iface = lg.add_interface(transform_z=(1.0, 0.0), elevation=0.0) fr_iface = lg.add_interface(transform_z=(1.0, 0.0), elevation=-1.0) bot_iface = lg.add_interface(transform_z=(1.0, 0.0), elevation=-2.0) # add region to layer geometry reg = lg.add_region(name="region_name", dim=RegionDim.bulk) # create decomposition decomp = PolygonDecomposition() pt1 = decomp.add_point((0.0, 0.0)) pt2 = decomp.add_point((10.0, 0.0)) pt3 = decomp.add_point((10.0, 10.0)) pt4 = decomp.add_point((0.0, 10.0)) decomp.add_line_for_points(pt1, pt2) decomp.add_line_for_points(pt2, pt3) decomp.add_line_for_points(pt3, pt4) decomp.add_line_for_points(pt4, pt1) res = decomp.get_last_polygon_changes() #assert res[0] == PolygonChange.add polygon = decomp.polygons[res[2]] decomp.set_attr(polygon, reg) # add region to layer geometry fr_reg = lg.add_region(name="fracture_region_name", dim=RegionDim.fracture) # create fracture decomposition fr_decomp = PolygonDecomposition() pt1 = fr_decomp.add_point((0.0, 0.0)) pt2 = fr_decomp.add_point((10.0, 0.0)) pt3 = fr_decomp.add_point((10.0, 10.0)) fr_decomp.add_line_for_points(pt1, pt2) fr_decomp.add_line_for_points(pt2, pt3) fr_decomp.add_line_for_points(pt3, pt1) res = fr_decomp.get_last_polygon_changes() #assert res[0] == PolygonChange.add polygon = fr_decomp.polygons[res[2]] fr_decomp.set_attr(polygon, fr_reg) # add layer to layer geometry lg.add_stratum_layer(decomp, top_iface, decomp, fr_iface) lg.add_fracture_layer(fr_decomp, fr_iface) lg.add_stratum_layer(decomp, fr_iface, decomp, bot_iface) # generate mesh file lg.filename_base = sandbox_fname("mesh_fracture", "") lg.init() lg.construct_brep_geometry() lg.make_gmsh_shape_dict() lg.distribute_mesh_step() lg.call_gmsh(mesh_step=0.0) lg.modify_mesh()
def test_extrude_rect(): """ Test extrusion of an rectangle. """ mesh_name = "extrude_rect" gen = gmsh.GeometryOCC(mesh_name, verbose=True) rect = gen.rectangle([2, 5]) prism_extrude = rect.extrude([1, 3, 4]) prism = prism_extrude[3] prism.set_region("prism").mesh_step(0.5) mesh_all = [prism] # gen.write_brep(mesh_name) gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_extrude_circle(): """ Test extrusion of an circle. """ mesh_name = "extrude_circle" gen = gmsh.GeometryOCC(mesh_name, verbose=True) circ = gen.disc(center=[2, 5, 1], rx=3, ry=3) circ_extrude = circ.extrude([2, 2, 2]) tube = circ_extrude[3] tube.set_region("tube").mesh_step(0.5) mesh_all = [tube] # gen.write_brep(mesh_name) gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_cylinder_discrete(): """ Test creating discrete cylinder (prism with regular n-point base), extrusion. """ mesh_name = "cylinder_discrete_mesh" gen = gmsh.GeometryOCC(mesh_name, verbose=True) r = 2.5 start = np.array([-10, -5, -15]) end = np.array([5, 15, 10]) axis = end - start center = (end + start) / 2 cyl = gen.cylinder_discrete(r, axis, center=center, n_points=12) cyl.mesh_step(1.0) mesh_all = [cyl] # gen.write_brep(mesh_name) gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_fuse_boxes(): """ Test of fusion function. It makes union of two intersection boxes. """ mesh_name = "box_fuse" gen = gmsh.GeometryOCC(mesh_name, verbose=True) # create inner box box_1 = gen.box([20, 20, 20]) box_2 = gen.box([10, 10, 40]) box_fused = box_2.fuse(box_1) box_fused.set_region("box") # box_fused.mesh_step(1) all_obj = [box_fused] mesh_all = [*all_obj] gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_extrude_polygon(): """ Test extrusion of an polygon. """ mesh_name = "extrude_polygon" gen = gmsh.GeometryOCC(mesh_name, verbose=True) # plane directional vectors vector u = np.array([1, 1, 0]) u = u / np.linalg.norm(u) v = np.array([0, 1, 1]) v = v / np.linalg.norm(v) #normal n = np.cross(u, v) n = n / np.linalg.norm(n) # add some points in the plane points = [] points.append(u) points.append(2 * u + 1 * v) points.append(5 * u + -2 * v) points.append(5 * u + 3 * v) points.append(4 * u + 5 * v) points.append(-2 * u + 3 * v) points.append(v) # create polygon polygon = gen.make_polygon(points) # trying to set mesh step directly to nodes # polygon = gen.make_polygon(points, 0.2) prism_extrude = polygon.extrude(3 * n) prism = prism_extrude[3] prism.set_region("prism").mesh_step_direct(0.5) mesh_all = [prism] # gen.write_brep(mesh_name) gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_revolve_square(): """ Test revolving a square. """ mesh_name = "revolve_square_mesh" gen = gmsh.GeometryOCC(mesh_name, verbose=True) square = gen.rectangle([2, 2], [5, 0, 0]) axis = [] center = [5, 10, 0] square_revolved = square.revolve(center=[5, 10, 0], axis=[1, 0, 0], angle=np.pi * 3 / 4) obj = square_revolved[3].mesh_step(0.5) mesh_all = [obj] # gen.write_brep(mesh_name) gen.make_mesh(mesh_all) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def apply_field(field, reference_fn, dim=2, tolerance=0.15, max_mismatch=5, mesh_name="field_mesh"): """ Create a mesh of dimension dim on a unit cube and compare element sizes to given reference funcion of coordinates. dim: Create mesh of that dimension. tolerance: maximum relative error of element sizes, actual size is max of edges, reference size is the field evaluated in the barycenter max_mismatch: maximum number of elements that could be over the tolerance """ model = gmsh.GeometryOCC(mesh_name) rec = model.rectangle([100, 100]) model.set_mesh_step_field(field) brep_fname = sandbox_fname(mesh_name, "brep") model.write_brep(brep_fname) model.mesh_options.CharacteristicLengthMin = 0.5 model.mesh_options.CharacteristicLengthMax = 100 model.make_mesh([rec], dim=dim) mesh_fname = sandbox_fname(mesh_name, "msh2") model.write_mesh(mesh_fname, gmsh.MeshFormat.msh2) # check ref_shape_edges = { 1: [(0, 1)], 2: [(0, 1), (0, 2), (1, 2)], 3: [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], } node_tags, coords, param_coords = gmsh_model.mesh.getNodes( dim=-1, returnParametricCoord=False) coords = np.reshape(coords, (-1, 3)) node_indices = {tag: idx for idx, tag in enumerate(node_tags)} assert coords.shape[0] == len(node_tags) ele_types, ele_tags, ele_node_tags = gmsh_model.mesh.getElements(dim=dim) assert len(ele_types) == 1 and len(ele_tags) == 1 and len( ele_node_tags) == 1 ele_tags = ele_tags[0] ele_node_tags = np.reshape(ele_node_tags[0], (-1, dim + 1)) n_mismatch = 0 max_rel_error = 0 for ele_tag, ele_nodes in zip(ele_tags, ele_node_tags): i_nodes = [node_indices[n_tag] for n_tag in ele_nodes] vertices = coords[i_nodes, :] edges = [ vertices[i, :] - vertices[j, :] for i, j in ref_shape_edges[dim] ] ele_size = np.max(np.linalg.norm(edges, axis=1)) barycenter = np.average(vertices, axis=0) ref_ele_size = reference_fn(barycenter) rel_error = abs(ele_size - ref_ele_size) / ref_ele_size max_rel_error = max(max_rel_error, rel_error) #print(f"ele {ele_tag}, size: {ele_size}, ref size: {ref_ele_size}, {rel_error}") if rel_error > tolerance: print( f"Size mismatch, ele {ele_tag}, size: {ele_size}, ref size: {ref_ele_size}, rel_err: {rel_error}" ) n_mismatch += 1 assert n_mismatch <= max_mismatch print(f"n_mismatch: {n_mismatch}, max n mismatch: {max_mismatch}") print(f"max rel error: {max_rel_error}") del model
def test_splitting(): """ In this test, we split the object (cylinder) into chosen number of parts. We should provide a function for this. Question is how to set the splitting plane, how to provide the axis in which we split the object. TODO: The main point is in the end, where we transform ObjectSet into list of ObjectSet, taking advantage of the simple problem.. We will have to use the symetric fragmentation and then select properly the parts... We should think of creating method for half-space defined by a plane.. """ mesh_name = "splitting" gen = gmsh.GeometryOCC(mesh_name, verbose=True) # tunnel_start = np.array([-50, -50, 10]) tunnel_start = np.array([0, 0, 0]) tunnel_end = np.array([50, 50, 10]) radius = 5 tunnel = gen.cylinder(radius, tunnel_end - tunnel_start, tunnel_start) # cutting box box_s = 50 # cutting plane between the cylinders split_plane = gen.rectangle([box_s, box_s]) # normal is in z-axis z = [0, 0, 1] # directional vector of the cylinder u_t = tunnel_end - tunnel_start u_t = u_t / np.linalg.norm(u_t) # normalize # axis of rotation axis = np.cross(z, u_t) axis = axis / np.linalg.norm(axis) # normalize angle = np.arccos(np.dot(u_t, z)) split_plane.rotate(axis=axis, angle=angle, center=[0, 0, 0]) splits = [] length_t = np.linalg.norm(tunnel_end - tunnel_start) n_parts = 5 # number of parts length_part = length_t / n_parts # length of a single part split_pos = tunnel_start + length_part * u_t for i in range(n_parts - 1): split = split_plane.copy().translate(split_pos) splits.append(split) split_pos = split_pos + length_part * u_t # tunnel_f = tunnel.fragment(*splits) tunnel_f = tunnel.fragment(*[s.copy() for s in splits]) # split fragmented ObjectSet into list of ObjectSets by dimtags tunnel_parts = [] for dimtag, reg in tunnel_f.dimtagreg(): tunnel_parts.append( gmsh.ObjectSet(gen, [dimtag], [gmsh.Region.default_region[3]])) def center_comparison(obj): center, mass = obj.center_of_mass() return np.linalg.norm(center - tunnel_start) # for t in tunnel: # print(center_comparison(t)) tunnel_parts.sort(reverse=False, key=center_comparison) # test setting mesh step size i = 0 delta = 0.4 for t in tunnel_parts: print(gen.model.getMass(*(t.dim_tags[0]))) t.mesh_step(0.6 + i * delta) i = i + 1 gen.make_mesh([*tunnel_parts, *splits]) gen.write_mesh(sandbox_fname(mesh_name, "msh2"), gmsh.MeshFormat.msh2)
def test_extrude_polygon(): """ Test extrusion of an polygon. BUG: Currently failing: - in this setting (set mesh step directly to nodes of polygon) it generates elements but writes empty mesh - when setting mesh step by getting boundary inside make_mesh, it fails """ gmsh.initialize() file_name = "extrude_polygon" gmsh.model.add(file_name) # plane directional vectors vector u = np.array([1, 1, 0]) u = u / np.linalg.norm(u) v = np.array([0, 1, 1]) v = v / np.linalg.norm(v) #normal n = np.cross(u, v) n = n / np.linalg.norm(n) # add some points in the plane points = [] points.append(u) points.append(2 * u + 1 * v) points.append(5 * u + -2 * v) points.append(5 * u + 3 * v) points.append(4 * u + 5 * v) points.append(-2 * u + 3 * v) points.append(v) point_tags = [gmsh.model.occ.addPoint(*p) for p in points] # point_tags = [gmsh.model.occ.addPoint(*p, meshSize=0.2) for p in points] lines = [ gmsh.model.occ.addLine(point_tags[i - 1], point_tags[i]) for i in range(len(points)) ] cl = gmsh.model.occ.addCurveLoop(lines) pol = gmsh.model.occ.addPlaneSurface([cl]) ext_dimtags = gmsh.model.occ.extrude([(2, pol)], *(3 * n)) tube_dimtags = [ext_dimtags[1]] gmsh.model.occ.synchronize() nodes = gmsh.model.getBoundary(tube_dimtags, combined=False, oriented=False, recursive=True) print(nodes) p_dimtags = [(0, tag) for tag in point_tags] gmsh.model.occ.mesh.setSize(p_dimtags, size=0.2) gmsh.model.occ.synchronize() # generate mesh, write to file and output number of entities that produced error # gmsh.option.setNumber("Mesh.CharacteristicLengthFromPoints", 0.2) # gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0) # gmsh.option.setNumber("Mesh.CharacteristicLengthExtendFromBoundary", 1) # gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.1) # gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 1.0) gmsh.model.mesh.generate(3) gmsh.model.mesh.removeDuplicateNodes() bad_entities = gmsh.model.mesh.getLastEntityError() print(bad_entities) # gmsh.fltk.run() gmsh.write(sandbox_fname(file_name, "msh2")) gmsh.finalize()