Numerical API and benchmarking¶
Documentation index · Method/recipe ownership · Measured results · Validation
The method implementation is margam/methods/pinn.py. Shared problem definitions
live in margam/components/problem.py, with named weighted losses alongside them.
SA-PINN is a separate implementation in margam/methods/self_adaptive.py;
hard Dirichlet is in margam/methods/hard_dirichlet.py. UI recipes are separate
construction definitions under margam/recipes/.
Only strong-form residuals are in scope; weak/variational methods are not implemented.
import torch
import margam as mg
problem = mg.PINNProblem(
residual=lambda x, u: mg.utils.laplacian(u, x) + 2,
collocation_points=lambda: torch.linspace(0, 1, 34)[1:-1, None],
constraints=[mg.PointConstraint("boundary", torch.tensor([[0.], [1.]]))],
)
network = mg.nn.FullyConnected([1, 16, 16, 1], "tanh", "Xavier normal",
input_bounds=([0.], [1.]))
method = mg.PINN(problem, network).compile(lr=0.01, device="cpu")
method.train(1000, display_every=250)
values = method.predict(torch.linspace(0, 1, 101)[:, None])
Sampling happens once per compile. Point sources are tensors or zero-argument
functions returning non-empty (N, D) tensors. Residuals and constraint operators
return (N, C) or (N,). Targets may be scalar, matching tensors, or callables of
points. Constraints can supply derivative operators. Each named term has its own
mean loss. Fixed term weights are summed for full-batch Adam training. LBFGS needs
a separate closure-based procedure and is explicitly rejected by this recipe.
train(n) runs exactly n additional updates. Compile resets optimiser and histories.
Loss history records unweighted named terms and the weighted total before each update.
Prediction restores the network's prior training/evaluation mode. FullyConnected
uses raw coordinates or fixed bounds; it does not normalise by batch extrema.
device="auto" selects CUDA when available, otherwise CPU.
margam.benchmarking exposes BenchmarkCase, Recipe, run_benchmark and solution_errors.
A case supplies a problem factory, evaluation points and reference values. Each
recipe builds its own compiled method. Per seed, the runner materialises data once
and gives independent copies to recipes. It records settings, Git state, sample
fingerprints, versions, timing, losses, predictions and errors. Recipe config should
include architecture and hyperparameters. Output directories must be new.
Artifacts include manifest.json, per-seed samples, per-recipe result.json, loss_history.csv and predictions.npz, plus summary and aggregate CSV/JSON files. Relative L2 is null for zero reference norm. Aggregates include success/failure counts and sample standard deviations; one seed has no sample standard deviation. Failures are recorded and re-raised. This analytical Poisson example is a baseline correctness exercise, not evidence of broad PDE coverage or hardware equivalence.
The small SA comparison has a separate runnable script,
examples.compare_self_adaptive, with optional provenance/settings JSON output.
It uses the template builder and existing mean-BC convention; it does not share
the historical baseline benchmark's exact collocation grid, learning rate or BC
weight. Compare results only under the stated protocols.
Integral squared-error loss¶
PINN(problem, network, loss_formulation="integral") uses PINNProblem.measure
and each PointConstraint.measure (positive finite scalars, default one). It sums
squared residual components, averages over points, and multiplies by the region
measure. Template builders set these measures from physical box dimensions.
The default loss_formulation="mean" preserves previous MSE behaviour. See
integral loss for importance correction and supported data.