hermit.domain

ShellDomain – mesh, shell state space and index maps, built once.

No CSDL, no per-evaluation cost. Carries the mixed state space W, mesh tags and regions, and the file/FE index maps the Field builders need. Deliberately does not depend on ShellPDE: the dependency runs the other way, with hermit._solve handing domain.W to the ShellPDE it caches on the domain.

Classes

ShellDomain

Mesh, shell state space, index maps and region tags, built once.

Functions

read_mesh(path[, name])

Read a mesh from an XDMF file.

Module Contents

class hermit.domain.ShellDomain(mesh, *, element='CG2CG1', cell_tags=None, regions=None, quadrature_degree=4)

Mesh, shell state space, index maps and region tags, built once.

The first object in every Hermit workflow. It carries no CSDL and no per-solve cost, so build it once and reuse it across every load case, sweep or optimizer iteration.

Parameters:
meshdolfinx.mesh.Mesh

A serial, straight-sided (P1 geometry) surface mesh of triangles or quadrilaterals.

element{‘CG2CG1’, ‘CG1CG1’, ‘CG2CR1’}, optional

Displacement x rotation element pair. Default 'CG2CG1'. 'CG2CR1' uses a Crouzeix-Raviart rotation that resists shear locking on thin shells, and is triangle meshes only.

cell_tagsdolfinx.mesh.MeshTags, optional

Cell tags, for per-region output integrals.

regionsdict, optional

Maps region names to tag values, so outputs can take region="skin".

quadrature_degreeint, optional

Degree for every integral this package pins by hand: the penalty-BC facet measures, the stress measures, the DG0 'average' field method and the oriented elastic energy. Default 4, which is deep in the converged regime for the shell integrand.

Attributes:
Wdolfinx.fem.FunctionSpace

The mixed state space for this domain, shared by everything downstream.

n_nodes, n_cellsint
node_coordsndarray

(n_nodes, 3) vertex coordinates in file order.

cell_centroidsndarray

(n_cells, 3) centroids in file order.

node_input_idx, cell_input_idxndarray

File-to-FE gather indices, fe_order = file_order[node_input_idx].

reverse_node_idx, reverse_cell_idxndarray

Their inverses, file_order = fe_order[reverse_node_idx].

Raises:
ValueError

If the mesh is not serial (its input_global_indices must form a node permutation), or if CG1 / DG0 dof order does not coincide with the mesh’s own vertex / cell order.

Notes

Serial meshes only. This is a requirement of every use, not only of the shape-derivative path: an MPI-partitioned mesh raises here, before any solve.

Three coefficient orderings coexist on any mesh: file (the mesh-file vertex and cell numbering, which external arrays use), local (DOLFINx’s post-read reordering) and FE dof (per function space, indexing Function.x.array). from_nodal() and from_cells() take file order and permute; from_coeffs() takes FE dof order directly.

One state space per domain. DOLFINx does not treat two independently built but structurally identical function spaces as interchangeable for boundary conditions: a strong BC located against a second instance is silently dropped, with no exception and a wrong answer. Everything downstream therefore shares domain.W.

Examples

>>> domain = hm.ShellDomain(hm.read_mesh("plate.xdmf"), element="CG2CG1")
check_cell_orientation_consistency(tol=None)

Verify that the cells are consistently wound across shared facets.

Called by pressure() and edge_pressure(), whose sign convention is only well defined on a consistently wound mesh.

The check is topological: two cells sharing an edge are consistently oriented when they traverse it in opposite directions. Unlike comparing the two normals, this does not depend on the angle between the cells, so sharp creases and the corners of a closed box (where adjacent normals are perpendicular, or further apart) pass as long as the winding agrees. Edges shared by three or more cells – shell junctions, such as a rib meeting a skin – carry no orientation constraint and are skipped, as are boundary edges.

Parameters:
tolNone

Deprecated and ignored. It was the normal dot-product threshold of the earlier, geometric check.

Raises:
ValueError

Naming the offending cell pair. Fix the mesh winding upstream, or use traction(), which takes an explicit global vector.

Notes

Cheap and memoized; a no-op after the first successful call.

dof_coords(space)

Coordinates of a space’s scalar dofs, in FE dof order.

Parameters:
spacetuple

(family, degree) or (family, degree, value_shape).

Returns:
ndarray

Shape (n_scalar_dofs, 3). For a blocked (vector or tensor) space these are per scalar dof, not per component: all components of one dof share a coordinate.

See also

hermit.from_coeffs, hermit.from_function

build coefficients on this space.

function_space(space)

The DOLFINx function space for a space descriptor.

Parameters:
spacetuple

(family, degree) or (family, degree, value_shape).

Returns:
dolfinx.fem.FunctionSpace

Memoized, one per normalized descriptor.

local_frames()

The orthonormal local shell frame of every cell.

Returns:
ndarray

Shape (n_cells, 3, 3), rows e0, e1 in-plane and e2 the element normal, at the reference geometry, in FE cell order. Memoized.

local_frames_at(points, cells)

The local shell frame at chosen points inside chosen cells.

Parameters:
pointsarray_like

Reference-cell coordinates: one point broadcast to every query, or one point per query.

cellsarray_like of int

Cell ids in file order.

Returns:
ndarray

Shape (n, 3, 3); see local_frames() for the row convention.

W
cell_centroids
cell_input_idx
cell_tags = None
element = 'CG2CG1'
mesh
n_cells
n_nodes
node_coords
node_input_idx
quadrature_degree = 4
regions
reverse_cell_idx
reverse_node_idx
hermit.domain.read_mesh(path, name='Grid')

Read a mesh from an XDMF file.

Parameters:
pathstr or pathlib.Path
namestr, optional

Grid name inside the file. Default "Grid".

Returns:
dolfinx.mesh.Mesh

Read on MPI.COMM_WORLD. Run serially – ShellDomain requires a serial mesh.

Examples

>>> domain = hm.ShellDomain(hm.read_mesh("plate.xdmf"))