Multi-entity models

Multi-entity models#

Multiple OCC entities (and polysurfaces or prisms) can be combined in a single model.

import shapely
from OCP.BRepBuilderAPI import (
    BRepBuilderAPI_MakeEdge,
    BRepBuilderAPI_MakeFace,
    BRepBuilderAPI_MakePolygon,
    BRepBuilderAPI_MakeWire,
)
from OCP.GC import GC_MakeCircle
from OCP.gp import gp_Ax2, gp_Dir, gp_Pnt

from meshwell.cad_occ import cad_occ
from meshwell.mesh import mesh
from meshwell.occ_entity import OCC_entity
from meshwell.occ_xao_writer import write_xao
from meshwell.polysurface import PolySurface
from meshwell.visualization import plot2D


def _rectangle(x, y, z, dx, dy):
    def build():
        poly = BRepBuilderAPI_MakePolygon()
        poly.Add(gp_Pnt(x, y, z))
        poly.Add(gp_Pnt(x + dx, y, z))
        poly.Add(gp_Pnt(x + dx, y + dy, z))
        poly.Add(gp_Pnt(x, y + dy, z))
        poly.Close()
        return BRepBuilderAPI_MakeFace(poly.Wire()).Shape()

    return build


def _disk(xc, yc, zc, r):
    """Planar disk (circular face) centered at (xc, yc, zc), axis +Z."""

    def build():
        ax = gp_Ax2(gp_Pnt(xc, yc, zc), gp_Dir(0, 0, 1))
        circle = GC_MakeCircle(ax, r).Value()
        edge = BRepBuilderAPI_MakeEdge(circle).Edge()
        wire = BRepBuilderAPI_MakeWire(edge).Wire()
        return BRepBuilderAPI_MakeFace(wire).Shape()

    return build
/home/runner/work/meshwell/meshwell/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
polygon_hull = shapely.Polygon(
    [[0, 0], [2, 0], [2, 2], [0, 2], [0, 0]],
)
line1 = shapely.LineString([[0.5, 0.5], [1.5, 1.5]])
polygon_hole1 = shapely.buffer(line1, 0.2)
line2 = shapely.LineString([[1.5, 0.5], [0.5, 1.5]])
polygon_hole2 = shapely.buffer(line2, 0.2)
polygon = polygon_hull - polygon_hole1 - polygon_hole2


s_curve = shapely.LineString([[-1, 0], [0, 0.5], [-1, 1], [0, 1.5], [-1, 2]])
s_shape = shapely.buffer(s_curve, 0.2)

poly2D = PolySurface(
    polygons=polygon,
    physical_name="meshwell_polygon",
    mesh_order=1,
)

s = PolySurface(
    polygons=s_shape,
    physical_name="meshwell_s",
    mesh_order=2,
)

disk_entity = OCC_entity(
    occ_function=_disk(xc=2, yc=2, zc=0, r=1),
    physical_name="occ_disk",
    mesh_order=3,
    dimension=2,
)

rectangle = OCC_entity(
    occ_function=_rectangle(x=1.5, y=0, z=0, dx=1, dy=1),
    physical_name="occ_rectangle",
    mesh_order=4,
    dimension=2,
)

entities_list = [poly2D, s, disk_entity, rectangle]

write_xao(cad_occ(entities_list), "complicated.xao")

output_mesh = mesh(
    dim=2,
    input_file="complicated.xao",
    output_file="complicated.msh",
    default_characteristic_length=0.5,
    mesh_element_order=1,  # set to 2 to generate a curved mesh with the disk
)
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'complicated.xao'...
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 163 to curve (distance = 1e-05)
Info    : Done reading 'complicated.xao'
plot2D(output_mesh, wireframe=False)
_images/a155bd17f130a2007bad7eb9b6c68044a423ed5011b81009cdbb8b791218702a.png
plot2D(output_mesh, wireframe=False, physicals=["meshwell_polygon___occ_disk"])
_images/e9c16fe9361a480cfea7f551b83e66f5bb1b306f2ccb8a90178e57b0dfbbf31f.png

mesh_order specifies which entity takes precedence if there is a conflict; lower numbers override higher numbers.

poly2D = PolySurface(
    polygons=polygon,
    physical_name="meshwell_polygon",
    mesh_order=4,
)

s = PolySurface(
    polygons=s_shape,
    physical_name="meshwell_s",
    mesh_order=3,
)

disk_entity = OCC_entity(
    occ_function=_disk(xc=2, yc=2, zc=0, r=1),
    physical_name="occ_disk",
    mesh_order=2,
    dimension=2,
)

rectangle = OCC_entity(
    occ_function=_rectangle(x=1.5, y=0, z=0, dx=1, dy=1),
    physical_name="occ_rectangle",
    mesh_order=1,
    dimension=2,
)

entities_list = [poly2D, s, disk_entity, rectangle]

write_xao(cad_occ(entities_list), "model.xao")

output_mesh = mesh(
    dim=2,
    input_file="model.xao",
    output_file="model.msh",
    default_characteristic_length=0.5,
    mesh_element_order=1,
)
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'model.xao'...
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 154 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 163 to curve (distance = 1e-05)
Info    : Done reading 'model.xao'
plot2D(output_mesh, wireframe=True)
_images/74b56fb9614cebae0867922a6cc1b9834d7daafadeeb5e320d9ae879727525b7.png

By default, all CAD entities get meshed. By setting mesh_bool to False, a CAD entity can be inserted for the purposes of cutting out regions / tagging interfaces, without adding a mesh within a region.

poly2D = PolySurface(
    polygons=polygon,
    physical_name="meshwell_polygon",
    mesh_order=4,
)

s = PolySurface(
    polygons=s_shape,
    physical_name="meshwell_s",
    mesh_order=3,
    mesh_bool=False,
)

disk_entity = OCC_entity(
    occ_function=_disk(xc=2, yc=2, zc=0, r=1),
    physical_name="occ_disk",
    mesh_order=2,
    mesh_bool=False,
    dimension=2,
)

rectangle = OCC_entity(
    occ_function=_rectangle(x=1.5, y=0, z=0, dx=1, dy=1),
    physical_name="occ_rectangle",
    mesh_order=1,
    dimension=2,
)

entities_list = [poly2D, s, disk_entity, rectangle]

write_xao(cad_occ(entities_list), "model.xao")

output_mesh = mesh(
    dim=2,
    input_file="model.xao",
    output_file="model.msh",
    default_characteristic_length=0.5,
    mesh_element_order=1,
)
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'model.xao'...
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 1 to curve (distance = 1e-05)
Info    : Snapping geometry point 77 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 77 to curve (distance = 3.33333e-06)
Info    : Snapping geometry point 82 to curve (distance = 1e-05)
Info    : Done reading 'model.xao'
plot2D(output_mesh, wireframe=True)
_images/77f3be5522915fea8ab9d3f195ccb16c8bb1ab2e096ff6df0db77d3b3245469d.png