Enforced constraint pipelines¤
Pipelines compose and apply enforced-constraint ansätze.
For the underlying ansatz constructors (enforce_dirichlet, enforce_neumann, etc.), see
Enforced constraint ansätze.
Note
Key notes:
- An
EnforcedConstraintPipelinestages overlays in the order boundary → initial → interior data. EnforcedConstraintPipelinestopologically orders multi-field dependencies (co_vars).- For a detailed mathematical treatment of the PCI pipeline (including BVH-weighted boundary blending, boundary–initial gating, and the interior anchor/data stage), see Appendix → Physics-Constrained Interpolation.
phydrax.solver.SingleFieldEnforcedConstraint
¤
Enforced constraint term acting on a single field.
An enforced constraint is a transformation that builds an ansatz \(\tilde u\) from a base field \(u\) such that some condition is satisfied by construction. Conceptually this is a map
where \(\tilde u\) is intended to satisfy, e.g., Dirichlet boundary conditions \(\tilde u|_{\partial\Omega}=g\), initial conditions \(\tilde u(\cdot,t_0)=u_0\), or similar constraints.
SingleFieldEnforcedConstraint stores the metadata needed to stage and compose
these transformations inside EnforcedConstraintPipeline.
co_vars
property
¤
Names of co-dependent fields (always empty for single-field terms).
__init__(field: str, component: DomainComponent, apply: Callable[[DomainFunction], DomainFunction], /, *, max_derivative_order: int = 0, time_derivative_order: int = 0, initial_target: DomainFunction | ArrayLike | None = None)
¤
Create a single-field enforced constraint.
Arguments:
field: Name of the field being modified (e.g."u").component: The domain subset where the constraint is defined (boundary, initial, etc.).apply: The enforcement map \(\mathcal{H}\) implemented as a callable that returns a newDomainFunction.
Keyword arguments:
max_derivative_order: Maximum spatial derivative order that the constraint construction expects to be well-defined (used for staging and gating in composite pipelines).time_derivative_order: When the constraint represents an initial derivative target, this is the derivative order \(k\) for \(\partial_t^k u(\cdot,t_0)\).initial_target: Optional target for the initial derivative order: provide \(g_k\) for \(\partial_t^k u(\cdot,t_0)=g_k\).
Notes:
- If
initial_targetis provided,EnforcedConstraintPipelinewill group targets for orders \(k=0,\dots,K\) and build a single initial overlay.
phydrax.solver.MultiFieldEnforcedConstraint
¤
Enforced constraint term that depends on other fields.
Some enforced constraint constructions require access to co-variables (other fields) when enforcing a given field. For example, a boundary condition for a stress-like quantity might depend on both displacement and material parameters.
This stores an apply function of the form
where get_field(name) supplies the current (possibly already enforced)
DomainFunction for each co-variable.
__init__(field: str, component: DomainComponent, co_vars: Sequence[str], apply: Callable[[DomainFunction, Callable[[str], DomainFunction]], DomainFunction], /, *, max_derivative_order: int = 0, time_derivative_order: int = 0)
¤
Create a multi-field enforced constraint.
Arguments:
field: Name of the field being modified.component: The domain subset where the constraint is defined.co_vars: Names of fields thatapplydepends on.apply: An enforcement map \(\mathcal{H}\) implemented asapply(u, get_field) -> DomainFunction.
Keyword arguments:
max_derivative_order: Maximum spatial derivative order expected by the constraint.time_derivative_order: Optional initial-derivative order metadata.
phydrax.solver.EnforcedInteriorData
¤
Interior data source for enforced data overlays.
EnforcedInteriorData represents measurements (or anchor constraints) that you
want to enforce by construction in the interior of a domain, without
competing with boundary/initial enforced constraints.
Two input modes are supported:
1) Anchor points: a set of points \(z_j\) with values \(y_j\).
points: mapping from domain label to coordinate arrays.values: an array of values with leading dimension \(N\).
2) Sensor tracks: a set of fixed sensors \(x_m\) observed over times \(t_n\).
sensors: array with shape \((M,d)\) (or \((d,)\) for a single sensor).times: array with shape \((N,)\).sensor_values: array with shape \((M,N)\) or \((M,N,C)\).
The enforced overlay built from this data uses inverse-distance weights (IDW) to compute a correction term \(\Delta u(z)\) from residuals \(r_j = y_j - u(z_j)\), while multiplying by a gate \(M(z)\) that vanishes on constrained sets (boundary / initial time) so the overlay does not destroy those conditions.
See EnforcedConstraintPipeline for how this integrates with other enforced stages.
__init__(field: str, /, *, points: Mapping[str, ArrayLike] | None = None, values: ArrayLike | None = None, sensors: ArrayLike | None = None, times: ArrayLike | None = None, sensor_values: ArrayLike | None = None, idw_exponent: float = 2.0, eps_snap: float = 1e-12, lengthscales: Mapping[str, float] | None = None, use_envelope: bool = False, envelope_scale: float = 1.0, space_label: str = 'x', time_label: str = 't', time_interp: Literal[idw, hermite] = 'idw')
¤
Create an enforced interior data source.
Arguments:
field: Name of the field that this data applies to.
Anchor mode:
points: Mapping{label: coords}giving anchor coordinates per domain label. Geometry labels should use shape(N,d)and scalar labels shape(N,).values: Anchor values with shape(N,)or(N,C).
Sensor-track mode:
sensors: Sensor locations, shape(M,d)(or(d,)).times: Observation times, shape(N,).sensor_values: Observations, shape(M,N)or(M,N,C).space_label: Domain label corresponding to space.time_label: Domain label corresponding to time.time_interp:"idw"flattens the \((x_m,t_n)\) grid into anchors in \((x,t)\) and uses IDW in the full domain."hermite"uses a cubic Hermite spline in time and IDW only in space (requires a 2-factor domain with(space_label, time_label)).
IDW details:
idw_exponent: Power \(p\) in weights \(w_j(z)\propto (\|z-z_j\|^2+\varepsilon)^{-p/2}\).lengthscales: Optional per-label lengthscales \(\ell_\alpha\) used inside the distance metric: \(\|z-z_j\|^2=\sum_\alpha \|(z_\alpha-z_{j,\alpha})/\ell_\alpha\|^2\).eps_snap: Snap threshold: when \(z\) is closer thaneps_snapto an anchor, the overlay uses a one-hot weight so that \(u(z)\) matches the anchor exactly.
Envelope (optional):
use_envelope: If enabled, multiplies IDW weights by a source-local envelope.envelope_scale: Envelope scale \(s\) in \(\psi(z)=\exp(-d(z)^2/s^2)\).
phydrax.solver.EnforcedConstraintPipeline
¤
Compose enforced overlays for a single field.
A pipeline takes a base field \(u\) and returns an enforced field \(\tilde u\) after applying a sequence of enforced transformations:
- Boundary overlays (if any), typically enforcing conditions on \(\partial\Omega\) using smooth blend weights.
- Initial overlays (if any), enforcing values and/or time-derivative targets at \(t=t_0\).
- Interior data overlays (optional), enforcing interior anchors/tracks while preserving the boundary/initial conditions via a multiplicative gate that vanishes on the constrained sets.
Boundary/initial stages are blended using a boundary gate \(\gamma(z)\), where \(\gamma=0\) on the constrained boundary and \(\gamma\approx 1\) away from it:
This ensures that later stages do not re-violate boundary enforced constraints.
__init__(u_base: DomainFunction, /, *, field: str, constraints: Sequence[SingleFieldEnforcedConstraint | MultiFieldEnforcedConstraint] = (), interior_data: Sequence[EnforcedInteriorData] = (), evolution_var: str = 't', include_identity_remainder: bool = True, num_reference: int = 3000000, sampler: str = 'latin_hypercube', key: Key[Array, ''] = jr.key(0))
¤
Build a pipeline for one field.
Arguments:
u_base: BaseDomainFunctionfor the field.
Keyword arguments:
field: Field name (used to match constraints/data to the field).constraints: Enforced constraint terms (single-field or multi-field).interior_data: Interior data sources used to build an IDW-based enforced overlay.evolution_var: Name of the time-like label used to detect initial constraints (default"t").include_identity_remainder: When blending multiple boundary pieces, include a remainder weight for the identity map (keeps \(u\) unchanged away from all pieces).num_reference: Reference sample count used to normalize boundary blend weights.sampler: Sampler used to draw reference points.key: PRNG key used to draw reference points.
Notes:
- Boundary staging currently requires boundary constraints to specify exactly one geometry boundary label, shared across all boundary pieces.
apply(u_base: DomainFunction, /, *, get_field: Callable[[str], DomainFunction]) -> DomainFunction
¤
phydrax.solver.EnforcedConstraintPipelines
¤
Enforced constraint pipelines for multiple fields.
When enforcing multiple fields \(\{u^{(k)}\}\), some enforced constraints may
require access to co-variables (other fields). This object builds a
directed acyclic graph (DAG) from MultiFieldEnforcedConstraint.co_vars and
applies per-field EnforcedConstraintPipelines in a topological order so that
dependencies are available when needed.
__init__(pipelines: Mapping[str, EnforcedConstraintPipeline], /, *, field_order: Sequence[str])
¤
Create a multi-field pipeline orchestrator.
Arguments:
pipelines: Mapping{field: EnforcedConstraintPipeline}.
Keyword arguments:
field_order: Preferred ordering for tie-breaking in the toposort (typicallytuple(functions.keys())).
build(*, functions: Mapping[str, DomainFunction], constraints: Sequence[SingleFieldEnforcedConstraint | MultiFieldEnforcedConstraint] = (), interior_data: Sequence[EnforcedInteriorData] = (), evolution_var: str = 't', include_identity_remainder: bool = True, num_reference: int = 3000000, sampler: str = 'latin_hypercube', key: Key[Array, ''] = jr.key(0)) -> EnforcedConstraintPipelines
classmethod
¤
apply(functions: Mapping[str, DomainFunction]) -> frozendict[str, DomainFunction]
¤
Apply all pipelines and return an enforced field mapping.
Pipelines are applied in a dependency-respecting order. If a pipeline for field \(u\) requires co-variables \(\{v\}\), then those \(v\) are taken from the current enforced mapping as the iteration proceeds.