hermit.bcs

BoundaryConditions – the BC builders clamp / pin / symmetry / gauge, compiled once against a hermit.ShellDomain.

No CSDL is involved, so a compiled BoundaryConditions survives across every solve for its domain. Two enforcement paths are available: a penalty term over the selected facets (the default; it eliminates no dofs and supports several independently masked regions in one form) and strong Dirichlet constraints (method="strong"). The penalty scale is large, so under a large geometry perturbation the strong path conditions better – see the shape-derivative docs.

Selecting a region: where

where is the raw DOLFINx entity locator, Callable[[ndarray], ndarray[bool]], receiving coordinates of shape (3, N) and returning an (N,) boolean mask. Two helpers build the common cases:

  • near() – x[axis] == value within an absolute tolerance.

  • on_plane() – points on a plane through a point with a given normal, which need not be axis-aligned.

Prescribed values

Every builder takes value= – a scalar, a (6,) vector over (ux, uy, uz, rx, ry, rz), or a callable returning (N, 6) for its (N, 3) coordinates. It defaults to zero. A csdl.Variable is deliberately not accepted: an enforced displacement is interpolated once, not carried as a differentiable solve input, so it cannot be a design variable. Loads and material properties can.

The symmetry mask

On a symmetry plane with unit normal n, the constrained dofs are the displacement along n and the two rotations about the in-plane axes; the rotation about n itself is left free. For an axis-aligned plane with normal index k that is mask = (m0, m1, m2, r0, r1, r2) with m_k = 1 and r_i = 1 for i != k – normal +x gives (1, 0, 0, 0, 1, 1), the standard “SPC on trans-x / rot-y / rot-z” convention. The penalty machinery supports only an axis-aligned 6-component mask, so symmetry raises on a rotated normal.

Merging: later terms win on overlap

a + b merges two BoundaryConditions on the same domain. Walking the merged term list from last-added to first, each term’s located entities are removed from every earlier term before that term’s measures are recompiled. So on a facet claimed by two regions only the later region’s mask governs, rather than the sum of both masks; a term that loses all of its entities is dropped. Strong constraints are concatenated in + order, and DOLFINx applies them in order, giving the same “later wins” rule.

penalty_beta

Stored on the whole compiled object (default 1e15); the effective penalty is beta / h through the form’s own CellDiameter. Merging two objects that both carry penalty terms with different explicit penalty_beta raises rather than silently picking one.

One state space per domain

A BoundaryConditions is valid only for a solve sharing its domain.W object. DOLFINx does not treat two independently built but structurally identical FunctionSpaces as interchangeable for DirichletBC application: it does not raise, it silently solves the wrong problem. See hermit.ShellDomain.

Classes

BoundaryConditions

Located facets, dofs and measures, compiled once against a domain.

Functions

clamp(domain, *, where[, method, penalty_beta, value])

Fix all six generalized dofs on a region.

gauge(domain, *, at, dofs[, value])

Pin selected dofs at a single point, to remove rigid-body modes.

near(axis, value, *[, tol])

Build a where predicate selecting an axis-aligned plane.

on_plane(point, normal, *[, tol])

Build a where predicate selecting an arbitrary plane.

pin(domain, *, where, dofs[, method, penalty_beta, value])

Fix a chosen subset of the six generalized dofs on a region.

symmetry(domain, *, where, normal[, penalty_beta, value])

Apply a symmetry-plane constraint (penalty enforcement).

Module Contents

class hermit.bcs.BoundaryConditions(domain, *, penalty_terms=(), strong=(), penalty_beta=None)

Located facets, dofs and measures, compiled once against a domain.

Build one with clamp(), pin(), symmetry() or gauge() rather than calling this constructor directly. a + b merges two objects on the same domain, with later terms winning on overlapping entities.

Parameters:
domainShellDomain
penalty_termssequence, optional

Compiled penalty regions, each carrying a dof mask, a prescribed target and its facet measures.

strongsequence of dolfinx.fem.DirichletBC, optional

Strong constraints.

penalty_betafloat, optional

Penalty scale for the whole object; None selects the default 1e15.

Attributes:
strong_dofsndarray

Sorted unique dof indices held by the strong constraints.

Notes

Valid only for a solve that shares this domain’s state space; see the module docstring.

to_bc_data()

Pack this object for the FEniCSx solve operation.

Returns:
hermit.fenics.bcs.BCData

Carrying a single masked penalty region when there is at most one, and a list of independently masked regions when several survive a merge.

domain
penalty_beta = None
penalty_terms = []
strong = []
property strong_dofs
hermit.bcs.clamp(domain, *, where, method='penalty', penalty_beta=None, value=0.0)

Fix all six generalized dofs on a region.

Parameters:
domainShellDomain
wherecallable

Coordinate predicate; receives a (3, N) array and returns an (N,) boolean mask. near() and on_plane() build the common cases.

method{‘penalty’, ‘strong’}, optional

Enforcement path. Default 'penalty'.

penalty_betafloat, optional

Penalty scale, 'penalty' only. Default 1e15.

valuefloat, array_like or callable, optional

Prescribed value: a scalar, a (6,) vector over (ux, uy, uz, rx, ry, rz), or a callable returning (N, 6) for its (N, 3) coordinates. Default 0. Not differentiable – see the module docstring.

Returns:
BoundaryConditions
Raises:
ValueError

If method is not recognised, or if penalty_beta is given with method='strong'.

See also

pin

constrain a subset of the six dofs.

Examples

>>> bcs = hm.clamp(domain, where=hm.near("x", 0.0))
hermit.bcs.gauge(domain, *, at, dofs, value=0.0)

Pin selected dofs at a single point, to remove rigid-body modes.

Always enforced strongly. Use it to fix the residual null space of an otherwise softly supported model.

Parameters:
domainShellDomain
atarray_like

A (3,) point; the nearest dof of each selected component is used.

dofssequence of str

Any subset of ('ux', 'uy', 'uz', 'rx', 'ry', 'rz').

valuefloat, array_like or callable, optional

Prescribed value; see clamp(). Default 0.

Returns:
BoundaryConditions
Raises:
ValueError

If a dof name is not one of the six.

Examples

>>> bcs = supports + hm.gauge(domain, at=[0.0, 0.0, 0.0], dofs=("ux", "uy"))
hermit.bcs.near(axis, value, *, tol=1e-12)

Build a where predicate selecting an axis-aligned plane.

Parameters:
axis{0, 1, 2, ‘x’, ‘y’, ‘z’}

Coordinate axis to test.

valuefloat

Coordinate value the plane sits at.

tolfloat, optional

Absolute tolerance. Default 1e-12.

Returns:
callable

Suitable as where= for any BC or edge-load builder.

Raises:
ValueError

If axis is not one of the accepted names.

Notes

The comparison is purely absolute. A relative tolerance would swamp tol far from the origin – near("x", 10.0) would select everything within 1e-4 of the plane.

Examples

>>> bcs = hm.clamp(domain, where=hm.near("x", 0.0))
hermit.bcs.on_plane(point, normal, *, tol=1e-12)

Build a where predicate selecting an arbitrary plane.

Parameters:
pointarray_like

A (3,) point on the plane.

normalarray_like

A (3,) plane normal; need not be unit or axis-aligned.

tolfloat, optional

Absolute distance tolerance. Default 1e-12.

Returns:
callable

Suitable as where= for any BC or edge-load builder.

See also

near

the axis-aligned shorthand.

hermit.bcs.pin(domain, *, where, dofs, method='penalty', penalty_beta=None, value=0.0)

Fix a chosen subset of the six generalized dofs on a region.

Parameters:
domainShellDomain
wherecallable

Coordinate predicate; see clamp().

dofssequence of str

Any subset of ('ux', 'uy', 'uz', 'rx', 'ry', 'rz').

method{‘penalty’, ‘strong’}, optional

Enforcement path. Default 'penalty'.

penalty_betafloat, optional

Penalty scale, 'penalty' only.

valuefloat, array_like or callable, optional

Prescribed value; see clamp(). Default 0.

Returns:
BoundaryConditions
Raises:
ValueError

If a dof name is unknown, if method is not recognised, or if penalty_beta is given with method='strong'.

Examples

>>> diaphragm = hm.pin(domain, where=hm.near("x", 0.0), dofs=("uy", "uz"))
hermit.bcs.symmetry(domain, *, where, normal, penalty_beta=None, value=0.0)

Apply a symmetry-plane constraint (penalty enforcement).

Constrains the displacement along normal and the two rotations about the in-plane axes, leaving the rotation about normal free.

Parameters:
domainShellDomain
wherecallable

Coordinate predicate selecting the plane; see clamp().

normalarray_like

A (3,) plane normal, which must be (close to) axis-aligned.

penalty_betafloat, optional

Penalty scale. Default 1e15.

valuefloat, array_like or callable, optional

Prescribed value; see clamp(). Default 0.

Returns:
BoundaryConditions
Raises:
ValueError

If normal is zero or not axis-aligned. The penalty form carries a 6-component mask in global x/y/z, with no rotated-frame projection.

Examples

>>> half = hm.symmetry(domain, where=hm.near("y", 0.0), normal=[0, 1, 0])