Exemple #1
0
 def test_nx_ny_21_with_material(self):
     """Test nx, ny with 2 levels of 1 division and a material."""
     ref_groups = groups_21_with_material
     ref_centroids = centroids_21
     mocmg.initialize()
     gmsh.initialize()
     rectangular_grid(bb_44, nx=[2, 2], ny=[2, 2], material="material_UO2")
     group_nums = gmsh.model.getPhysicalGroups()
     names = [gmsh.model.getPhysicalName(*grp) for grp in group_nums]
     ref_names = list(ref_groups.keys())
     # Check correct names/entities
     for i, name in enumerate(ref_names):
         self.assertEqual(name, names[i])
         index = names.index(name)
         group_ents = list(
             gmsh.model.getEntitiesForPhysicalGroup(*group_nums[index]))
         ref_group_ents = ref_groups[name]
         self.assertEqual(group_ents, ref_group_ents)
     # Check correct area/centroid
     for ent in gmsh.model.getEntities(2):
         tag = ent[1]
         mass = gmsh.model.occ.getMass(2, tag)
         self.assertAlmostEqual(1.0,
                                mass,
                                places=5,
                                msg="1 width, 1 height, 1 area")
         x, y, z = gmsh.model.occ.getCenterOfMass(2, tag)
         centroid = (x, y, z)
         for i in range(3):
             self.assertAlmostEqual(centroid[i], ref_centroids[tag][i])
     # Check materials
     gmsh.clear()
     gmsh.finalize()
Exemple #2
0
 def test_x_y_nonuniform_2(self):
     """Test x, y with nonuniform grid with 2 levels."""
     ref_groups = groups_nu2
     ref_centroids = centroids_nu2
     ref_areas = areas_nu2
     mocmg.initialize()
     gmsh.initialize()
     rectangular_grid(bb_12_4,
                      x=[[0.0, 12.0], [2.0, 10.0]],
                      y=[[2.0], [1.0, 3.0]])
     group_nums = gmsh.model.getPhysicalGroups()
     names = [gmsh.model.getPhysicalName(*grp) for grp in group_nums]
     ref_names = list(ref_groups.keys())
     # Check correct names/entities
     for i, name in enumerate(ref_names):
         self.assertEqual(name, names[i])
         index = names.index(name)
         group_ents = list(
             gmsh.model.getEntitiesForPhysicalGroup(*group_nums[index]))
         ref_group_ents = ref_groups[name]
         self.assertEqual(group_ents, ref_group_ents)
     # Check correct area/centroid
     for ent in gmsh.model.getEntities(2):
         tag = ent[1]
         mass = gmsh.model.occ.getMass(2, tag)
         self.assertAlmostEqual(ref_areas[tag], mass, places=5)
         x, y, z = gmsh.model.occ.getCenterOfMass(2, tag)
         centroid = (x, y, z)
         for i in range(3):
             self.assertAlmostEqual(centroid[i], ref_centroids[tag][i])
     gmsh.clear()
     gmsh.finalize()
 def test_2_rectangles_with_bad_overwrite(self):
     """Test a 2 rectangle case, overwriting a material that doesnt exist."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             gmsh.model.occ.addRectangle(0.0, 0.0, 0.0, 2.0, 2.0)
             gmsh.model.occ.addRectangle(1.0, 1.0, 0.0, 2.0, 2.0)
             gmsh.model.occ.synchronize()
             gmsh.model.addPhysicalGroup(2, [1])
             gmsh.model.addPhysicalGroup(2, [2])
             gmsh.model.addPhysicalGroup(2, [1, 2])
             gmsh.model.setPhysicalName(2, 1, "Material_1")
             gmsh.model.setPhysicalName(2, 2, "Material_2")
             gmsh.model.setPhysicalName(2, 3, "All")
             mocmg.model.group_preserving_fragment(
                 [(2, 1)], [(2, 2)], overwrite_material="BAD_MAT"
             )
     gmsh.clear()
     gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, ref_out)
     self.assertEqual(err, bad_overwrite)
Exemple #4
0
 def reinit(self):
     """
     Clear whole geometry model.
     TODO: need tests
     Returns:
     """
     gmsh.clear()
Exemple #5
0
 def test_nx_y_11(self):
     """Test nx, y with 1 division."""
     ref_groups = groups_11
     ref_centroids = centroids_11
     mocmg.initialize()
     gmsh.initialize()
     rectangular_grid(bb_44, nx=[2], y=[[2.0]])
     group_nums = gmsh.model.getPhysicalGroups()
     names = [gmsh.model.getPhysicalName(*grp) for grp in group_nums]
     ref_names = list(ref_groups.keys())
     # Check correct names/entities
     for i, name in enumerate(ref_names):
         self.assertEqual(name, names[i])
         index = names.index(name)
         group_ents = list(
             gmsh.model.getEntitiesForPhysicalGroup(*group_nums[index]))
         ref_group_ents = ref_groups[name]
         self.assertEqual(group_ents, ref_group_ents)
     # Check correct area/centroid
     for ent in gmsh.model.getEntities(2):
         tag = ent[1]
         mass = gmsh.model.occ.getMass(2, tag)
         self.assertAlmostEqual(4.0,
                                mass,
                                places=5,
                                msg="2 width, 2 height, 4 area")
         x, y, z = gmsh.model.occ.getCenterOfMass(2, tag)
         centroid = (x, y, z)
         for i in range(3):
             self.assertAlmostEqual(centroid[i], ref_centroids[tag][i])
     gmsh.clear()
     gmsh.finalize()
Exemple #6
0
def _embed_points(model, x, bounding_shape, **kwargs):
    '''Hypercube mesh with vertices x'''
    npoints, tdim = x.shape

    # Figure out how to bound it
    counts = bounding_shape.create_volume(model, x)
    
    # In gmsh Point(4) will be returned as fourth node
    vertex_map = []  # mesh_1d.x[i] is embedding_mesh[vertex_map[i]]
    if tdim == 2:
        for xi in x:
            vertex_map.append(model.geo.addPoint(*np.r_[xi, 0])-1)
    else:
        for xi in x:
            vertex_map.append(model.geo.addPoint(*xi)-1)
                            
    vertex_map = np.array(vertex_map)

    model.addPhysicalGroup(tdim, [counts[tdim]], 1)

    model.geo.synchronize()
    model.mesh.embed(0, 1+vertex_map, tdim, counts[tdim])
    model.geo.synchronize()

    kwargs['save_geo'] and gmsh.write('%s.geo_unrolled' % kwargs['save_geo'])

    model.mesh.generate(tdim)

    kwargs['save_msh'] and gmsh.write('%s.msh' % kwargs['save_msh'])

    embedding_mesh, _ = conversion.mesh_from_gmshModel(model, include_mesh_functions=None)
    gmsh.clear()

    return embedding_mesh, vertex_map
Exemple #7
0
def make_mesh(gmsh, densities):
    gmsh.clear()
    gmsh.model.add("SubProblem")
    geo.sub.create(gmsh, densities)
    gmsh.model.occ.synchronize()
    gmsh.model.mesh.generate(2)

    return npyfem.from_gmsh(gmsh)
Exemple #8
0
def meshObj(obj, dim, meshParms=False, tessObj=None):
    # Create gmsh from shape or mesh
    # Clear any previous models
    gmsh.clear()
    setMeshParms(meshParms, obj, tessObj)
    if hasattr(obj, 'Shape'):
        return (meshObjShape(obj, dim))

    elif hasattr(obj, 'Mesh'):
        return (meshObjMesh(obj, dim))
Exemple #9
0
 def __init__(self, name):
     gmsh.initialize()
     gmsh.clear()
     gmsh.model.add(name)
     self.name = name
     self.model = gmsh.model
     self.fac = self.model.occ
     self.pos = gmsh.view
     self.vertices = np.array([])
     self.tetra = np.array([])
    def test_2_pins_new_material(self):
        """Test overlaying grid on 2 pins with a new grid material."""
        ref_groups = groups_2_pins_new_mat
        ref_centroids = centroids_2_pins

        with captured_output() as (out, err):
            mocmg.initialize()
            gmsh.initialize()

            gmsh.model.occ.addDisk(1.0, 1.0, 0.0, 0.5, 0.5)
            gmsh.model.occ.addDisk(3.0, 1.0, 0.0, 0.5, 0.5)
            gmsh.model.occ.synchronize()

            p = gmsh.model.addPhysicalGroup(2, [1])
            gmsh.model.setPhysicalName(2, p, "MATERIAL_UO2")
            p = gmsh.model.addPhysicalGroup(2, [2])
            gmsh.model.setPhysicalName(2, p, "MATERIAL_MOX")

            overlay_rectangular_grid(bb_42,
                                     nx=[2],
                                     ny=[1],
                                     material="MATERIAL_NEW")

        out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
        out = [line.split(None, 1)[1] for line in out]
        self.assertEqual(out, reference_out)
        self.assertEqual(err, [])

        group_nums = gmsh.model.getPhysicalGroups()
        names = [gmsh.model.getPhysicalName(*grp) for grp in group_nums]
        ref_names = list(ref_groups.keys())
        # Check correct names/entities
        for i, name in enumerate(ref_names):
            self.assertEqual(name, names[i])
            index = names.index(name)
            group_ents = list(
                gmsh.model.getEntitiesForPhysicalGroup(*group_nums[index]))
            ref_group_ents = ref_groups[name]
            self.assertEqual(group_ents, ref_group_ents)
        # Check correct area/centroid
        for ent in gmsh.model.getEntities(2):
            tag = ent[1]
            mass = gmsh.model.occ.getMass(2, tag)
            if tag == 1 or tag == 2:
                self.assertAlmostEqual(0.785398,
                                       mass,
                                       places=5,
                                       msg="pi*0.5**2")
                x, y, z = gmsh.model.occ.getCenterOfMass(2, tag)
                centroid = (x, y, z)
                for i in range(3):
                    self.assertAlmostEqual(centroid[i], ref_centroids[tag][i])
        gmsh.clear()
        gmsh.finalize()
Exemple #11
0
def meshObject(obj, dim, algol, lm, lc, lp):
    # Create gmsh from shape or mesh
    # Clear any previous models
    print('mesh Object - first Clear')
    gmsh.clear()
    setMeshParms(algol, lm, lc, lp)
    if hasattr(obj, 'Shape'):
        return (meshObjShape(obj, dim))

    elif hasattr(obj, 'Mesh'):
        return (meshObjMesh(obj, dim))
Exemple #12
0
def load_gmsh_elems(gmshpath, entity):
    '''
    Wrapper function for loading gmsh elements
    '''

    gmsh.initialize()
    gmsh.open(gmshpath)
    nodes, elem_ids, node_maps = gmsh.model.mesh.getElements(
        entity[0], entity[1])
    gmsh.clear()

    return nodes, elem_ids[0] - 1, node_maps[0] - 1
Exemple #13
0
 def test_get_entities_for_physical_group(self):
     """Test the get_entities_for_physical_group_name for a regular use case."""
     mocmg.initialize()
     gmsh.initialize()
     tag = gmsh.model.occ.addDisk(0.0, 0.0, 0.0, 1.0, 1.0)
     gmsh.model.occ.synchronize()
     output_tag = gmsh.model.addPhysicalGroup(2, [tag])
     gmsh.model.setPhysicalName(2, output_tag, "Test Physical Group Name")
     ents = mocmg.gmsh_utils.get_entities_for_physical_group_name(
         "Test Physical Group Name")
     self.assertEqual([1], ents)
     gmsh.clear()
     gmsh.finalize()
 def test_3_rectangles_1_not_in_frag(self):
     """Test 2 rectangles in frag, one off to the side."""
     ref_groups = groups_3_rectangles_1_not_in_frag
     ref_centroids = centroids_3_rectangles_1_not_in_frag
     ref_areas = areas_3_rectangles_1_not_in_frag
     # Setup
     with captured_output() as (out, err):
         mocmg.initialize()
         gmsh.initialize()
         gmsh.model.occ.addRectangle(0.0, 0.0, 0.0, 2.0, 2.0)
         gmsh.model.occ.addRectangle(1.0, 1.0, 0.0, 2.0, 2.0)
         gmsh.model.occ.addRectangle(4.0, 4.0, 0.0, 2.0, 2.0)
         gmsh.model.occ.synchronize()
         gmsh.model.addPhysicalGroup(2, [1])
         gmsh.model.addPhysicalGroup(2, [2])
         gmsh.model.addPhysicalGroup(2, [3])
         gmsh.model.addPhysicalGroup(2, [1, 2, 3])
         gmsh.model.setPhysicalName(2, 1, "Group 1")
         gmsh.model.setPhysicalName(2, 2, "Group 2")
         gmsh.model.setPhysicalName(2, 3, "Group 3")
         gmsh.model.setPhysicalName(2, 4, "All")
         mocmg.model.group_preserving_fragment([(2, 1)], [(2, 2)])
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in err]  # strip times
     self.assertEqual(out, ref_out)
     self.assertEqual(err, [])
     # Get info
     group_nums = gmsh.model.getPhysicalGroups()
     names = [gmsh.model.getPhysicalName(*grp) for grp in group_nums]
     ref_names = list(ref_groups.keys())
     # Check correct group names/entities
     for i, name in enumerate(names):
         self.assertEqual(name, ref_names[i])
         index = names.index(name)
         group_ents = list(gmsh.model.getEntitiesForPhysicalGroup(*group_nums[index]))
         ref_group_ents = ref_groups[name]
         self.assertEqual(group_ents, ref_group_ents)
     # Check correct area/centroid
     for ent in gmsh.model.getEntities(2):
         tag = ent[1]
         mass = gmsh.model.occ.getMass(2, tag)
         self.assertAlmostEqual(ref_areas[tag], mass, places=5)
         x, y, z = gmsh.model.occ.getCenterOfMass(2, tag)
         centroid = (x, y, z)
         for i in range(3):
             self.assertAlmostEqual(centroid[i], ref_centroids[tag][i])
     # Clean up
     gmsh.clear()
     gmsh.finalize()
Exemple #15
0
def stp_to_stl(file):
    basename = os.path.basename(file)
    filename, ext = os.path.splitext(basename)
    if ext.lower().endswith('.stp'):
        import gmsh

        stl_file = file.replace(ext, '.stl')
        gmsh.initialize()
        gmsh.open(file)
        gmsh.write(stl_file)
        gmsh.clear()

        os.remove(file)
        return stl_file
    else:
        raise TypeError
Exemple #16
0
def guess_entity(msh, dim, tag):
    '''
    Use last digit method of figuring out what the entity ID is
    '''

    tag = str(tag)

    gmsh.initialize()
    gmsh.open(msh)
    ent_list = gmsh.model.getEntities()

    subset = [k for k in ent_list if k[0] == dim]
    entity = [k for k in subset if str(k[1])[-1] == tag]

    gmsh.clear()

    return entity[0]
Exemple #17
0
def load_gmsh_nodes(gmshpath, entity):
    '''
    Given a fullpath to some .msh file
    load in the mesh nodes IDs, triangles and coordinates.

    gmshpath -- path to gmsh file
    dimtag   -- tuple specifying the (dimensionality,tagID) being loaded


    If entity=(dim,tag) not provided then pull the first entity and return
    '''

    gmsh.initialize()
    gmsh.open(gmshpath)
    nodes, coords, params = gmsh.model.mesh.getNodes(entity[0], entity[1])
    coords = np.array(coords).reshape((len(coords) // 3, 3))
    gmsh.clear()

    return nodes - 1, coords, params
Exemple #18
0
 def test_y_noniterable_type(self):
     """Test rect grid with non-iterable type elements."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_11, x=[[1]], y=[1.0])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, y_nonlist_type)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + y_nonlist_type)
Exemple #19
0
 def test_bad_bounding_box(self):
     """Test a bad bounding box that produces negative dx, dy, dz."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid([0, 0, 0, -1, -1, -1], x=[[0.5]], y=[[0.5]])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, bad_bb)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + bad_bb)
Exemple #20
0
 def test_get_entities_for_physical_group_bad_name(self):
     """Test the get_entities_for_physical_group_name for a regular use case."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             tag = gmsh.model.occ.addDisk(0.0, 0.0, 0.0, 1.0, 1.0)
             gmsh.model.occ.synchronize()
             output_tag = gmsh.model.addPhysicalGroup(2, [tag])
             gmsh.model.setPhysicalName(2, output_tag,
                                        "Test Physical Group Name")
             mocmg.gmsh_utils.get_entities_for_physical_group_name(
                 "Bad name")
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, [])
     self.assertEqual(err, bad_name)
     gmsh.clear()
     gmsh.finalize()
Exemple #21
0
 def test_y_out_of_bb(self):
     """Test rect grid with a y-division outside the bb."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_11, x=[[1.0]], y=[[-1.0]])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, out_of_bb)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + out_of_bb)
 def __ExportingMeshToMdpa(self):
     
     gmsh.write(self.file_name+"_3d.vtk")
     meshing=meshio.read(self.file_name+"_3d.vtk")
     meshio.mdpa.write(self.file_name+"_3d.mdpa", meshing)
     gmsh.clear()
     gmsh.finalize()
     toedit_mdpa=open(self.file_name+"_3d.mdpa","r")
     edited_mdpa = open("test.mdpa", 'w')
     checkWords = ("Begin Elements Triangle3D3","Begin Elements Tetrahedra3D4","Begin ElementalData CellEntityIds","End ElementalData CellEntityIds")
     repWords = ("Begin Elements Element3D3N","Begin Elements Element3D4N","Begin ElementalData ACTIVATION_LEVEL","End ElementalData")
     for line in toedit_mdpa:
         for check, rep in zip(checkWords, repWords):
             line = line.replace(check, rep)
         edited_mdpa.write(line)
     toedit_mdpa.close()
     edited_mdpa.close()
     if os.path.exists(self.file_name+"_3d.mdpa"):
         os.remove(self.file_name+"_3d.mdpa")
         os.rename("test.mdpa",self.file_name+"_3d.mdpa")
Exemple #23
0
 def test_ny0(self):
     """Test ny with 0 division."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_11, nx=[1, 1], ny=[0, 1])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, ny_type)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + ny_type)
Exemple #24
0
 def test_arg_len_mismatch_nxny(self):
     """Test rect grid with mismatched arg len."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_11, x=[2, 3], y=[1])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, len_mismatch)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + len_mismatch)
Exemple #25
0
 def test_thick_dz(self):
     """Test rect grid with large change in z direction."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_dz, x=[[0.5]], y=[[0.5]])
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, thick_dz)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + thick_dz)
Exemple #26
0
 def test_nx_ny_21_with_bad_material(self):
     """Test nx, ny with 2 levels of 1 division and an invalid material name."""
     with self.assertRaises(SystemExit):
         with captured_output() as (out, err):
             mocmg.initialize()
             gmsh.initialize()
             rectangular_grid(bb_44,
                              nx=[2, 2],
                              ny=[2, 2],
                              material="bad_mat")
             gmsh.clear()
             gmsh.finalize()
     out, err = out.getvalue().splitlines(), err.getvalue().splitlines()
     out = [line.split(None, 1)[1] for line in out]
     err = [line.split(None, 1)[1] for line in [err[0]]]  # strip times
     self.assertEqual(out, reference_out)
     self.assertEqual(err, bad_material)
     # check log file
     f = open("mocmg.log", "r")
     lines = f.readlines()
     f.close()
     lines = [line.split(None, 1)[1].rstrip("\n") for line in lines]
     self.assertEqual(lines, reference_out + bad_material)
Exemple #27
0
import gmsh

# initial commands
gmsh.initialize()
gmsh.clear()
gmsh.option.setNumber('General.Terminal', 1)
msTg = 'gmsh/port2'
gmsh.model.add(msTg)
gmg = gmsh.model.geo

# geometry (m)
Lx = 5.0
Ly = 4.0
H = 0.5

# define points
ms = 0.10  # mesh size
gmg.addPoint(0, 0, 0, ms, 1)
gmg.addPoint(H, 0, 0, ms, 2)
gmg.addPoint(H, Ly - H, 0, ms, 3)
gmg.addPoint(Lx - H, Ly - H, 0, ms, 4)
gmg.addPoint(Lx - H, 0, 0, ms, 5)
gmg.addPoint(Lx, 0, 0, ms, 6)
gmg.addPoint(Lx, Ly, 0, ms, 7)
gmg.addPoint(Lx / 2 + 0.5, Ly, 0, ms, 8)
gmg.addPoint(Lx / 2 - 0.5, Ly, 0, ms, 9)
gmg.addPoint(0, Ly, 0, ms, 10)

# define lines
gmg.addLine(1, 2, 1)
gmg.addLine(2, 3, 2)
def gmsh_2D_stacked(celltype: str, theta: float, verbose: bool = False):
    res = 0.1
    x0, y0, z0 = 0, 0, 0
    x1, y1 = 1, 1
    y2 = 2

    # Check if GMSH is initialized
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", int(verbose))
    gmsh.clear()

    if MPI.COMM_WORLD.rank == 0:
        if celltype == "quadrilateral":
            gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
            gmsh.option.setNumber("Mesh.RecombineAll", 2)
            recombine = True
        else:
            recombine = False

        points = [
            gmsh.model.occ.addPoint(x0, y0, z0),
            gmsh.model.occ.addPoint(x1, y0, z0),
            gmsh.model.occ.addPoint(x0, y2, z0),
            gmsh.model.occ.addPoint(x1, y2, z0)
        ]
        bottom = gmsh.model.occ.addLine(points[0], points[1])
        top = gmsh.model.occ.addLine(points[2], points[3])
        gmsh.model.occ.extrude([(1, bottom)],
                               0,
                               y1 - y0,
                               0,
                               numElements=[int(1 / (res))],
                               recombine=recombine)
        gmsh.model.occ.extrude([(1, top)],
                               0,
                               y1 - y2 - 1e-12,
                               0,
                               numElements=[int(1 / (2 * res))],
                               recombine=recombine)
        # Syncronize to be able to fetch entities
        gmsh.model.occ.synchronize()

        # Create entity -> marker map (to be used after rotation)
        volumes = gmsh.model.getEntities(2)
        volume_entities = {"Top": [-1, 1], "Bottom": [-1, 2]}
        for i, volume in enumerate(volumes):
            com = gmsh.model.occ.getCenterOfMass(volume[0], volume[1])
            if np.isclose(com[1], (y1 - y0) / 2):
                bottom_index = i
                volume_entities["Bottom"][0] = volume[1]
            elif np.isclose(com[1], (y2 - y1) / 2 + y1):
                top_index = i
                volume_entities["Top"][0] = volume[1]
        surfaces = ["Top", "Bottom", "Left", "Right"]
        entities: Dict[str, Dict[str, List[List[int]]]] = {
            "Bottom": {key: [[], []]
                       for key in surfaces},
            "Top": {key: [[], []]
                    for key in surfaces}
        }
        # Identitfy entities for each surface of top and bottom cube
        # Bottom cube: Top, Right, Bottom, Left
        # Top cube : Top, Right, Bottom, Left
        facet_markers = [[4, 7, 5, 6], [3, 12, 9, 13]]
        bottom_surfaces = gmsh.model.getBoundary([volumes[bottom_index]],
                                                 oriented=False,
                                                 recursive=False)

        for entity in bottom_surfaces:
            com = gmsh.model.occ.getCenterOfMass(entity[0], abs(entity[1]))
            if np.allclose(com, [(x1 - x0) / 2, y0, z0]):
                entities["Bottom"]["Bottom"][0].append(entity[1])
                entities["Bottom"]["Bottom"][1] = [facet_markers[0][2]]
            elif np.allclose(com, [x1, (y1 - y0) / 2, z0]):
                entities["Bottom"]["Right"][0].append(entity[1])
                entities["Bottom"]["Right"][1] = [facet_markers[0][1]]
            elif np.allclose(com, [x0, (y1 - y0) / 2, z0]):
                entities["Bottom"]["Left"][0].append(entity[1])
                entities["Bottom"]["Left"][1] = [facet_markers[0][3]]
            elif np.allclose(com, [(x1 - x0) / 2, y1, z0]):
                entities["Bottom"]["Top"][0].append(entity[1])
                entities["Bottom"]["Top"][1] = [facet_markers[0][0]]
        # Physical markers for top
        top_surfaces = gmsh.model.getBoundary([volumes[top_index]],
                                              oriented=False,
                                              recursive=False)
        for entity in top_surfaces:
            com = gmsh.model.occ.getCenterOfMass(entity[0], abs(entity[1]))
            if np.allclose(com, [(x1 - x0) / 2, y1, z0]):
                entities["Top"]["Bottom"][0].append(entity[1])
                entities["Top"]["Bottom"][1] = [facet_markers[1][2]]
            elif np.allclose(com, [x1, y1 + (y2 - y1) / 2, z0]):
                entities["Top"]["Right"][0].append(entity[1])
                entities["Top"]["Right"][1] = [facet_markers[1][1]]
            elif np.allclose(com, [x0, y1 + (y2 - y1) / 2, z0]):
                entities["Top"]["Left"][0].append(entity[1])
                entities["Top"]["Left"][1] = [facet_markers[1][3]]
            elif np.allclose(com, [(x1 - x0) / 2, y2, z0]):
                entities["Top"]["Top"][0].append(entity[1])
                entities["Top"]["Top"][1] = [facet_markers[1][0]]

        # Note: Rotation cannot be used on recombined surfaces
        gmsh.model.occ.synchronize()

        for volume in volume_entities.keys():
            gmsh.model.addPhysicalGroup(2, [volume_entities[volume][0]],
                                        tag=volume_entities[volume][1])
            gmsh.model.setPhysicalName(2, volume_entities[volume][1], volume)
        for box in entities.keys():
            for surface in entities[box].keys():
                gmsh.model.addPhysicalGroup(1,
                                            entities[box][surface][0],
                                            tag=entities[box][surface][1][0])
                gmsh.model.setPhysicalName(1, entities[box][surface][1][0],
                                           box + ":" + surface)
        # Set mesh sizes on the points from the surface we are extruding
        bottom_nodes = gmsh.model.getBoundary([volumes[bottom_index]],
                                              oriented=False,
                                              recursive=True)
        gmsh.model.occ.mesh.setSize(bottom_nodes, res)
        top_nodes = gmsh.model.getBoundary([volumes[top_index]],
                                           oriented=False,
                                           recursive=True)
        gmsh.model.occ.mesh.setSize(top_nodes, 2 * res)
        # NOTE: Need to synchronize after setting mesh sizes
        gmsh.model.occ.synchronize()
        # Generate mesh
        gmsh.option.setNumber("Mesh.MaxNumThreads1D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads2D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads3D", MPI.COMM_WORLD.size)
        gmsh.model.mesh.generate(2)
        gmsh.model.mesh.setOrder(1)

    mesh, ft = _utils.gmsh_model_to_mesh(gmsh.model, facet_data=True, gdim=2)
    r_matrix = _utils.rotation_matrix([0, 0, 1], theta)

    # NOTE: Hex mesh must be rotated after generation due to gmsh API
    mesh.geometry.x[:] = np.dot(r_matrix, mesh.geometry.x.T).T
    gmsh.clear()
    gmsh.finalize()
    MPI.COMM_WORLD.barrier()
    return mesh, ft
def generate_hex_boxes(x0: float,
                       y0: float,
                       z0: float,
                       x1: float,
                       y1: float,
                       z1: float,
                       z2: float,
                       res: float,
                       facet_markers: Sequence[Sequence[int]],
                       volume_markers: Sequence[int],
                       verbose: bool = False):
    """
    Generate the stacked boxes [x0,y0,z0]x[y1,y1,z1] and
    [x0,y0,z1] x [x1,y1,z2] with different resolution in each box.
    The markers are is a list of arrays containing markers
    array of markers for [back, bottom, right, left, top, front] per box
    volume_markers a list of marker per volume
    """
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", int(verbose))

    if MPI.COMM_WORLD.rank == 0:
        gmsh.clear()
        gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
        gmsh.option.setNumber("Mesh.RecombineAll", 2)
        bottom = gmsh.model.occ.addRectangle(x0, y0, z0, x1 - x0, y1 - y0)
        top = gmsh.model.occ.addRectangle(x0, y0, z2, x1 - x0, y1 - y0)

        # Set mesh size at point
        gmsh.model.occ.extrude([(2, bottom)],
                               0,
                               0,
                               z1 - z0,
                               numElements=[int(1 / (2 * res))],
                               recombine=True)
        gmsh.model.occ.extrude([(2, top)],
                               0,
                               0,
                               z1 - z2 - 1e-12,
                               numElements=[int(1 / (2 * res))],
                               recombine=True)
        # Syncronize to be able to fetch entities
        gmsh.model.occ.synchronize()

        # Tag faces and volume
        tag_cube_model(gmsh.model, x0, y0, z0, x1, y1, z1, z2, facet_markers,
                       volume_markers)

        # Set mesh sizes on the points from the surface we are extruding
        bottom_nodes = gmsh.model.getBoundary([(2, bottom)],
                                              oriented=False,
                                              recursive=True)
        gmsh.model.occ.mesh.setSize(bottom_nodes, res)
        top_nodes = gmsh.model.getBoundary([(2, top)],
                                           oriented=False,
                                           recursive=True)
        gmsh.model.occ.mesh.setSize(top_nodes, 2 * res)
        # NOTE: Need to synchronize after setting mesh sizes
        gmsh.model.occ.synchronize()
        # Generate mesh
        gmsh.option.setNumber("Mesh.MaxNumThreads1D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads2D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads3D", MPI.COMM_WORLD.size)
        gmsh.model.mesh.generate(3)
        gmsh.model.mesh.setOrder(1)
    mesh, ft = _utils.gmsh_model_to_mesh(gmsh.model, facet_data=True)
    gmsh.clear()
    gmsh.finalize()
    MPI.COMM_WORLD.barrier()
    return mesh, ft
def generate_tet_boxes(
        x0: float,
        y0: float,
        z0: float,
        x1: float,
        y1: float,
        z1: float,
        z2: float,
        res: float,
        facet_markers: Sequence[Sequence[int]],
        volume_markers: Sequence[int],
        verbose: bool = False) -> Tuple[_mesh.Mesh, _cpp.mesh.MeshTags_int32]:
    """
    Generate the stacked boxes [x0,y0,z0]x[y1,y1,z1] and
    [x0,y0,z1] x [x1,y1,z2] with different resolution in each box.
    The markers are is a list of arrays containing markers
    array of markers for [back, bottom, right, left, top, front] per box
    volume_markers a list of marker per volume
    """
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", int(verbose))
    if MPI.COMM_WORLD.rank == 0:
        gmsh.clear()
        # NOTE: Have to reset this until:
        # https://gitlab.onelab.info/gmsh/gmsh/-/issues/1001
        # is in master
        gmsh.option.setNumber("Mesh.RecombineAll", 0)

        # Added tolerance to ensure that gmsh separates boxes
        tol = 1e-12
        gmsh.model.occ.addBox(x0, y0, z0, x1 - x0, y1 - y0, z1 - z0)
        gmsh.model.occ.addBox(x0, y0, z1 + tol, x1 - x0, y1 - y0, z2 - z1)

        # Syncronize to be able to fetch entities
        gmsh.model.occ.synchronize()

        tag_cube_model(gmsh.model, x0, y0, z0, x1, y1, z1, z2, facet_markers,
                       volume_markers)

        gmsh.model.mesh.field.add("Box", 1)
        gmsh.model.mesh.field.setNumber(1, "VIn", res)
        gmsh.model.mesh.field.setNumber(1, "VOut", 2 * res)
        gmsh.model.mesh.field.setNumber(1, "XMin", 0)
        gmsh.model.mesh.field.setNumber(1, "XMax", 1)
        gmsh.model.mesh.field.setNumber(1, "YMin", 0)
        gmsh.model.mesh.field.setNumber(1, "YMax", 1)
        gmsh.model.mesh.field.setNumber(1, "ZMin", 0)
        gmsh.model.mesh.field.setNumber(1, "ZMax", 1)

        gmsh.model.mesh.field.setAsBackgroundMesh(1)
        # NOTE: Need to synchronize after setting mesh sizes
        gmsh.model.occ.synchronize()
        # Generate mesh
        gmsh.option.setNumber("Mesh.MaxNumThreads1D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads2D", MPI.COMM_WORLD.size)
        gmsh.option.setNumber("Mesh.MaxNumThreads3D", MPI.COMM_WORLD.size)
        gmsh.model.mesh.generate(3)
        gmsh.model.mesh.setOrder(1)
    mesh, ft = _utils.gmsh_model_to_mesh(gmsh.model, facet_data=True)
    gmsh.finalize()
    return mesh, ft