DD-PINN¶
Damped-ansatz DD-PINN surrogate: continuous-time model, scaler, and physics-only trainer.
DampedAnsatzPINN ¶
DampedAnsatzPINN(n_state: int, n_cond: int, n_ansatz: int = 50, hidden_size: int = 64, hidden_layer: int = 3, act: type = nn.Tanh, t_zero: float = -1.0, exp_clamp: float = 30.0)
Bases: Module
Continuous-time surrogate with an analytically-differentiable damped ansatz.
Operates entirely in normalized [-1, 1] coordinates. The input row is laid out as
[x_k (n_state) | cond (n_cond) | t (1)] where the last channel is normalized time.
The MLP trunk maps (x_k, cond) to 4·n_ansatz·n_state coefficients — time is
decoupled from the trunk and enters only through the closed form. Per output channel,
summed over k = 1..n_ansatz with ansatz-time τ = t − t_zero::
g_k(τ) = a_k·(sin(b_k·τ + c_k)·exp(−d_k·τ) − sin(c_k))
x(τ) = x_k + Σ_k g_k(τ)
g_k(0) = 0 makes x(0) = x_k exact (the initial condition is enforced by
construction — no IC loss), and dx/dτ is closed-form, so the physics residual needs
no autograd over time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_state
|
int
|
state dimension; |
required |
n_cond
|
int
|
conditioning channels (control + collocation vars) between |
required |
n_ansatz
|
int
|
number of damped ansatz functions summed per output channel. |
50
|
hidden_size
|
int
|
width of the trunk MLP. |
64
|
hidden_layer
|
int
|
number of hidden layers in the trunk MLP. |
3
|
act
|
type
|
trunk activation function class. |
Tanh
|
t_zero
|
float
|
normalized-time value mapped to ansatz-time |
-1.0
|
exp_clamp
|
float
|
upper bound on the decay exponent |
30.0
|
Source code in tsfast/pinn/ddpinn.py
DDPINNRollout ¶
DDPINNRollout(model: Module, state_scaler: Module, cond_scaler: Module, t_sample: float, t_max: float)
Bases: Module
Autoregressive rollout of a :class:DampedAnsatzPINN as a differentiable sequence model.
Turns the pointwise continuous-time map into a sequence-to-sequence model: given a physical
initial state and a physical conditioning sequence, it predicts the physical state trajectory
by feeding each one-step prediction back as the next initial state. The loop runs in normalized
[-1, 1] space (the model's native coordinates); the two scalers it carries bridge to
physical units at the boundary, so callers work entirely in physical units. forward is
differentiable end-to-end — use it inside a training step for a multi-step / data-assisted loss,
or under :func:torch.no_grad for inference. :meth:step is the atomic normalized-space unit
the loop iterates (and the natural single-step target for ONNX export).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
a trained :class: |
required |
state_scaler
|
Module
|
the :class: |
required |
cond_scaler
|
Module
|
the :class: |
required |
t_sample
|
float
|
physical step size per autoregressive step; must be |
required |
t_max
|
float
|
physical horizon defining the |
required |
Source code in tsfast/pinn/ddpinn.py
step ¶
One autoregressive step in normalized coordinates: [B, 1, n_state] -> [B, 1, n_state].
Source code in tsfast/pinn/ddpinn.py
forward ¶
Roll out N steps in physical units.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x0
|
Tensor
|
physical initial state |
required |
cond_seq
|
Tensor
|
physical conditioning sequence |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Physical-unit state trajectory |
Source code in tsfast/pinn/ddpinn.py
SurrogatePINNLearner ¶
SurrogatePINNLearner(model: Module, generate_pinn_input: Callable, residual_func: Callable, state_range: list[tuple[float, float]], cond_range: list[tuple[float, float]], t_max: float, steps_per_epoch: int = 200, bs: int = 4096, val_steps: int = 20, val_seed: int = 0, lr: float = 0.003, metrics: list | None = None, **kw)
Bases: Learner
Physics-only (no-data) trainer for a :class:DampedAnsatzPINN.
Each step samples a fresh batch of collocation points (in normalized [-1, 1]
coordinates) and minimizes the ODE residual built from the ansatz's analytic dx/dt.
Normalization and the chain-rule factor live here, so the model stays in normalized
space and the user's residual_func only ever sees physical quantities. Reuses
:class:~tsfast.training.learner.Learner for the optimizer, scheduler, NaN guard, and
progress reporting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
a :class: |
required |
generate_pinn_input
|
Callable
|
|
required |
residual_func
|
Callable
|
|
required |
state_range
|
list[tuple[float, float]]
|
list of |
required |
cond_range
|
list[tuple[float, float]]
|
list of |
required |
t_max
|
float
|
physical time horizon mapped to the upper edge of the |
required |
steps_per_epoch
|
int
|
collocation batches drawn per epoch (sets the scheduler length). |
200
|
bs
|
int
|
collocation batch size. |
4096
|
val_steps
|
int
|
number of fixed validation batches. |
20
|
val_seed
|
int
|
seed for the deterministic validation set. |
0
|
lr
|
float
|
learning rate. |
0.003
|
metrics
|
list | None
|
optional metrics (unused by the physics-only |
None
|
Source code in tsfast/pinn/ddpinn.py
setup ¶
Standard setup plus moving the scalers and chain-rule factor to the device.
Source code in tsfast/pinn/ddpinn.py
physics_loss ¶
ODE residual on a batch of normalized collocation points.
Source code in tsfast/pinn/ddpinn.py
validate ¶
Mean physics residual over the (fixed) validation collocation set.
The derivative is analytic, so this runs entirely under no_grad.
Source code in tsfast/pinn/ddpinn.py
as_rollout ¶
Bundle the trained model with both scalers into a differentiable sequence rollout.
The returned :class:DDPINNRollout is a single self-contained nn.Module (physical state
+ physical conditioning sequence in, physical trajectory out) that torch.save persists as
one deployable artifact. Call it under :func:torch.no_grad for inference, or inside a
training step for a multi-step / data-assisted loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t_sample
|
float | None
|
physical step size per autoregressive step (defaults to |
None
|
Source code in tsfast/pinn/ddpinn.py
make_collocation_dls ¶
make_collocation_dls(generate_pinn_input: Callable, bs: int, steps_per_epoch: int, val_steps: int, val_seed: int = 0, seq_len: int = 1) -> DataLoaders
Build a :class:DataLoaders of collocation batches for physics-only training.
The training stream re-samples fresh collocation points every epoch; the validation set
is generated once under a fixed seed so its physics metric is comparable across epochs.
len(dls.train) == steps_per_epoch so the scheduler receives the right total-step
count. Batches are (X, dummy_y) pairs — the dummy target is ignored by the
physics-only learner.