Пример #1
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #2
0
def test_greet_no_volume():
    """
    Problem: Does not generate volume mesh.
    select_by_intersect probably fails, in comparison to simple cut(*tunnel_f)

    The cutting of the tunnels is a dead end, however, we do not understand the behaviour above.
    """
    mesh_name = "greet_no_volume"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    geom = geometry()

    # create inner box
    box_inner = gen.box(geom['inner_box']["size"])
    # create tunnel
    box_size = np.array(geom['outer_box']["size"])
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])
    side_y = gen.rectangle([box_size[0], box_size[2]]).rotate([-1, 0, 0],
                                                              np.pi / 2)
    tunnel_split = dict(start=side_y.copy().translate([0, tunnel_start[1], 0]),
                        mid=side_y.copy().translate([0, tunnel_mid[1], 0]),
                        end=side_y.copy().translate([0, tunnel_end[1], 0]))

    tunnel_1_c, tunnel_box_1 = create_cylinder(gen, geom['tunnel_1'], 0.2)
    tunnel_1_x = tunnel_1_c.copy().intersect(tunnel_box_1)

    tunnel_2_c, tunnel_box_2 = create_cylinder(gen, geom['tunnel_2'], 0.2)
    tunnel_2_x = tunnel_2_c.copy().intersect(tunnel_box_2)

    splits = [tunnel_split["start"].copy(), tunnel_split["end"].copy()]
    frag = gen.fragment(box_inner.copy(), tunnel_1_c, tunnel_2_c, *splits)

    tunnel_1_f = frag[1].select_by_intersect(tunnel_1_x)
    tunnel_2_f = frag[2].select_by_intersect(tunnel_2_x)
    tunnel_f = [tunnel_1_f, tunnel_2_f]

    box_inner_cut = box_inner.cut(*tunnel_f)
    box_inner_reg = frag[0].select_by_intersect(box_inner_cut)
    # box_inner_reg = box_inner.cut(tunnel_box_1)
    box_inner_reg.mesh_step(4.0)

    box_all = []
    b_box_inner = box_inner_reg.get_boundary()
    b_tunnel = b_box_inner.select_by_intersect(*tunnel_f)
    box_all.append(
        b_tunnel.modify_regions("." + geom['inner_box']["name"] + "_tunnel"))

    box_all.extend([box_inner_reg])

    b_tunnel.mesh_step(1.0)

    mesh_all = [*box_all]

    print("Generating mesh...")
    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")
    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #3
0
def mesh_from_brep(brep_file, mesh_file, project_conf, inv_par):
    if project_conf.method == GenieMethod.ERT:
        data = pg.DataContainerERT("input_snapped.dat", removeInvalid=False)
    else:
        data = pg.DataContainer("input_snapped.dat",
                                sensorTokens='s g',
                                removeInvalid=False)

    el_pos = []
    for i in range(len(data.sensorPositions())):
        pos = data.sensorPosition(i)
        pos = np.array([pos[0], pos[1], pos[2]])
        el_pos.append(pos)

    model = gmsh.GeometryOCC("model_name")
    compound = model.import_shapes(brep_file, highestDimOnly=False)
    points = [model.point(pos).tags[0] for pos in el_pos]
    dist = field.distance_nodes(points)
    f_distance = field.threshold(dist,
                                 lower_bound=(inv_par.elementSize_d,
                                              inv_par.elementSize_d),
                                 upper_bound=(inv_par.elementSize_D,
                                              inv_par.elementSize_H))
    model.set_mesh_step_field(f_distance)
    model.mesh_options.CharacteristicLengthMin = 0.1
    model.mesh_options.CharacteristicLengthMax = 100
    model.make_mesh([compound])
    model.write_mesh(mesh_file, gmsh.MeshFormat.msh2)
Пример #4
0
def test_exceptions():
    """
    Test exceptions.
    Using the broken remove_duplicate_entities() function for testing.
    """
    mesh_name = "square_mesh"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True, gmsh_exceptions=True)

    square = gen.rectangle([2, 2], [5, 0, 0])
    with pytest.raises(gmsh_exceptions.FragmentationError,
                       match=r".* duplicate .*"):
        gen.remove_duplicate_entities()

    gen.gmsh_exceptions = False
    # we cannot check warning type due to inline creation of the warning type in gmsh_exceptions.make_warning
    with pytest.warns(Warning, match=r".* duplicate .*"):
        gen.remove_duplicate_entities()
Пример #5
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #6
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #7
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #8
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #9
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #10
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
Пример #11
0
def make_mesh(config_dict, fractures, mesh_name, mesh_file):
    geom = config_dict["geometry"]
    fracture_mesh_step = geom['fracture_mesh_step']
    dimensions = geom["box_dimensions"]
    well_z0, well_z1 = geom["well_openning"]
    well_length = well_z1 - well_z0
    well_r = geom["well_effective_radius"]
    well_dist = geom["well_distance"]
    print("load gmsh api")

    factory = gmsh.GeometryOCC(mesh_name, verbose=True)
    gopt = gmsh_options.Geometry()
    gopt.Tolerance = 0.0001
    gopt.ToleranceBoolean = 0.001
    # gopt.MatchMeshTolerance = 1e-1

    # Main box
    box = factory.box(dimensions).set_region("box")
    side_z = factory.rectangle([dimensions[0], dimensions[1]])
    side_y = factory.rectangle([dimensions[0], dimensions[2]])
    side_x = factory.rectangle([dimensions[2], dimensions[1]])
    sides = dict(
        side_z0=side_z.copy().translate([0, 0, -dimensions[2] / 2]),
        side_z1=side_z.copy().translate([0, 0, +dimensions[2] / 2]),
        side_y0=side_y.copy().translate([0, 0, -dimensions[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        side_y1=side_y.copy().translate([0, 0, +dimensions[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        side_x0=side_x.copy().translate([0, 0, -dimensions[0] / 2]).rotate([0, 1, 0], np.pi / 2),
        side_x1=side_x.copy().translate([0, 0, +dimensions[0] / 2]).rotate([0, 1, 0], np.pi / 2)
    )
    for name, side in sides.items():
        side.modify_regions(name)

    b_box = box.get_boundary().copy()

    # two vertical cut-off wells, just permeable part
    left_center = [-well_dist/2, 0, 0]
    right_center = [+well_dist/2, 0, 0]
    left_well = factory.cylinder(well_r, axis=[0, 0, well_z1 - well_z0]) \
        .translate([0, 0, well_z0]).translate(left_center)
    right_well = factory.cylinder(well_r, axis=[0, 0, well_z1 - well_z0]) \
        .translate([0, 0, well_z0]).translate(right_center)
    b_right_well = right_well.get_boundary()
    b_left_well = left_well.get_boundary()

    print("n fractures:", len(fractures))
    fractures = create_fractures_rectangles(factory, fractures, factory.rectangle())
    #fractures = create_fractures_polygons(factory, fractures)
    fractures_group = factory.group(*fractures)
    #fractures_group = fractures_group.remove_small_mass(fracture_mesh_step * fracture_mesh_step / 10)

    # drilled box and its boundary
    box_drilled = box.cut(left_well, right_well)

    # fractures, fragmented, fractures boundary
    print("cut fractures by box without wells")
    fractures_group = fractures_group.intersect(box_drilled.copy())
    print("fragment fractures")
    box_fr, fractures_fr = factory.fragment(box_drilled, fractures_group)
    print("finish geometry")
    b_box_fr = box_fr.get_boundary()
    b_left_r = b_box_fr.select_by_intersect(b_left_well).set_region(".left_well")
    b_right_r = b_box_fr.select_by_intersect(b_right_well).set_region(".right_well")

    box_all = []
    for name, side_tool in sides.items():
        isec = b_box_fr.select_by_intersect(side_tool)
        box_all.append(isec.modify_regions("." + name))
    box_all.extend([box_fr, b_left_r, b_right_r])

    b_fractures = factory.group(*fractures_fr.get_boundary_per_region())
    b_fractures_box = b_fractures.select_by_intersect(b_box).modify_regions("{}_box")
    b_fr_left_well = b_fractures.select_by_intersect(b_left_well).modify_regions("{}_left_well")
    b_fr_right_well = b_fractures.select_by_intersect(b_right_well).modify_regions("{}_right_well")
    b_fractures = factory.group(b_fr_left_well, b_fr_right_well, b_fractures_box)
    mesh_groups = [*box_all, fractures_fr, b_fractures]

    print(fracture_mesh_step)
    #fractures_fr.set_mesh_step(fracture_mesh_step)

    factory.keep_only(*mesh_groups)
    factory.remove_duplicate_entities()
    factory.write_brep()

    min_el_size = fracture_mesh_step / 10
    fracture_el_size = np.max(dimensions) / 20
    max_el_size = np.max(dimensions) / 8


    fracture_el_size = gmsh_field.constant(fracture_mesh_step, 10000)
    frac_el_size_only = gmsh_field.restrict(fracture_el_size, fractures_fr, add_boundary=True)
    gmsh_field.set_mesh_step_field(frac_el_size_only)

    mesh = gmsh_options.Mesh()
    #mesh.Algorithm = options.Algorithm2d.MeshAdapt # produce some degenerated 2d elements on fracture boundaries ??
    #mesh.Algorithm = options.Algorithm2d.Delaunay
    #mesh.Algorithm = options.Algorithm2d.FrontalDelaunay
    #mesh.Algorithm3D = options.Algorithm3d.Frontal
    #mesh.Algorithm3D = options.Algorithm3d.Delaunay
    mesh.ToleranceInitialDelaunay = 0.01
    #mesh.ToleranceEdgeLength = fracture_mesh_step / 5
    mesh.CharacteristicLengthFromPoints = True
    mesh.CharacteristicLengthFromCurvature = True
    mesh.CharacteristicLengthExtendFromBoundary = 2
    mesh.CharacteristicLengthMin = min_el_size
    mesh.CharacteristicLengthMax = max_el_size
    mesh.MinimumCirclePoints = 6
    mesh.MinimumCurvePoints = 2


    #factory.make_mesh(mesh_groups, dim=2)
    factory.make_mesh(mesh_groups)
    factory.write_mesh(format=gmsh.MeshFormat.msh2)
    os.rename(mesh_name + ".msh2", mesh_file)
Пример #12
0
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
Пример #13
0
def test_empty_mesh():
    """
    Problem: Even though gmsh reports errors, it creates mesh with no elements.
    See seg fault problem below...

    The fragmentation of the tunnels is a dead end, however, we do not understand the behaviour above.
    """
    mesh_name = "greet_empty_mesh"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    geom = geometry()

    # create inner box
    # box_inner = create_box(gen, geometry_dict['inner_box'])

    # create tunnel
    box_size = np.array(geom['outer_box']["size"])
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])
    side_y = gen.rectangle([box_size[0], box_size[2]]).rotate([-1, 0, 0],
                                                              np.pi / 2)
    tunnel_split = dict(start=side_y.copy().translate([0, tunnel_start[1], 0]),
                        mid=side_y.copy().translate([0, tunnel_mid[1], 0]),
                        end=side_y.copy().translate([0, tunnel_end[1], 0]))

    tunnel_1_c, tunnel_box_1 = create_cylinder(gen, geom['tunnel_1'], 0.2)
    tunnel_1_x = tunnel_1_c.copy().intersect(tunnel_box_1)

    tunnel_2_c, tunnel_box_2 = create_cylinder(gen, geom['tunnel_2'], 0.2)
    tunnel_2_x = tunnel_2_c.copy().intersect(tunnel_box_2)

    tunnel_1_s, tunnel_2_s, s1, s3 = gen.fragment(
        tunnel_1_c.copy(),
        tunnel_2_c.copy(),
        tunnel_split["start"].copy(),
        # tunnel_split["mid"].copy(),
        tunnel_split["end"].copy())

    tunnel_1 = tunnel_1_s.select_by_intersect(tunnel_1_x)
    tunnel_2 = tunnel_2_s.select_by_intersect(tunnel_2_x)
    tunnel_1.set_region("t1")
    tunnel_2.set_region("t2")

    # box_inner_reg = box_inner.cut(*tunnel)

    # ENDS WITH SEG FAULT !!!!!!!!!!!!!!!!!!!!!!!!!!!
    # tunnel_1.mesh_step(1.5)
    # tunnel_2.mesh_step(1.5)

    # ends normally, but with empty mesh !!!!!!!!!!!!!!!!!!!!!!!!!!!
    tunnel_1_s.mesh_step(1.5)
    tunnel_2_s.mesh_step(1.5)

    mesh_all = [tunnel_1, tunnel_2]

    # gen.write_brep()
    print("Generating mesh...")
    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")
    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #14
0
def make_mesh(config_dict, fractures, mesh_name, mesh_file):
    geom = config_dict["geometry"]
    fracture_mesh_step = geom['fracture_mesh_step']
    dimensions = geom["box_dimensions"]
    # well_z0, well_z1 = geom["well_openning"]
    # well_length = well_z1 - well_z0
    # well_r = geom["well_effective_radius"]
    # well_dist = geom["well_distance"]

    mtr = geom["main_tunnel_radius"]
    mtw = geom["main_tunnel_width"]
    mtl = geom["main_tunnel_length"]

    st_r = geom["lateral_tunnel_radius"]
    stw = geom["lateral_tunnel_width"]
    stl = geom["lateral_tunnel_length"]
    # small_tunnel_passage_width = geom["lateral_tunnel_passage_width"]

    br = geom["borehole_radius"]
    bl = geom["borehole_length"]
    bd = geom["borehole_distance"]

    factory = gmsh.GeometryOCC(mesh_name, verbose=True)
    gopt = options.Geometry()
    gopt.Tolerance = 0.0001
    gopt.ToleranceBoolean = 0.001
    # gopt.MatchMeshTolerance = 1e-1

    # Main box
    box = factory.box(dimensions).set_region("box")
    side_z = factory.rectangle([dimensions[0], dimensions[1]])
    side_y = factory.rectangle([dimensions[0], dimensions[2]])
    side_x = factory.rectangle([dimensions[2], dimensions[1]])
    sides = dict(
        side_z0=side_z.copy().translate([0, 0, -dimensions[2] / 2]),
        side_z1=side_z.copy().translate([0, 0, +dimensions[2] / 2]),
        side_y0=side_y.copy().translate([0, 0, -dimensions[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        side_y1=side_y.copy().translate([0, 0, +dimensions[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        side_x0=side_x.copy().translate([0, 0, -dimensions[0] / 2]).rotate([0, 1, 0], np.pi / 2),
        side_x1=side_x.copy().translate([0, 0, +dimensions[0] / 2]).rotate([0, 1, 0], np.pi / 2)
    )
    for name, side in sides.items():
        side.modify_regions(name)

    b_box = box.get_boundary().copy()

    # # two vertical cut-off wells, just permeable part
    # left_center = [-well_dist/2, 0, 0]
    # right_center = [+well_dist/2, 0, 0]

    # main tunnel
    main_tunnel_block = factory.box([mtw, mtl, mtr])

    y_shift = math.sqrt(mtr * mtr - 0.25 * mtw * mtw) - mtr / 2
    main_tunnel_block_tmp = main_tunnel_block.copy().translate([0, 0, mtr])
    main_tunnel_cylinder_tmp = factory.cylinder(mtr, axis=[0, mtl, 0]).translate([0, -mtl / 2, -y_shift])
    main_tunnel_cylinder = main_tunnel_block_tmp.intersect(main_tunnel_cylinder_tmp)

    # lateral part of main tunnel
    y_shift_2 = math.sqrt(st_r * st_r - 0.25 * stw * stw) - st_r / 2

    small_tunnel_block = factory.box([stl, stw, st_r])
    small_tunnel_block_tmp = small_tunnel_block.copy().translate([0, 0, st_r])
    small_tunnel_cylinder_tmp = factory.cylinder(st_r, axis=[stl, 0, 0])\
        .translate([-stl / 2, 0, -y_shift_2])
    small_tunnel_cylinder = small_tunnel_block_tmp.intersect(small_tunnel_cylinder_tmp)

    lateral_tunnel_part_1 = factory.group(small_tunnel_block, small_tunnel_cylinder) \
        .translate([stl / 2, 0, 0])
    lateral_tunnel_part_2 = lateral_tunnel_part_1.copy().translate([0, bd, 0])
    lateral_tunnel_part_3 = lateral_tunnel_part_1.copy().translate([0, -bd, 0])
    # lateral_tunnel_part = factory.group(lateral_tunnel_part_1, lateral_tunnel_part_2)

    # main tunnel with lateral parts
    right_well = main_tunnel_block.fuse(main_tunnel_cylinder, lateral_tunnel_part_1, lateral_tunnel_part_2,\
                                        lateral_tunnel_part_3).translate([-bl/2, 0, 0])

    # horizontal boreholes
    # right_well_1 = factory.cylinder(br, axis=[bl, 0, 0]).translate([stl, 0, 0])
    # right_well_2 = right_well_1.copy().translate([0, 0, 20])
    # # right_well = factory.group(right_well_1, right_well_2).translate([-30, 0, 0])

    left_well_1 = factory.cylinder(br, axis=[bl, 0, 0]).translate([stl, 0, 0])
    left_well_2 = left_well_1.copy().translate([0, bd, 0])
    left_well_3 = left_well_1.copy().translate([0, -bd, 0])
    left_well = left_well_1.fuse(left_well_2, left_well_3).translate([-bl/2, 0, 0])

    b_right_well = right_well.get_boundary()
    b_left_well = left_well.get_boundary()

    print("n fractures:", len(fractures))
    fractures = process.create_fractures_rectangles(factory, fractures, factory.rectangle())
    # fractures = create_fractures_polygons(factory, fractures)
    fractures_group = factory.group(*fractures)
    # fractures_group = fractures_group.remove_small_mass(fracture_mesh_step * fracture_mesh_step / 10)

    # drilled box and its boundary
    box_drilled = box.cut(left_well, right_well)

    # fractures, fragmented, fractures boundary
    print("cut fractures by box without wells")
    fractures_group = fractures_group.intersect(box_drilled.copy())
    print("fragment fractures")
    box_fr, fractures_fr = factory.fragment(box_drilled, fractures_group)
    print("finish geometry")
    b_box_fr = box_fr.get_boundary()
    b_left_r = b_box_fr.select_by_intersect(b_left_well).set_region(".boreholes")
    b_right_r = b_box_fr.select_by_intersect(b_right_well).set_region(".main_tunnel")

    box_all = []
    for name, side_tool in sides.items():
        isec = b_box_fr.select_by_intersect(side_tool)
        box_all.append(isec.modify_regions("." + name))
    box_all.extend([box_fr, b_left_r, b_right_r])

    b_fractures = factory.group(*fractures_fr.get_boundary_per_region())
    b_fractures_box = b_fractures.select_by_intersect(b_box).modify_regions("{}_box")
    b_fr_left_well = b_fractures.select_by_intersect(b_left_well).modify_regions("{}_boreholes")
    b_fr_right_well = b_fractures.select_by_intersect(b_right_well).modify_regions("{}_main_tunnel")
    b_fractures = factory.group(b_fractures_box, b_fr_left_well, b_fr_right_well)
    mesh_groups = [*box_all, fractures_fr, b_fractures]

    print(fracture_mesh_step)
    # fractures_fr.set_mesh_step(fracture_mesh_step)

    factory.keep_only(*mesh_groups)
    factory.remove_duplicate_entities()
    factory.write_brep()

    min_el_size = fracture_mesh_step / 10
    fracture_el_size = np.max(dimensions) / 20
    max_el_size = np.max(dimensions) / 8

    fracture_el_size = field.constant(fracture_mesh_step, 10000)
    frac_el_size_only = field.restrict(fracture_el_size, fractures_fr, add_boundary=True)
    field.set_mesh_step_field(frac_el_size_only)

    mesh = options.Mesh()
    # mesh.Algorithm = options.Algorithm2d.MeshAdapt # produce some degenerated 2d elements on fracture boundaries ??
    # mesh.Algorithm = options.Algorithm2d.Delaunay
    # mesh.Algorithm = options.Algorithm2d.FrontalDelaunay
    # mesh.Algorithm3D = options.Algorithm3d.Frontal
    # mesh.Algorithm3D = options.Algorithm3d.Delaunay
    mesh.ToleranceInitialDelaunay = 0.01
    # mesh.ToleranceEdgeLength = fracture_mesh_step / 5
    mesh.CharacteristicLengthFromPoints = True
    mesh.CharacteristicLengthFromCurvature = True
    mesh.CharacteristicLengthExtendFromBoundary = 2
    mesh.CharacteristicLengthMin = min_el_size
    mesh.CharacteristicLengthMax = max_el_size
    mesh.MinimumCirclePoints = 6
    mesh.MinimumCurvePoints = 2

    # factory.make_mesh(mesh_groups, dim=2)
    factory.make_mesh(mesh_groups)
    factory.write_mesh(format=gmsh.MeshFormat.msh2)
    os.rename(mesh_name + ".msh2", mesh_file)
Пример #15
0
def test_empty_mesh():
    """
    Problem: Even though gmsh reports errors, it creates mesh with no elements.
    See seg fault problem below...

    The fragmentation of the tunnels is a dead end, however, we do not understand the behaviour above.

    JB: I can not reproduce seg faults but the meshing problem comes from trying to mesh a rounded tip
    of the two tunnels intersection, that may leads to creating to overleaping surface elements on different
    surfaces.
    """
    os.chdir(this_source_dir)
    mesh_name = "greet_empty_mesh"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    geom = geometry()

    # create inner box
    # box_inner = create_box(gen, geometry_dict['inner_box'])

    # create tunnel
    box_size = np.array(geom['outer_box']["size"])
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])
    side_y = gen.rectangle([box_size[0], box_size[2]]).rotate([-1, 0, 0],
                                                              np.pi / 2)
    tunnel_split = dict(start=side_y.copy().translate([0, tunnel_start[1], 0]),
                        mid=side_y.copy().translate([0, tunnel_mid[1], 0]),
                        end=side_y.copy().translate([0, tunnel_end[1], 0]))

    tunnel_1_c, tunnel_box_1 = create_cylinder(gen, geom['tunnel_1'], 0.2)
    tunnel_1_x = tunnel_1_c.copy().intersect(tunnel_box_1)

    tunnel_2_c, tunnel_box_2 = create_cylinder(gen, geom['tunnel_2'], 0.2)
    tunnel_2_x = tunnel_2_c.copy().intersect(tunnel_box_2)

    tunnel_1_s, tunnel_2_s, s1, s3 = gen.fragment(
        tunnel_1_c.copy(),
        tunnel_2_c.copy(),
        tunnel_split["start"].copy(),
        # tunnel_split["mid"].copy(),
        tunnel_split["end"].copy())

    tunnel_1 = tunnel_1_s.select_by_intersect(tunnel_1_x)
    tunnel_2 = tunnel_2_s.select_by_intersect(tunnel_2_x)
    tunnel_1.set_region("t1")
    tunnel_2.set_region("t2")

    # box_inner_reg = box_inner.cut(*tunnel)

    # ENDS WITH SEG FAULT !!!!!!!!!!!!!!!!!!!!!!!!!!!
    # tunnel_1.mesh_step(1.5)
    # tunnel_2.mesh_step(1.5)

    # ends normally, but with empty mesh !!!!!!!!!!!!!!!!!!!!!!!!!!!
    tunnel_1_s.mesh_step(1.5)
    tunnel_2_s.mesh_step(1.5)

    mesh_all = [tunnel_1, tunnel_2]

    gen.write_brep()
    print("Generating mesh...")

    # Occasionally ends with error:
    # Exception: Invalid boundary mesh (overlapping facets) on surface 39 surface 40
    #   ...
    #   Info    : Tetrahedrizing 744 nodes...
    #   Info    : Done tetrahedrizing 752 nodes (Wall 0.0108547s, CPU 0.010854s)
    #   Info    : Reconstructing mesh...
    #   Info    :  - Creating surface mesh
    #   Info    : Found two overlapping facets.
    #   Info    :   1st: [26, 25, 64] #39
    #   Info    :   2nd: [26, 25, 64] #40
    #   ----------------------------- Captured stderr call -----------------------------
    #   Warning : 16 elements remain invalid in surface 11
    #   Warning : 18 elements remain invalid in surface 25
    #   Warning : 12 elements remain invalid in surface 41
    #   Warning : 18 elements remain invalid in surface 45
    #   Warning : 66 elements remain invalid in surface 25
    #   Warning : 32 elements remain invalid in surface 45
    #   Error   : Invalid boundary mesh (overlapping facets) on surface 39 surface 40

    # Sucessfull test run:
    # Info    : Found volume 6
    # Info    : It. 0 - 0 nodes created - worst tet radius 1.14137 (nodes removed 0 0)
    # Info    : 3D refinement terminated (2567 nodes total):
    # Info    :  - 0 Delaunay cavities modified for star shapeness
    # Info    :  - 0 nodes could not be inserted
    # Info    :  - 657 tetrahedra created in 0.000683932 sec. (960621 tets/s)
    # Info    : Tetrahedrizing 585 nodes...
    # Info    : Done tetrahedrizing 593 nodes (Wall 0.00824587s, CPU 0.008245s)
    # Info    : Reconstructing mesh...
    # Info    :  - Creating surface mesh
    # Info    :  - Identifying boundary edges
    # Info    :  - Recovering boundary
    # Info    : Done reconstructing mesh (Wall 0.0159928s, CPU 0.015992s)

    # local TOX run:
    # ...
    # Info    : Found volume 6
    # Info    : It. 0 - 0 nodes created - worst tet radius 1.87415 (nodes removed 0 0)
    # Info    : 3D refinement terminated (2553 nodes total):
    # Info    :  - 0 Delaunay cavities modified for star shapeness
    # Info    :  - 7 nodes could not be inserted
    # Info    :  - 64 tetrahedra created in 4.7456e-05 sec. (1348617 tets/s)
    # Info    : Tetrahedrizing 1297 nodes...
    # Info    : Done tetrahedrizing 1305 nodes (Wall 0.020723s, CPU 0.020724s)
    # Info    : Reconstructing mesh...
    # Info    :  - Creating surface mesh
    # Info    : Found two overlapping facets.
    # Info    :   1st: [114, 113, 64] #39
    # Info    :   2nd: [114, 113, 64] #40
    # ---------------------------------------------------------------------------------------------- Captured stderr call -----------------------------------------------------------------------------------------------
    # Warning : 16 elements remain invalid in surface 11
    # Warning : 18 elements remain invalid in surface 25
    # Warning : 4 elements remain invalid in surface 41
    # Warning : 24 elements remain invalid in surface 45
    # Warning : 34 elements remain invalid in surface 25
    # Warning : 6 elements remain invalid in surface 41
    # Warning : 20 elements remain invalid in surface 45
    # Error   : Invalid boundary mesh (overlapping facets) on surface 39 surface 40
    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")

    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #16
0
def test_fuse_tunnel_2():
    """
    Test shows, how to fuse two cylinders cross-secting each in a common plane under given angle.
    In contrast to previous test, we rotate the second tunnel around extremal point EP of the intersetion ellipse
    and then fuses both into final object.

    -> RESULT: not a good approach - the point EP is found correctly, however the cylinders stick out
    which can be seen both in brep and even better in resulting mesh with finer mesh step.
    """
    os.chdir(this_source_dir)
    mesh_name = "fuse_tunnel_2"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    geom = geometry()

    # create tunnel
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])

    radius = float(geom['tunnel_1']["radius"])
    assert radius == float(geom['tunnel_2']["radius"])

    # # cutting box
    box_s = 20
    # box = gen.box([box_s, box_s, box_s])
    # # cutting plane between the cylinders
    plane = gen.rectangle([box_s, box_s]).rotate([1, 0, 0], np.pi / 2)

    # directional vectors of the cylinders
    # supposing equal radius
    v_t1 = tunnel_mid - tunnel_start
    v_t1 = v_t1 / np.linalg.norm(v_t1)  # normalize
    v_t2 = tunnel_mid - tunnel_end
    v_t2 = v_t2 / np.linalg.norm(v_t2)  # normalize

    # directional vectors of the cutting plane
    angle_12 = np.pi - np.arccos(np.dot(v_t1, v_t2))
    d = radius / np.sin(angle_12)
    u = d * (v_t1 + v_t2
             )  # points from the center to the extremal point of the ellipse E

    # distance we have to move both cylinder, so they meet at E with their corners
    delta = np.sqrt(np.dot(u, u) - radius * radius)

    # create prolongated tunnels for fusion
    tunnel_mid_1 = tunnel_mid + delta * v_t1
    tunnel_mid_2 = tunnel_mid + delta * v_t2
    tunnel_1 = gen.cylinder(radius, tunnel_mid_1 - tunnel_start, tunnel_start)
    tunnel_2 = gen.cylinder(radius, tunnel_mid_2 - tunnel_end, tunnel_end)

    # if needed, make the cutting ellipse plane
    v = np.cross(v_t1, v_t2)
    # normal of the cutting plane
    n = np.cross(u, v)
    n = n / np.linalg.norm(n)  # normalize

    # angle between cutting plane and y-axis
    angle = np.arccos(np.dot([0, 0, 1], n)) - np.pi / 2
    # rotate cutting box and plane
    plane.rotate(axis=[1, 0, 0], angle=angle)

    # move the cutting plane into the connecting point
    plane.translate(tunnel_mid)

    print("fuse...")
    # tunnel = tunnel_1.copy().fuse(tunnel_2.copy())
    tunnel = tunnel_1.fuse(tunnel_2)
    # tunnel = tunnel_2_x.fuse(tunnel_1_x)
    mesh_step = 1.0
    tunnel.set_region("tunnel").mesh_step(mesh_step)

    # tunnel_3 = gen.cylinder(radius, tunnel_mid - tunnel_start, tunnel_start)
    # tunnel_4 = gen.cylinder(radius, tunnel_mid - tunnel_end, tunnel_end)
    # tunnel_1.set_region("tunnel_1").mesh_step(mesh_step)
    # tunnel_2.set_region("tunnel_2").mesh_step(mesh_step)
    # tunnel_3.set_region("tunnel_3").mesh_step(mesh_step)
    # tunnel_4.set_region("tunnel_4").mesh_step(mesh_step)

    # mesh_all = [tunnel]

    # uncomment one of the following (and the corresponding above) to see auxilliary objects
    mesh_all = [tunnel, plane]
    # mesh_all = [plane, tunnel_1, tunnel_2]
    # mesh_all = [tunnel_1, tunnel_2, tunnel, plane, tunnel_3, tunnel_4]

    print("Generating mesh...")
    gen.keep_only(*mesh_all)
    gen.write_brep()
    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")
    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #17
0
def test_fuse_tunnel():
    """
    Test shows, how to fuse two cylinders cross-secting each in a common plane under given angle.
    It prolongates the cylinders, creates the common face in the middle, cuts the original cylinders
    and then fuses them into final object.
    """
    os.chdir(this_source_dir)
    mesh_name = "fuse_tunnel"
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    geom = geometry()

    # create tunnel
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])

    tunnel_1_c = create_cylinder(gen, geom['tunnel_1'], 0.2)[0]
    tunnel_2_c = create_cylinder(gen, geom['tunnel_2'], 0.2)[0]

    # cutting box
    box_s = 200
    box = gen.box([box_s, box_s, box_s])
    # cutting plane between the cylinders
    plane = gen.rectangle([box_s, box_s]).rotate([1, 0, 0], np.pi / 2)

    # directional vectors of the cylinders
    # supposing equal radius
    v_t1 = tunnel_mid - tunnel_start
    v_t1 = v_t1 / np.linalg.norm(v_t1)  # normalize
    v_t2 = tunnel_mid - tunnel_end
    v_t2 = v_t2 / np.linalg.norm(v_t2)  # normalize

    # directional vectors of the cutting plane
    u = v_t1 + v_t2
    v = np.cross(v_t1, v_t2)
    # normal of the cutting plane
    n = np.cross(u, v)
    n = n / np.linalg.norm(n)  # normalize

    # angle between cutting plane and y-axis
    angle = np.arccos(np.dot([0, 0, 1], n)) - np.pi / 2
    # rotate cutting box and plane
    box.rotate(axis=[1, 0, 0], angle=angle)
    plane.rotate(axis=[1, 0, 0], angle=angle)

    # move the cutting plane into the connecting point
    plane.translate(tunnel_mid)

    # move box and cut the first cylinder
    box.translate(tunnel_mid)
    box.translate(-box_s / 2 * n)
    tunnel_1_x = tunnel_1_c.intersect(box)

    # move box and cut the second cylinder
    box.translate(+box_s * n)
    tunnel_2_x = tunnel_2_c.intersect(box)

    print("fuse...")
    tunnel = tunnel_1_x.fuse(tunnel_2_x)
    # tunnel = tunnel_2_x.fuse(tunnel_1_x)
    tunnel.set_region("tunnel").mesh_step(1.5)

    mesh_all = [tunnel]

    print("Generating mesh...")
    gen.keep_only(*mesh_all)
    gen.write_brep()
    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")
    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #18
0
def test_2D_tunnel_cut():
    """
    Generates a square mesh with an elliptic hole in its center.
    Test:
    - square and ellipse creation
    - cut and fragment functions
    - adding physical boundaries (select_by_intersect)
    - setting mesh_step to the tunnel boundary
    - reading the gmsh logger
    """
    mesh_name = "2d_tunnel_cut"

    tunnel_mesh_step = 0.5
    dimensions = [100, 100]
    tunnel_dims = np.array([4.375, 3.5]) / 2
    tunnel_center = [0, 0, 0]

    # test gmsh loggger
    gen = gmsh.GeometryOCC(mesh_name, verbose=True)
    gmsh_logger = gen.get_logger()
    gmsh_logger.start()

    # Main box
    box = gen.rectangle(dimensions).set_region("box")
    side = gen.line([-dimensions[0] / 2, 0, 0], [dimensions[0] / 2, 0, 0])
    sides = dict(bottom=side.copy().translate([0, -dimensions[1] / 2, 0]),
                 top=side.copy().translate([0, +dimensions[1] / 2, 0]),
                 left=side.copy().translate([0, +dimensions[0] / 2,
                                             0]).rotate([0, 0, 1], np.pi / 2),
                 right=side.copy().translate([0, -dimensions[0] / 2,
                                              0]).rotate([0, 0, 1], np.pi / 2))

    # ellipse of the tunnel cross-section
    tunnel_disc = gen.disc(tunnel_center, *tunnel_dims)
    tunnel_select = tunnel_disc.copy()

    box_drilled = box.cut(tunnel_disc)
    box_fr, tunnel_fr = gen.fragment(box_drilled, tunnel_disc)

    box_all = []

    b_box_fr = box_fr.get_boundary()
    for name, side_tool in sides.items():
        isec = b_box_fr.select_by_intersect(side_tool)
        box_all.append(isec.modify_regions("." + name))

    b_tunnel_select = tunnel_select.get_boundary()
    b_tunnel = b_box_fr.select_by_intersect(b_tunnel_select)
    b_tunnel.modify_regions(".tunnel").mesh_step(tunnel_mesh_step)
    box_all.extend([box_fr, b_tunnel])

    mesh_groups = [*box_all]
    gen.keep_only(*mesh_groups)
    # gen.write_brep()

    min_el_size = tunnel_mesh_step / 2
    max_el_size = np.max(dimensions) / 10

    gen.make_mesh(mesh_groups)

    gmsh_log_msgs = gmsh_logger.get()
    gmsh_logger.stop()

    def check_gmsh_log(lines):
        """
        Search for "No elements in volume" message -> could not mesh the volume -> empty mesh.
        # PLC Error:  A segment and a facet intersect at point (-119.217,65.5762,-40.8908).
        #   Segment: [70,2070] #-1 (243)
        #   Facet:   [3147,9829,13819] #482
        # Info    : failed to recover constrained lines/triangles
        # Info    : function failed
        # Info    : function failed
        # Error   : HXT 3D mesh failed
        # Error   : No elements in volume 1
        # Info    : Done meshing 3D (Wall 0.257168s, CPU 0.256s)
        # Info    : 13958 nodes 34061 elements
        # Error   : ------------------------------
        # Error   : Mesh generation error summary
        # Error   :     0 warnings
        # Error   :     2 errors
        # Error   : Check the full log for details
        # Error   : ------------------------------
        """
        empty_volume_error = "No elements in volume"
        res = [line for line in lines if empty_volume_error in line]
        if len(res) != 0:
            raise Exception("GMSH error - No elements in volume")

    check_gmsh_log(gmsh_log_msgs)

    gen.write_mesh(mesh_name + ".msh2", gmsh.MeshFormat.msh2)

    # estimate number of the smallest elements around the tunnel
    tunnel_circuference = np.pi * np.sqrt(
        2 * (tunnel_dims[0]**2 + tunnel_dims[1]**2))
    n_expected = np.round(tunnel_circuference / tunnel_mesh_step)

    # get number of the smallest elements
    n_match = check_min_mesh_step(dim=2,
                                  step_size=tunnel_mesh_step,
                                  tolerance=0.05)
    assert n_match > n_expected
Пример #19
0
def generate_mesh(geom):
    # options.Geometry.Tolerance = 0.001
    # options.Geometry.ToleranceBoolean = 1e-2
    # options.Geometry.AutoCoherence = 2
    # options.Geometry.OCCFixSmallEdges = True
    # options.Geometry.OCCFixSmallFaces = True
    # options.Geometry.OCCFixDegenerated = True
    # options.Geometry.OCCSewFaces = True
    # # #
    # options.Mesh.ToleranceInitialDelaunay = 0.01
    # options.Mesh.CharacteristicLengthMin = 0.1
    # options.Mesh.CharacteristicLengthMax = 2.0
    # options.Mesh.AngleToleranceFacetOverlap = 0.8

    gen = gmsh.GeometryOCC("greet_mesh_tunnel", verbose=True)

    # with open(os.path.join(script_dir, "geometry.yaml"), "r") as f:
    #     geom = yaml.safe_load(f)

    # create tunnel
    box_size = np.array(geometry_dict['outer_box']["size"])
    tunnel_start = np.array(geom['tunnel_1']["start"])
    tunnel_mid = np.array(geom['tunnel_1']["end"])
    tunnel_end = np.array(geom['tunnel_2']["end"])

    tunnel = fuse_tunnels(gen, geom)

    # create inner box
    box_inner = create_box(gen, geometry_dict['inner_box'])
    # create outer box
    box_outer = create_box(gen, geometry_dict['outer_box'])
    # create fracture cut box
    cut_fracture_box = create_box(gen, geometry_dict['cut_fracture_box'])

    # create cut outer_box object for setting the correct region
    box_outer_cut = box_outer.copy().cut(box_inner)
    # cut tunnel from inner box
    box_inner_cut = box_inner.cut(*tunnel)

    # prepare auxiliary boundary objects to set boundary regions
    side_z = gen.rectangle([box_size[0], box_size[1]])
    side_y = gen.rectangle([box_size[0], box_size[2]])
    side_x = gen.rectangle([box_size[2], box_size[1]])
    sides = dict(
        bottom=side_z.copy().translate([0, 0, -box_size[2] / 2]),
        top=side_z.copy().translate([0, 0, +box_size[2] / 2]),
        back=side_y.copy().translate([0, 0, -box_size[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        front=side_y.copy().translate([0, 0, +box_size[1] / 2]).rotate([-1, 0, 0], np.pi / 2),
        right=side_x.copy().translate([0, 0, -box_size[0] / 2]).rotate([0, 1, 0], np.pi / 2),
        left=side_x.copy().translate([0, 0, +box_size[0] / 2]).rotate([0, 1, 0], np.pi / 2)
    )

    # translate and rotate all to final position
    objs_to_rotate = [box_outer_cut, box_inner_cut, cut_fracture_box, *tunnel, *sides.values()]
    outer_box_points = np.array(geometry_dict['outer_box']["nodes"])
    barycenter = [np.average(outer_box_points[:, 0]), np.average(outer_box_points[:, 1]),
                  np.average(outer_box_points[:, 2])]
    rot_x = float(geometry_dict['outer_box']["rot_x"])
    rot_y = float(geometry_dict['outer_box']["rot_y"])
    rot_z = float(geometry_dict['outer_box']["rot_z"])
    for obj in objs_to_rotate:
        if rot_x != 0:
            obj.rotate([1, 0, 0], rot_x)
        if rot_y != 0:
            obj.rotate([0, 1, 0], rot_y)
        if rot_z != 0:
            obj.rotate([0, 0, 1], rot_z)
        obj.translate(barycenter)
    # I have no idea, why I have to do this separately..
    box_outer.translate(barycenter)

    # create fractures
    fractures = []
    fracture_names = []
    for f in geometry_dict['fractures']:
        fract = create_plane(gen, f)
        # fract.set_region(f["name"])
        fractures.append(fract.intersect(cut_fracture_box))
        fracture_names.append(f["name"])

    print("fragment start")
    frag = gen.fragment(box_outer, box_inner_cut, *[f.copy() for f in fractures])
    fractures_f_group = gen.group(*[frag[i] for i in range(2, len(frag))])
    # frag = gen.fragment(box_outer, box_inner_cut)
    print("fragment end")

    box_outer_reg = frag[0].select_by_intersect(box_outer_cut)
    box_outer_reg.set_region(geometry_dict['outer_box']["name"])
    gen.set_mesh_step(box_outer_reg, 10.0)
    box_inner_reg = frag[1]
    box_inner_reg.set_region(geometry_dict['inner_box']["name"])
    gen.set_mesh_step(box_inner_reg, 4.0)

    box_all = [box_outer_reg, box_inner_reg]

    # make boundaries
    print("Making boundaries...")
    b_box_outer = box_outer_reg.get_boundary()
    b_box_inner = box_inner_reg.get_boundary()
    for name, side_tool in sides.items():
        isec_outer = b_box_outer.select_by_intersect(side_tool)
        isec_inner = b_box_inner.select_by_intersect(side_tool)
        isec_outer.set_region("." + geometry_dict['outer_box']["name"] + "_" + name)
        isec_inner.set_region("." + geometry_dict['inner_box']["name"] + "_" + name)
        box_all.append(isec_outer)
        box_all.append(isec_inner)

    b_box_inner = box_inner_reg.get_boundary()
    b_tunnel_parts = []
    for i in range(len(tunnel)):
        b_tunnel_part = b_box_inner.select_by_intersect(tunnel[i])
        b_tunnel_part.set_region(".tunnel" + "_" + str(i))
        b_tunnel_parts.append(b_tunnel_part)
        gen.set_mesh_step(b_tunnel_part, 1.0)
    print("Making boundaries...[finished]")

    box_all.extend(b_tunnel_parts)

    print("Setting fractures regions...")
    # fracture regions
    fractures_reg = []
    for frac, name in zip(fractures, fracture_names):
        frac_cut = frac.cut(*tunnel)
        frac_reg = fractures_f_group.select_by_intersect(frac_cut)
        frac_reg.set_region(name)
        gen.set_mesh_step(frac_reg, 2.0)
        fractures_reg.append(frac_reg)

        # set regions on the 1D curve cross-section of fractures and tunnel surface
        b_frac_reg = frac_reg.get_boundary()
        for i in range(len(b_tunnel_parts)):
            b_fract_tunnel = b_frac_reg.select_by_intersect(b_tunnel_parts[i])
            if len(b_fract_tunnel.dim_tags) < 1:
                continue
            b_fract_tunnel.set_region("." + name + "_tunnel" + "_" + str(i))
            box_all.append(b_fract_tunnel)

    box_all.extend(fractures_reg)
    print("Setting fractures regions...[finished]")

    # the tunnel must be removed before meshing | we do not know the reason
    for t in tunnel:
        gen.model.remove(t.dim_tags)
    # for sb in split_boxes:
    #     gen.model.remove(sb.dim_tags)

    i=0
    for b in box_all:
        print("i={0} ".format(i))
        for r in b.regions:
            print("{0} ({1}) ".format(r.name, r.id))
        for dt in b.dim_tags:
            print(dt)
        i = i+1

    # mesh_all = [*tunnel]
    mesh_all = [*box_all]
    # mesh_all = [*split_boxes]

    print("Generating mesh...")
    gen.keep_only(*mesh_all)
    gen.write_brep()

    gen.make_mesh(mesh_all)
    print("Generating mesh...[finished]")
    print("Writing mesh...")
    mesh_name = "greet_mesh.msh2"
    gen.write_mesh(mesh_name, gmsh.MeshFormat.msh2)
    print("Writing mesh...[finished]")
Пример #20
0
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(mesh_name + ".msh2", gmsh.MeshFormat.msh2)