Пример #1
0
def xtest_read_write_p2_mesh(tempdir, encoding):
    pygmsh = pytest.importorskip("pygmsh")
    if MPI.COMM_WORLD.rank == 0:
        geom = pygmsh.opencascade.Geometry()
        geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.4)
        pygmsh_mesh = pygmsh.generate_mesh(
            geom, mesh_file_type="vtk", extra_gmsh_arguments=["-order", "2"])
        cells, x = pygmsh_mesh.cells[-1].data, pygmsh_mesh.points
        pygmsh_cell = pygmsh_mesh.cells[-1].type
        cell_type, gdim, num_nodes = MPI.COMM_WORLD.bcast(
            [pygmsh_cell, x.shape[1], cells.shape[1]], root=0)
    else:
        cell_type, gdim, num_nodes = MPI.COMM_WORLD.bcast([None, None, None],
                                                          root=0)
        cells, x = np.empty([0, num_nodes]), np.empty([0, gdim])

    domain = ufl_mesh_from_gmsh(cell_type, gdim)
    cell_type = cpp.mesh.to_type(str(domain.ufl_cell()))
    cells = cells[:, perm_vtk(cell_type, cells.shape[1])]
    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)

    filename = os.path.join(tempdir, "tet10_mesh.xdmf")
    with XDMFFile(mesh.mpi_comm(), filename, "w", encoding=encoding) as xdmf:
        xdmf.write_mesh(mesh)
    with XDMFFile(mesh.mpi_comm(), filename, "r", encoding=encoding) as xdmf:
        mesh2 = xdmf.read_mesh()

    assert mesh.topology.index_map(0).size_global == mesh2.topology.index_map(
        0).size_global
    dim = mesh.topology.dim
    assert mesh.topology.index_map(
        dim).size_global == mesh2.topology.index_map(dim).size_global
Пример #2
0
def test_gmsh_input_3d(order, cell_type):
    try:
        import gmsh
    except ImportError:
        pytest.skip()
    if cell_type == CellType.hexahedron and order > 2:
        pytest.xfail("GMSH permutation for order > 2 hexahedra not implemented in DOLFINx.")

    res = 0.2

    gmsh.initialize()
    if cell_type == CellType.hexahedron:
        gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
        gmsh.option.setNumber("Mesh.RecombineAll", 2)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", res)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", res)

    circle = gmsh.model.occ.addDisk(0, 0, 0, 1, 1)

    if cell_type == CellType.hexahedron:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5], recombine=True)
    else:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5])
    gmsh.model.occ.synchronize()

    gmsh.model.mesh.generate(3)
    gmsh.model.mesh.setOrder(order)

    idx, points, _ = gmsh.model.mesh.getNodes()
    points = points.reshape(-1, 3)
    idx -= 1
    srt = np.argsort(idx)
    assert np.all(idx[srt] == np.arange(len(idx)))
    x = points[srt]

    element_types, element_tags, node_tags = gmsh.model.mesh.getElements(dim=3)
    name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
        element_types[0])

    cells = node_tags[0].reshape(-1, num_nodes) - 1
    if cell_type == CellType.tetrahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("tetrahedron", order), root=0)
    elif cell_type == CellType.hexahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("hexahedron", order), root=0)
    gmsh.finalize()

    # Permute the mesh topology from GMSH ordering to DOLFINx ordering
    domain = ufl_mesh_from_gmsh(gmsh_cell_id, 3)
    cells = cells[:, perm_gmsh(cell_type, cells.shape[1])]

    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)

    volume = assemble_scalar(form(1 * dx(mesh)))

    assert mesh.comm.allreduce(volume, op=MPI.SUM) == pytest.approx(np.pi, rel=10 ** (-1 - order))
Пример #3
0
def test_read_write_p2_mesh(tempdir, encoding):
    try:
        import gmsh
    except ImportError:
        pytest.skip()
    if MPI.COMM_WORLD.rank == 0:
        gmsh.initialize()
        gmsh.model.occ.addSphere(0, 0, 0, 1, tag=1)
        gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.3)
        gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 0.4)
        gmsh.model.occ.synchronize()
        gmsh.model.mesh.generate(3)
        gmsh.model.mesh.setOrder(2)

        idx, points, _ = gmsh.model.mesh.getNodes()
        points = points.reshape(-1, 3)
        idx -= 1
        srt = np.argsort(idx)
        assert np.all(idx[srt] == np.arange(len(idx)))
        x = points[srt]

        element_types, element_tags, node_tags = gmsh.model.mesh.getElements(
            dim=3)
        name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
            element_types[0])
        cells = node_tags[0].reshape(-1, num_nodes) - 1
        num_nodes, gmsh_cell_id = MPI.COMM_WORLD.bcast(
            [cells.shape[1],
             gmsh.model.mesh.getElementType("tetrahedron", 2)],
            root=0)
        gmsh.finalize()

    else:
        num_nodes, gmsh_cell_id = MPI.COMM_WORLD.bcast([None, None], root=0)
        cells, x = np.empty([0, num_nodes]), np.empty([0, 3])

    domain = ufl_mesh_from_gmsh(gmsh_cell_id, 3)
    cell_type = _cpp.mesh.to_type(str(domain.ufl_cell()))
    cells = cells[:, perm_gmsh(cell_type, cells.shape[1])]

    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)

    filename = os.path.join(tempdir, "tet10_mesh.xdmf")
    with XDMFFile(mesh.comm, filename, "w", encoding=encoding) as xdmf:
        xdmf.write_mesh(mesh)
    with XDMFFile(mesh.comm, filename, "r", encoding=encoding) as xdmf:
        mesh2 = xdmf.read_mesh()

    assert mesh.topology.index_map(0).size_global == mesh2.topology.index_map(
        0).size_global
    assert mesh.topology.index_map(
        mesh.topology.dim).size_global == mesh2.topology.index_map(
            mesh.topology.dim).size_global
Пример #4
0
def test_gmsh_input_2d(order, cell_type):
    try:
        import gmsh
    except ImportError:
        pytest.skip()
    res = 0.2
    gmsh.initialize()
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", res)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", res)

    if cell_type == CellType.quadrilateral:
        gmsh.option.setNumber("Mesh.Algorithm", 2 if order == 2 else 5)

    gmsh.model.occ.addSphere(0, 0, 0, 1, tag=1)
    gmsh.model.occ.synchronize()

    gmsh.model.mesh.generate(2)
    if cell_type == CellType.quadrilateral:
        gmsh.model.mesh.recombine()
    gmsh.model.mesh.setOrder(order)
    idx, points, _ = gmsh.model.mesh.getNodes()
    points = points.reshape(-1, 3)
    idx -= 1
    srt = np.argsort(idx)
    assert np.all(idx[srt] == np.arange(len(idx)))
    x = points[srt]

    element_types, element_tags, node_tags = gmsh.model.mesh.getElements(dim=2)
    name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
        element_types[0])

    cells = node_tags[0].reshape(-1, num_nodes) - 1
    if cell_type == CellType.triangle:
        gmsh_cell_id = gmsh.model.mesh.getElementType("triangle", order)
    elif cell_type == CellType.quadrilateral:
        gmsh_cell_id = gmsh.model.mesh.getElementType("quadrangle", order)
    gmsh.finalize()

    cells = cells[:, perm_gmsh(cell_type, cells.shape[1])]
    mesh = create_mesh(MPI.COMM_WORLD, cells, x,
                       ufl_mesh_from_gmsh(gmsh_cell_id, x.shape[1]))
    surface = assemble_scalar(1 * dx(mesh))

    assert mesh.mpi_comm().allreduce(surface, op=MPI.SUM) == pytest.approx(
        4 * np.pi, rel=10**(-1 - order))
Пример #5
0
def test_gmsh_input_quad(order):
    pygmsh = pytest.importorskip("pygmsh")

    # Parameterize test if gmsh gets wider support
    R = 1
    res = 0.2 if order == 2 else 0.2
    algorithm = 2 if order == 2 else 5

    geo = pygmsh.opencascade.Geometry()
    geo.add_raw_code("Mesh.ElementOrder={0:d};".format(order))
    geo.add_ball([0, 0, 0], R, char_length=res)
    geo.add_raw_code("Recombine Surface {1};")
    geo.add_raw_code("Mesh.Algorithm = {0:d};".format(algorithm))
    msh = pygmsh.generate_mesh(geo, verbose=True, dim=2)

    gmsh_quad = perm_gmsh(cpp.mesh.CellType.quadrilateral, (order + 1)**2)
    cells = msh.cells[-1].data[:, gmsh_quad]
    mesh = create_mesh(MPI.COMM_WORLD, cells, msh.points,
                       ufl_mesh_from_gmsh(msh.cells[-1].type, msh.points.shape[1]))
    surface = assemble_scalar(1 * dx(mesh))
    assert mesh.mpi_comm().allreduce(surface, op=MPI.SUM) == pytest.approx(4 * np.pi * R * R, rel=1e-5)
Пример #6
0
def test_gmsh_input_quad(order):
    gmsh = pytest.importorskip("gmsh")
    R = 1
    res = 0.2
    algorithm = 2 if order == 2 else 5
    gmsh.initialize()
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", res)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", res)
    gmsh.option.setNumber("Mesh.Algorithm", algorithm)

    gmsh.model.occ.addSphere(0, 0, 0, 1, tag=1)
    gmsh.model.occ.synchronize()

    gmsh.model.mesh.generate(2)
    gmsh.model.mesh.recombine()
    gmsh.model.mesh.setOrder(order)
    idx, points, _ = gmsh.model.mesh.getNodes()
    points = points.reshape(-1, 3)
    idx -= 1
    srt = np.argsort(idx)
    assert np.all(idx[srt] == np.arange(len(idx)))
    x = points[srt]

    element_types, element_tags, node_tags = gmsh.model.mesh.getElements(dim=2)
    name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
        element_types[0])

    cells = node_tags[0].reshape(-1, num_nodes) - 1
    gmsh_cell_id = gmsh.model.mesh.getElementType("quadrangle", order)
    gmsh.finalize()

    gmsh_quad = perm_gmsh(cpp.mesh.CellType.quadrilateral, (order + 1)**2)
    cells = cells[:, gmsh_quad]
    mesh = create_mesh(MPI.COMM_WORLD, cells, x,
                       ufl_mesh_from_gmsh(gmsh_cell_id, x.shape[1]))
    surface = assemble_scalar(1 * dx(mesh))

    assert mesh.mpi_comm().allreduce(surface, op=MPI.SUM) == pytest.approx(
        4 * np.pi * R * R, rel=1e-5)
Пример #7
0
# Generate mesh
model.occ.synchronize()
model.mesh.generate(3)

# Sort mesh nodes according to their index in gmsh (Starts at 1)
x = extract_gmsh_geometry(model, model_name="Sphere")

# Extract cells from gmsh (Only interested in tetrahedrons)
element_types, element_tags, node_tags = model.mesh.getElements(dim=3)
assert len(element_types) == 1
name, dim, order, num_nodes, local_coords, num_first_order_nodes = model.mesh.getElementProperties(
    element_types[0])
cells = node_tags[0].reshape(-1, num_nodes) - 1

mesh = create_mesh(MPI.COMM_SELF, cells, x,
                   ufl_mesh_from_gmsh(element_types[0], x.shape[1]))

with XDMFFile(MPI.COMM_SELF, "mesh_rank_{}.xdmf".format(MPI.COMM_WORLD.rank),
              "w") as file:
    file.write_mesh(mesh)

# Create a distributed (parallel) mesh with affine geometry.
# Generate mesh on rank 0, then build a distributed mesh ::

if MPI.COMM_WORLD.rank == 0:
    # Generate a mesh

    model.add("Sphere minus box")
    model.setCurrent("Sphere minus box")

    sphere_dim_tags = model.occ.addSphere(0, 0, 0, 1)
Пример #8
0
def gmsh_model_to_mesh(model, cell_data=False, facet_data=False, gdim=None, exportMesh=False, fileName="mesh.msh"):
    """
    Given a GMSH model, create a DOLFIN-X mesh and MeshTags. Can theoretically export to msh file
        model: The GMSH model
        cell_data: Boolean, True of a mesh tag for cell data should be returned
                   (Default: False)
        facet_data: Boolean, True if a mesh tag for facet data should be
                    returned (Default: False)
        gdim: Geometrical dimension of problem (Default: 3)
    """

    if gdim is None:
        gdim = 3

    if MPI.COMM_WORLD.rank == 0:
        # Get mesh geometry
        x = extract_gmsh_geometry(model)

        # Get mesh topology for each element
        topologies = extract_gmsh_topology_and_markers(model)

        # Get information about each cell type from the msh files
        num_cell_types = len(topologies.keys())
        cell_information = {}
        cell_dimensions = numpy.zeros(num_cell_types, dtype=numpy.int32)
        for i, element in enumerate(topologies.keys()):
            properties = model.mesh.getElementProperties(element)
            name, dim, order, num_nodes, local_coords, _ = properties
            cell_information[i] = {
                "id": element,
                "dim": dim,
                "num_nodes": num_nodes
            }
            cell_dimensions[i] = dim

        # Sort elements by ascending dimension
        perm_sort = numpy.argsort(cell_dimensions)

        # Broadcast cell type data and geometric dimension
        cell_id = cell_information[perm_sort[-1]]["id"]
        tdim = cell_information[perm_sort[-1]]["dim"]
        num_nodes = cell_information[perm_sort[-1]]["num_nodes"]
        cell_id, num_nodes = MPI.COMM_WORLD.bcast([cell_id, num_nodes], root=0)

        # Check for facet data and broadcast if found
        if facet_data:
            if tdim - 1 in cell_dimensions:
                num_facet_nodes = MPI.COMM_WORLD.bcast(
                    cell_information[perm_sort[-2]]["num_nodes"], root=0)
                gmsh_facet_id = cell_information[perm_sort[-2]]["id"]
                marked_facets = numpy.asarray(
                    topologies[gmsh_facet_id]["topology"], dtype=numpy.int64)
                facet_values = numpy.asarray(
                    topologies[gmsh_facet_id]["cell_data"], dtype=numpy.int32)
            else:
                raise ValueError("No facet data found in file.")

        cells = numpy.asarray(topologies[cell_id]["topology"],
                              dtype=numpy.int64)
        cell_values = numpy.asarray(topologies[cell_id]["cell_data"],
                                    dtype=numpy.int32)

    else:
        cell_id, num_nodes = MPI.COMM_WORLD.bcast([None, None], root=0)
        cells, x = numpy.empty([0, num_nodes],
                               dtype=numpy.int32), numpy.empty([0, gdim])
        cell_values = numpy.empty((0, ), dtype=numpy.int32)
        if facet_data:
            num_facet_nodes = MPI.COMM_WORLD.bcast(None, root=0)
            marked_facets = numpy.empty((0, num_facet_nodes),
                                        dtype=numpy.int32)
            facet_values = numpy.empty((0, ), dtype=numpy.int32)

    # Create distributed mesh
    ufl_domain = ufl_mesh_from_gmsh(cell_id, gdim)
    gmsh_cell_perm = perm_gmsh(to_type(str(ufl_domain.ufl_cell())), num_nodes)
    cells = cells[:, gmsh_cell_perm]
    mesh = create_mesh(MPI.COMM_WORLD, cells, x[:, :gdim], ufl_domain)
    # Create MeshTags for cells
    if cell_data:
        local_entities, local_values = distribute_entity_data(
            mesh, mesh.topology.dim, cells, cell_values)
        mesh.topology.create_connectivity(mesh.topology.dim, 0)
        adj = AdjacencyList_int32(local_entities)
        ct = create_meshtags(mesh, mesh.topology.dim, adj,
                             numpy.int32(local_values))
        ct.name = "cells"

    # Create MeshTags for facets
    if facet_data:
        # Permute facets from MSH to Dolfin-X ordering
        # FIXME: This does not work for prism meshes
        facet_type = cell_entity_type(to_type(str(ufl_domain.ufl_cell())),
                                      mesh.topology.dim - 1, 0)
        gmsh_facet_perm = perm_gmsh(facet_type, num_facet_nodes)
        marked_facets = marked_facets[:, gmsh_facet_perm]

        local_entities, local_values = distribute_entity_data(
            mesh, mesh.topology.dim - 1, marked_facets, facet_values)
        mesh.topology.create_connectivity(mesh.topology.dim - 1,
                                          mesh.topology.dim)
        adj = AdjacencyList_int32(local_entities)
        ft = create_meshtags(mesh, mesh.topology.dim - 1, adj,
                             numpy.int32(local_values))
        ft.name = "facets"

    if exportMesh:
        gmsh.write(fileName)

    if cell_data and facet_data:
        return mesh, ct, ft
    elif cell_data and not facet_data:
        return mesh, ct
    elif not cell_data and facet_data:
        return mesh, ft
    else:
        return mesh
Пример #9
0
# Generate mesh
model.occ.synchronize()
model.mesh.generate(3)


# Sort mesh nodes according to their index in gmsh (Starts at 1)
x = extract_gmsh_geometry(model, model_name="Sphere")

# Extract cells from gmsh (Only interested in tetrahedrons)
element_types, element_tags, node_tags = model.mesh.getElements(dim=3)
assert len(element_types) == 1
name, dim, order, num_nodes, local_coords, num_first_order_nodes = model.mesh.getElementProperties(element_types[0])
cells = node_tags[0].reshape(-1, num_nodes) - 1

mesh = create_mesh(MPI.COMM_SELF, cells, x, ufl_mesh_from_gmsh(element_types[0], x.shape[1]))

with XDMFFile(MPI.COMM_SELF, "mesh_rank_{}.xdmf".format(MPI.COMM_WORLD.rank), "w") as file:
    file.write_mesh(mesh)

# Create a distributed (parallel) mesh with affine geometry.
# Generate mesh on rank 0, then build a distributed mesh ::

if MPI.COMM_WORLD.rank == 0:
    # Generate a mesh

    model.add("Sphere minus box")
    model.setCurrent("Sphere minus box")

    sphere_dim_tags = model.occ.addSphere(0, 0, 0, 1)
    box_dim_tags = model.occ.addBox(0, 0, 0, 1, 1, 1)
Пример #10
0
def gmsh_to_dolfin(gmsh_model,
                   tdim: int,
                   comm=MPI.COMM_WORLD,
                   prune_y=False,
                   prune_z=False):
    """Converts a gmsh model object into `dolfinx.Mesh` and `dolfinx.MeshTags`
    for physical tags.

    Parameters
    ----------
    gmsh_model
    tdim
        Topological dimension of the mesh
    comm: optional
    ghost_mode: optional
    prune_y: optional
        Prune y-components. Used to embed a flat geometries into lower dimension.
    prune_z: optional
        Prune z-components. Used to embed a flat geometries into lower dimension.

    Note
    ----
    User must call `geo.synchronize()` and `mesh.generate()` before passing the model into
    this method.
    """

    rank = comm.rank

    logger = logging.getLogger("dolfiny")

    if rank == 0:
        # Map from internal gmsh cell type number to gmsh cell name
        # see https://gitlab.onelab.info/gmsh/gmsh/blob/master/Common/GmshDefines.h#L75
        gmsh_cellname = {
            1: 'line',
            2: 'triangle',
            3: "quad",
            4: 'tetra',
            5: "hexahedron",
            8: 'line3',
            9: 'triangle6',
            10: "quad9",
            11: 'tetra10',
            12: 'hexahedron27',
            15: 'vertex',
            21: 'triangle10',
            26: 'line4',
            29: 'tetra20',
            36: 'quad16',
            #  92: 'hexahedron64',
        }

        gmsh_dolfin = {
            "vertex": (CellType.point, 0),
            "line": (CellType.interval, 1),
            "line3": (CellType.interval, 2),
            "line4": (CellType.interval, 3),
            "triangle": (CellType.triangle, 1),
            "triangle6": (CellType.triangle, 2),
            "triangle10": (CellType.triangle, 3),
            "quad": (CellType.quadrilateral, 1),
            "quad9": (CellType.quadrilateral, 2),
            "quad16": (CellType.quadrilateral, 3),
            "tetra": (CellType.tetrahedron, 1),
            "tetra10": (CellType.tetrahedron, 2),
            "tetra20": (CellType.tetrahedron, 3),
            "hexahedron": (CellType.hexahedron, 1),
            "hexahedron27": (CellType.hexahedron, 2),
            #  "hexahedron64": (CellType.hexahedron, 3),
        }

        # Number of nodes for gmsh cell type
        nodes = {
            'vertex': 1,
            'line': 2,
            'line3': 3,
            'line4': 4,
            'triangle': 3,
            'triangle6': 6,
            'triangle10': 10,
            'tetra': 4,
            'tetra10': 10,
            'tetra20': 20,
            'quad': 4,
            'quad9': 9,
            'quad16': 16,
            'hexahedron': 8,
            'hexahedron27': 27,
            #  'hexahedron64': 64,
        }

        # node_tags, coord, param_coords = gmsh_model.mesh.getNodes()

        # FIXME: This silences the RuntimeWarning (ctypes / PEP3118 format string) caused by Gmsh/numpy
        import warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", RuntimeWarning)
            node_tags, coord, param_coords = gmsh_model.mesh.getNodes()

        # Fetch elements for the mesh
        cell_types, cell_tags, cell_node_tags = gmsh_model.mesh.getElements(
            dim=tdim)

        unused_nodes = numpy.setdiff1d(node_tags, cell_node_tags)
        unused_nodes_indices = []

        # FIXME: This would be expensive for many unused nodes case
        for unused_node in unused_nodes:
            unused_nodes_indices.append(
                numpy.where(node_tags == unused_node)[0])

        unused_nodes_indices = numpy.asarray(unused_nodes_indices)

        # Every node has 3 components in gmsh
        dim = 3
        points = numpy.reshape(coord, (-1, dim))

        # Delete unreferenced nodes
        points = numpy.delete(points, unused_nodes_indices, axis=0)
        node_tags = numpy.delete(node_tags, unused_nodes_indices)

        # Prepare a map from node tag to index in coords array
        nmap = numpy.argsort(node_tags - 1)
        cells = {}

        if len(cell_types) > 1:
            raise RuntimeError("Mixed topology meshes not supported.")

        try:
            cellname = gmsh_cellname[cell_types[0]]
        except KeyError:
            raise RuntimeError(
                f"Gmsh cell code {cell_types[0]:d} not supported.")

        try:
            num_nodes = nodes[cellname]
        except KeyError:
            raise RuntimeError(
                f"Cannot determine number of nodes for Gmsh cell type \"{cellname:s}\"."
            )

        logger.info(f"Processing mesh of gmsh cell name \"{cellname:s}\"")

        # Shift 1-based numbering and apply node map
        cells[cellname] = nmap[cell_node_tags[0] - 1]
        cells[cellname] = numpy.reshape(cells[cellname], (-1, num_nodes))

        if prune_z:
            if not numpy.allclose(points[:, 2], 0.0):
                raise RuntimeError("Non-zero z-component would be pruned.")

            points = points[:, :-1]

        if prune_y:
            if not numpy.allclose(points[:, 1], 0.0):
                raise RuntimeError("Non-zero y-component would be pruned.")

            if prune_z:
                # In the case we already pruned z-component
                points = points[:, 0]
            else:
                points = points[:, [0, 2]]

        try:
            dolfin_cell_type, order = gmsh_dolfin[cellname]
        except KeyError:
            raise RuntimeError(
                f"Cannot determine dolfin cell type for Gmsh cell type \"{cellname:s}\"."
            )

        perm = cpp.io.perm_gmsh(dolfin_cell_type, num_nodes)
        logger.info(f"Mesh will be permuted with {perm}")
        cells = cells[cellname][:, perm]

        logger.info(
            f"Constructing mesh for tdim: {tdim:d}, gdim: {points.shape[1]:d}")
        logger.info(f"Number of elements: {cells.shape[0]:d}")

        cells_shape, pts_shape, cellname = comm.bcast(
            [cells.shape, points.shape, cellname], root=0)
    else:
        cells_shape, pts_shape, cellname = comm.bcast([None, None, None],
                                                      root=0)
        cells = numpy.empty((0, cells_shape[1]))
        points = numpy.empty((0, pts_shape[1]))

    mesh = create_mesh(comm, cells, points,
                       ufl_mesh_from_gmsh(cellname, pts_shape[1]))
    mts = {}

    # Get physical groups (dimension, tag)
    pgdim_pgtags = comm.bcast(
        gmsh_model.getPhysicalGroups() if rank == 0 else None, root=0)

    for pgdim, pgtag in pgdim_pgtags:

        # For the current physical tag there could be multiple entities
        # e.g. user tagged bottom and up boundary part with one physical tag
        entity_tags = comm.bcast(gmsh_model.getEntitiesForPhysicalGroup(
            pgdim, pgtag) if rank == 0 else None,
                                 root=0)
        pg_tag_name = comm.bcast(
            gmsh_model.getPhysicalName(pgdim, pgtag) if rank == 0 else None,
            root=0)

        if pg_tag_name == "":
            pg_tag_name = f"tag_{pgtag:d}"

        if rank == 0:

            _mt_cells = []
            _mt_values = []

            for i, entity_tag in enumerate(entity_tags):
                pgcell_types, pgcell_tags, pgnode_tags = gmsh_model.mesh.getElements(
                    pgdim, entity_tag)

                assert (len(pgcell_types) == 1)
                pgcellname = gmsh_cellname[pgcell_types[0]]
                pgnum_nodes = nodes[pgcellname]

                # Shift 1-based numbering and apply node map
                pgnode_tags[0] = nmap[pgnode_tags[0] - 1]
                _mt_cells.append(pgnode_tags[0].reshape(-1, pgnum_nodes))
                _mt_values.append(
                    numpy.full(_mt_cells[-1].shape[0],
                               pgtag,
                               dtype=numpy.int32))

            # Stack all topology and value data. This prepares data
            # for one MVC per (dim, physical tag) instead of multiple MVCs
            _mt_values = numpy.hstack(_mt_values)
            _mt_cells = numpy.vstack(_mt_cells)

            # Fetch the permutation needed for physical group
            pgdolfin_cell_type, pgorder = gmsh_dolfin[pgcellname]
            pgpermutation = cpp.io.perm_gmsh(pgdolfin_cell_type, pgnum_nodes)

            _mt_cells[:, :] = _mt_cells[:, pgpermutation]

            logger.info(f"Constructing MVC for tdim: {pgdim:d}")
            logger.info(f"Number of data values: {_mt_values.shape[0]:d}")

            mt_cells_shape, pgdim = comm.bcast([_mt_cells.shape, pgdim],
                                               root=0)
        else:
            mt_cells_shape, pgdim = comm.bcast([None, None], root=0)
            _mt_cells = numpy.empty((0, mt_cells_shape[1]))
            _mt_values = numpy.empty((0, ))

        local_entities, local_values = extract_local_entities(
            mesh, pgdim, _mt_cells, _mt_values)

        mesh.topology.create_connectivity(pgdim, 0)

        mt = create_meshtags(mesh, pgdim,
                             cpp.graph.AdjacencyList_int32(local_entities),
                             numpy.int32(local_values))
        mt.name = pg_tag_name

        mts[pg_tag_name] = mt

    return mesh, mts
Пример #11
0
def build_piston(n, length, radius, write_file=False, fname=""):
    """
    Build a hex cylinder mesh using gmsh
    """
    gmsh.initialize()
    gmsh.option.setNumber("General.Terminal", 0)
    model = gmsh.model()

    if MPI.COMM_WORLD.rank == 0:
        model.add("Piston")
        model.setCurrent("Piston")

        h = length / n

        gmsh.option.setNumber("Mesh.RecombineAll", 2)
        gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
        gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.98 * h)
        gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 1.02 * h)

        circle = model.occ.addDisk(0, 0, 0, radius, radius)
        model.occ.rotate([(2, circle)], 0., 0., 0., 0., 1., 0., np.pi / 2)
        model.occ.extrude([(2, circle)],
                          length,
                          0,
                          0,
                          numElements=[n],
                          recombine=True)

        model.occ.synchronize()
        model.mesh.generate(3)

        # sort mesh according to their index in gmsh
        x = extract_gmsh_geometry(model, model.getCurrent())

        # extract cells from gmsh
        element_types, element_tags, node_tags = model.mesh.getElements(dim=3)
        name, dim, order, num_nodes, local_coords, num_first_order_nodes = \
            model.mesh.getElementProperties(element_types[0])

        # broadcast cell type data and geometric dimension
        gmsh_cell_id = MPI.COMM_WORLD.bcast(element_types[0], root=0)

        # get mesh data for dim (0, tdim)
        cells = node_tags[0].reshape(-1, num_nodes) - 1

        num_nodes = MPI.COMM_WORLD.bcast(cells.shape[1], root=0)
        gmsh.finalize()
    else:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(None, root=0)
        num_nodes = MPI.COMM_WORLD.bcast(None, root=0)
        cells, x = np.empty([0, num_nodes]), np.empty([0, 3])

    # permute the mesh topology from GMSH ordering to DOLFIN-X ordering
    domain = ufl_mesh_from_gmsh(gmsh_cell_id, 3)
    gmsh_hex = perm_gmsh(cpp.mesh.CellType.hexahedron, 8)
    cells = cells[:, gmsh_hex]

    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)
    mesh.name = "piston_hex"

    if write_file:
        with XDMFFile(MPI.COMM_WORLD, "{}.xdmf".format(fname), "w") as file:
            file.write_mesh(mesh)

    return mesh
    cells = topologies[gmsh_cell_id]["topology"]
    cell_data = topologies[gmsh_cell_id]["cell_data"]
    num_nodes = MPI.COMM_WORLD.bcast(cells.shape[1], root=0)
    gmsh_facet_id = gmsh.model.mesh.getElementType("line", 2)
    marked_facets = topologies[gmsh_facet_id]["topology"].astype(np.int64)
    facet_values = topologies[gmsh_facet_id]["cell_data"].astype(np.int32)
else:
    # Create dolfinx mesh on other processes
    gmsh_cell_id = MPI.COMM_WORLD.bcast(None, root=0)
    num_nodes = MPI.COMM_WORLD.bcast(None, root=0)
    cells, x = np.empty([0, num_nodes]), np.empty([0, 3])
    marked_facets = np.empty((0, 3), dtype=np.int64)
    facet_values = np.empty((0,), dtype=np.int32)

# Permute the topology from GMSH to DOLFINx ordering
domain = ufl_mesh_from_gmsh(gmsh_cell_id, 2)
gmsh_tri6 = perm_gmsh(cpp.mesh.CellType.triangle, cells.shape[1])
cells = cells[:, gmsh_tri6]
mesh = create_mesh(MPI.COMM_WORLD, cells, x[:, :2], domain)

# Permute also entities which are tagged
gmsh_line3 = perm_gmsh(cpp.mesh.CellType.interval, 3)
marked_facets = marked_facets[:, gmsh_line3]

local_entities, local_values = extract_local_entities(
    mesh, 1, marked_facets, facet_values)
mesh.topology.create_connectivity(1, 0)
mt = create_meshtags(mesh, 1,
                     cpp.graph.AdjacencyList_int32(local_entities),
                     np.int32(local_values))
Пример #13
0
def gmsh_model_to_mesh(model, gdim):
    """
    Given a GMSH model, create a DOLFINx mesh and MeshTags.

    Parameters
    ----------
    model : gmsh.model
        The GMSH model.
    gdim: int
        Geometrical dimension of problem.

    Author
    ----------
    J. S. Dokken, http://jsdokken.com/converted_files/tutorial_gmsh.html
    """

    assert MPI.COMM_WORLD.size == 1, "This function has been simplified to the case of serial computations"

    # Get mesh geometry
    x = extract_gmsh_geometry(model)

    # Get mesh topology for each element
    topologies = extract_gmsh_topology_and_markers(model)

    # Get information about each cell type from the msh files
    num_cell_types = len(topologies.keys())
    cell_information = {}
    cell_dimensions = np.zeros(num_cell_types, dtype=np.int32)
    for i, element in enumerate(topologies.keys()):
        properties = model.mesh.getElementProperties(element)
        name, dim, order, num_nodes, coords, _ = properties
        cell_information[i] = {
            "id": element,
            "dim": dim,
            "num_nodes": num_nodes
        }
        cell_dimensions[i] = dim

    # Sort elements by ascending dimension
    perm_sort = np.argsort(cell_dimensions)

    # Get cell type data and geometric dimension
    cell_id = cell_information[perm_sort[-1]]["id"]
    tdim = cell_information[perm_sort[-1]]["dim"]
    num_nodes = cell_information[perm_sort[-1]]["num_nodes"]
    cells = np.asarray(topologies[cell_id]["topology"], dtype=np.int64)
    cell_values = np.asarray(topologies[cell_id]["cell_data"], dtype=np.int32)

    # Look up facet data
    assert tdim - 1 in cell_dimensions
    num_facet_nodes = cell_information[perm_sort[-2]]["num_nodes"]
    gmsh_facet_id = cell_information[perm_sort[-2]]["id"]
    marked_facets = np.asarray(topologies[gmsh_facet_id]["topology"],
                               dtype=np.int64)
    facet_values = np.asarray(topologies[gmsh_facet_id]["cell_data"],
                              dtype=np.int32)

    # Create distributed mesh
    ufl_domain = ufl_mesh_from_gmsh(cell_id, gdim)
    gmsh_cell_perm = perm_gmsh(to_type(str(ufl_domain.ufl_cell())), num_nodes)
    cells = cells[:, gmsh_cell_perm]
    mesh = create_mesh(MPI.COMM_WORLD, cells, x[:, :gdim], ufl_domain)

    # Create MeshTags for cells
    entities, values = distribute_entity_data(mesh, mesh.topology.dim, cells,
                                              cell_values)
    mesh.topology.create_connectivity(mesh.topology.dim, 0)
    adj = AdjacencyList_int32(entities)
    ct = meshtags_from_entities(mesh, mesh.topology.dim, adj, np.int32(values))
    ct.name = "Cell tags"

    # Create MeshTags for facets
    facet_type = cell_entity_type(to_type(str(ufl_domain.ufl_cell())),
                                  mesh.topology.dim - 1, 0)
    gmsh_facet_perm = perm_gmsh(facet_type, num_facet_nodes)
    marked_facets = marked_facets[:, gmsh_facet_perm]

    entities, values = distribute_entity_data(mesh, mesh.topology.dim - 1,
                                              marked_facets, facet_values)
    mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
    adj = AdjacencyList_int32(entities)
    ft = meshtags_from_entities(mesh, mesh.topology.dim - 1, adj,
                                np.int32(values))
    ft.name = "Facet tags"

    return mesh, ct, ft
Пример #14
0
# Generating a mesh on each process rank
# ======================================
#
# Generate a mesh on each rank with pygmsh, and create a DOLFIN-X mesh
# on each rank

# Interface needs updating for (py)msh API change
sys.exit(0)

geom = pygmsh.opencascade.Geometry()
geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2)
pygmsh_mesh = pygmsh.generate_mesh(geom)
cells, x = pygmsh_mesh.cells[-1].data, pygmsh_mesh.points
pygmsh_cell = pygmsh_mesh.cells[-1].type
mesh = create_mesh(MPI.COMM_SELF, cells, x,
                   ufl_mesh_from_gmsh(pygmsh_cell, x.shape[1]))

with XDMFFile(MPI.COMM_SELF, "mesh_rank_{}.xdmf".format(MPI.COMM_WORLD.rank),
              "w") as file:
    file.write_mesh(mesh)

# Create a distributed (parallel) mesh with affine geometry
# =========================================================
#
# Generate mesh on rank 0, then build a distributed mesh

if MPI.COMM_WORLD.rank == 0:
    # Generate a mesh
    geom = pygmsh.opencascade.Geometry()
    ball = geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2)
    box = geom.add_box([0.0, 0.0, 0.0], [1.0, 1.0, 1.0])