Unstructured Sub Meshes#
- class pybamm.UnstructuredSubMesh(vertices, elements, coord_sys='cartesian', boundary_faces=None)[source]#
Cell-centered finite volume submesh on polygonal/polyhedral elements.
Supported element types:
2D: triangles (3 vertices) or quadrilaterals (4 vertices)
3D: tetrahedra (4 vertices) or hexahedra (8 vertices)
Hexahedra must have planar faces: volumes and face fluxes are ill-defined on warped (non-planar-faced) hexes, so construction raises a
pybamm.GeometryErrorfor them.All operators are dimension-agnostic: the same code path handles both 2D and 3D, with dimension inferred from
vertices.shape[1].- Parameters:
vertices (numpy.ndarray) – Vertex coordinates, of shape
(n_vertices, d)(d = 2 or 3).elements (numpy.ndarray) – Element vertex indices, of shape
(n_cells, n_verts_per_cell). For 2D: 3 (triangles) or 4 (quads). For 3D: 4 (tetrahedra) or 8 (hexahedra).coord_sys (str, optional) – Coordinate system, default
"cartesian".boundary_faces (dict[str, numpy.ndarray] or None, optional) – Maps boundary name to face indices. If
None, no boundary tags are assigned: tags must come from the mesh source (the built-in generator tags its own box output, file generators use the mesh file’s boundary names), or calldetect_box_boundaries()for a hand-built axis-aligned box.
Extends:
pybamm.meshes.meshes.SubMesh- boundary_loops()[source]#
Return boundary loops as a list of
matplotlib.path.Path(2D only).Walks boundary edges to extract one or more closed loops. The first path is the outer boundary (largest area); subsequent paths are holes. Use this to test containment: a point is in the domain if it is inside the outer loop and outside all hole loops.
- classmethod combine(submeshes)[source]#
Weld a list of
UnstructuredSubMeshobjects into one mesh.Coincident boundary nodes at domain interfaces are merged so that face connectivity spans across domains.
- Parameters:
submeshes (list of UnstructuredSubMesh) – The submeshes to combine, in order.
- Returns:
A single mesh covering the union of the input domains.
- Return type:
- contains_points_3d(query_pts)[source]#
Test whether 3D points lie inside the mesh domain.
Uses the generalized winding number (Van Oosterom–Strackee signed solid angle sum over all boundary triangles). Points inside the domain return
True; points outside or inside internal cavities returnFalse.
- detect_box_boundaries()[source]#
Tag boundary faces of an axis-aligned box by outward normal.
Assigns
left/right(x),front/back(y, 3D only), andbottom/top(z) by each exterior face’s dominant normal direction, overwritingboundary_faces. Only meaningful for axis-aligned box domains (each face genuinely normal to one axis); on curved geometry the buckets are not surfaces. The built-in generator calls this on its output; meshes from files should carry their own boundary names instead.
- optimize_ordering()[source]#
Reorder cells using Reverse Cuthill-McKee to reduce Jacobian bandwidth.
Permutes all cell-indexed arrays (elements, centroids, volumes, face_owner, face_neighbor, interface_data) so that adjacent cells have nearby indices, minimising the bandwidth of the FVM connectivity matrix.
- class pybamm.UnstructuredMeshGenerator(coord_sys='cartesian', element_type=None)[source]#
Built-in generator that creates meshes from structured grids.
2D: rectangular domain meshed as quads, or triangulated by splitting each quad into 2 triangles.
3D: rectangular prism meshed as hexahedra, or split into 6 tetrahedra per hex (Kuhn decomposition).
On box domains, hexahedra (the 3D default) are preferred for real simulations: same resolution with 6x fewer cells and ideal face orthogonality. The simplex element types chiefly exercise the same code paths as user-supplied (e.g. gmsh) meshes without needing a mesh file, which is useful for testing and validation.
- Parameters:
Extends:
pybamm.meshes.meshes.MeshGenerator
- class pybamm.UserSuppliedUnstructuredMesh(filepath, subdomain_mapping=None, boundary_mapping=None, coord_sys='cartesian', merge_tolerance=1e-12)[source]#
Load an unstructured mesh from an external file via meshio.
Supported cell types are tetrahedra (3D) and triangles or quadrilaterals (2D). Hexahedral file meshes are rejected: file meshes commonly contain warped (non-planar-faced) hexes, whose volumes and face fluxes are ill-defined. Convert such meshes to tetrahedra before loading.
The interface between adjacent domains must be conforming: the two sides must share the same interface nodes, so that welding in
UnstructuredSubMesh.combine()turns the interface into internal faces. In gmsh, build the regions from one geometry or fragment the parts (BooleanFragments/Coherence) so the shared surface is meshed once. A non-conforming interface raises apybamm.GeometryErrorwhen the domains are combined.- Parameters:
filepath (str) – Path to the mesh file (GMSH
.msh, VTK.vtu, etc.).subdomain_mapping (dict[str, int] or None) – Maps PyBaMM domain name to physical group / cell-data tag.
boundary_mapping (dict[str, int] or None) – Maps boundary name to physical group / facet tag.
coord_sys (str, optional) – Coordinate system, default
"cartesian".merge_tolerance (float or None, optional) – Absolute length (in the mesh file’s units) below which coincident nodes across cell blocks are welded, by quantising coordinates to a grid of this spacing. Default
1e-12; passNoneor0to disable welding.
Extends:
pybamm.meshes.meshes.MeshGenerator
- class pybamm.TaggedSubMeshGenerator(region, mesh_path, scale=1.0, coord_sys='cartesian', boundary_mapping=None)[source]#
Build an
UnstructuredSubMeshfrom cells of a single Gmsh physical group in a.mshfile.Use one instance per region in a multi-domain pybamm model — the region name doubles as the pybamm domain name. Compare to
UserSuppliedUnstructuredMesh, which routes multiple regions through one generator by introspectinglims;TaggedSubMeshGeneratoris simpler when the model already supplies one mesh generator per domain.Regions that share an interface must be conforming across it (the shared surface meshed once, so both regions reference the same interface nodes), or combining the domains raises a
pybamm.GeometryError. Fragment the geometry in gmsh (BooleanFragments/Coherence) to guarantee this.- Parameters:
region (str) – Gmsh physical-group name (key in
meshio.read(...).field_data).mesh_path (str or pathlib.Path) – Path to the
.mshfile.scale (float, optional) – Multiplier applied to mesh node coordinates (e.g.
1e-3to convert mm to m). Default1.0.coord_sys (str, optional) – Coordinate system label, default
"cartesian".boundary_mapping (dict[str, str or int] or None, optional) – Maps boundary name to a gmsh physical surface group, given as its
field_dataname or integer tag. Matching tagged surface triangles become the named entries inboundary_faces. Without it the submesh carries no boundary tags.
Extends:
pybamm.meshes.meshes.MeshGenerator
- pybamm.compute_interface_data(left_mesh, right_mesh, left_name=None, right_name=None)[source]#
Compute coupling data for the interface between two adjacent
UnstructuredSubMeshobjects.Finds “right” boundary faces of left_mesh and “left” boundary faces of right_mesh, matches them by face centroid position, and records cell indices, face areas, and centroid-to-centroid distances.
Domains are assumed to be stacked along x: faces are paired by their transverse (non-x) centroid coordinates.
- Parameters:
left_mesh (UnstructuredSubMesh)
right_mesh (UnstructuredSubMesh)
left_name (str or None) – Domain name of the left mesh (stored as key in
interface_data).right_name (str or None) – Domain name of the right mesh (stored as key in
interface_data).
- Returns:
Keys:
"left_cells","right_cells","face_areas","cell_distances".- Return type: