PINA Development Skill
Expert guidance for Physics-Informed Neural Networks (PINNs) and Scientific Machine Learning with PINA.
What is PINA?
PINA (Physics-Informed Neural networks for Advanced modeling) is a PyTorch-based library for solving partial differential equations (PDEs) using neural networks. It combines:
- Physics-Informed Neural Networks (PINNs): Solve forward and inverse PDE problems
- Neural Operators: FNO, DeepONet for operator learning
- Data-Driven Modeling: Supervised learning with physics constraints
- Reduced Order Modeling: POD-NN for efficient simulations
Built on: PyTorch, PyTorch Lightning, PyTorch Geometric
Core Workflow
Every PINA project follows these 4 steps:
python1from pina import Trainer 2from pina.problem import SpatialProblem 3from pina.solver import PINN 4from pina.model import FeedForward 5 6# Step 1: Define Problem 7problem = MyProblem() 8problem.discretise_domain(n=100, mode="grid") 9 10# Step 2: Design Model 11model = FeedForward(input_dimensions=1, output_dimensions=1, layers=[64, 64]) 12 13# Step 3: Define Solver 14solver = PINN(problem, model) 15 16# Step 4: Train 17trainer = Trainer(solver, max_epochs=1000, accelerator='gpu') 18trainer.train()
Simple ODE Example
python1from pina.problem import SpatialProblem 2from pina.domain import CartesianDomain 3from pina.condition import Condition 4from pina.equation import Equation, FixedValue 5from pina.operator import grad 6import torch 7 8def ode_equation(input_, output_): 9 """PDE residual: du/dx - u = 0""" 10 u_x = grad(output_, input_, components=["u"], d=["x"]) 11 u = output_.extract(["u"]) 12 return u_x - u 13 14class SimpleODE(SpatialProblem): 15 output_variables = ["u"] 16 spatial_domain = CartesianDomain({"x": [0, 1]}) 17 18 domains = { 19 "x0": CartesianDomain({"x": 0.0}), # Boundary 20 "D": CartesianDomain({"x": [0, 1]}) # Interior 21 } 22 23 conditions = { 24 "bound_cond": Condition(domain="x0", equation=FixedValue(1.0)), 25 "phys_cond": Condition(domain="D", equation=Equation(ode_equation)) 26 } 27 28 def solution(self, pts): 29 """Analytical solution for validation.""" 30 return torch.exp(pts.extract(["x"])) 31 32problem = SimpleODE()
Models
FeedForward Networks
python1from pina.model import FeedForward 2 3# Basic network 4model = FeedForward( 5 input_dimensions=2, 6 output_dimensions=1, 7 layers=[64, 64, 64], # Hidden layers 8 func=torch.nn.Tanh # Activation function 9) 10 11# Alternative activations 12model = FeedForward( 13 input_dimensions=1, 14 output_dimensions=1, 15 layers=[100, 100, 100], 16 func=torch.nn.Softplus # or torch.nn.SiLU 17)
See Custom Models Reference for advanced architectures including:
- Hard constraints
- Fourier feature embeddings
- Periodic boundary embeddings
- POD-NN
- Graph neural networks
See Neural Operators Reference for operator learning with FNO, DeepONet, and more.
PINN Solver
python1from pina.solver import PINN 2from pina.optim import TorchOptimizer 3import torch 4 5pinn = PINN( 6 problem=problem, 7 model=model, 8 optimizer=TorchOptimizer(torch.optim.Adam, lr=0.001) 9)
See Advanced Solvers Reference for:
- Self-Adaptive PINN (SAPINN)
- Supervised Solver
- Custom solvers
- Training strategies
Training
Basic Training
python1from pina import Trainer 2from pina.callbacks import MetricTracker 3 4# Discretize domain 5problem.discretise_domain(n=1000, mode="random", domains="all") 6 7# Create trainer 8trainer = Trainer( 9 solver=pinn, 10 max_epochs=1500, 11 accelerator="cpu", # or "gpu" 12 enable_model_summary=False, 13 callbacks=[MetricTracker()] 14) 15 16# Train 17trainer.train()
Training Configuration
python1trainer = Trainer( 2 solver=solver, 3 max_epochs=1000, 4 accelerator="gpu", 5 devices=1, 6 batch_size=32, 7 gradient_clip_val=0.1, # Gradient clipping 8 callbacks=[MetricTracker()] 9) 10trainer.train()
Testing
python1# Test the model 2test_results = trainer.test() 3 4# Manual evaluation 5with torch.no_grad(): 6 test_pts = problem.spatial_domain.sample(100, "grid") 7 prediction = solver(test_pts) 8 true_solution = problem.solution(test_pts) 9 error = torch.abs(prediction - true_solution)
Domain Discretization
Sampling Modes
python1# Grid sampling (uniform points) 2problem.discretise_domain(n=100, mode="grid", domains=["D", "x0"]) 3 4# Random sampling (Monte Carlo) 5problem.discretise_domain(n=1000, mode="random", domains="all") 6 7# Latin Hypercube Sampling 8problem.discretise_domain(n=500, mode="lh", domains=["D"]) 9 10# Manual sampling 11pts = problem.spatial_domain.sample(256, "grid", variables="x")
Best Practice: Start with grid for testing, use random/LH for training with more points.
Visualization
python1import matplotlib.pyplot as plt 2 3@torch.no_grad() 4def plot_solution(solver, n_points=256): 5 # Sample points 6 pts = solver.problem.spatial_domain.sample(n_points, "grid") 7 8 # Get predictions 9 predicted = solver(pts).extract("u").detach() 10 true = solver.problem.solution(pts).detach() 11 12 # Plot comparison 13 fig, axes = plt.subplots(1, 3, figsize=(15, 5)) 14 15 axes[0].plot(pts.extract(["x"]), true, label="True", color="blue") 16 axes[0].set_title("True Solution") 17 axes[0].legend() 18 19 axes[1].plot(pts.extract(["x"]), predicted, label="PINN", color="green") 20 axes[1].set_title("PINN Solution") 21 axes[1].legend() 22 23 diff = torch.abs(true - predicted) 24 axes[2].plot(pts.extract(["x"]), diff, label="Error", color="red") 25 axes[2].set_title("Absolute Error") 26 axes[2].legend() 27 28 plt.tight_layout() 29 plt.show()
See Visualization Reference for comprehensive plotting techniques.
Best Practices
1. Start Simple
python1# Begin with small network 2model = FeedForward(input_dimensions=2, output_dimensions=1, layers=[20, 20]) 3 4# Gradually increase complexity 5model = FeedForward(input_dimensions=2, output_dimensions=1, layers=[64, 64, 64])
2. Monitor Losses
python1from pina.callbacks import MetricTracker 2 3trainer = Trainer( 4 solver=pinn, 5 max_epochs=1000, 6 callbacks=[MetricTracker(["train_loss", "bound_cond_loss", "phys_cond_loss"])] 7)
3. Two-Phase Training
python1# Phase 1: Rough solution (high LR) 2pinn = PINN(problem, model, optimizer=TorchOptimizer(torch.optim.Adam, lr=0.01)) 3trainer = Trainer(pinn, max_epochs=500) 4trainer.train() 5 6# Phase 2: Refinement (low LR) 7pinn.optimizer.param_groups[0]['lr'] = 0.001 8trainer = Trainer(pinn, max_epochs=1500) 9trainer.train()
MLflow Integration
Track PINA experiments with MLflow for reproducibility and comparison:
python1import mlflow 2from pina import Trainer 3from pina.solver import PINN 4 5# Set experiment 6mlflow.set_experiment("pina-poisson-solver") 7 8with mlflow.start_run(run_name="baseline"): 9 # Log hyperparameters 10 mlflow.log_params({ 11 "layers": [64, 64, 64], 12 "activation": "Tanh", 13 "learning_rate": 0.001, 14 "n_points": 1000, 15 "epochs": 1500 16 }) 17 18 # Setup and train 19 problem.discretise_domain(n=1000, mode="random") 20 trainer = Trainer(solver, max_epochs=1500) 21 trainer.train() 22 23 # Log final metrics 24 mlflow.log_metric("final_loss", trainer.callback_metrics["train_loss"]) 25 26 # Log model 27 mlflow.pytorch.log_model(solver.model, "pinn_model")
Marimo Dashboard Integration
Create interactive PINA dashboards with marimo:
python1import marimo as mo 2from pina.solver import PINN 3 4# UI controls for hyperparameters 5layers = mo.ui.slider(1, 5, value=3, label="Hidden Layers") 6neurons = mo.ui.slider(16, 128, value=64, step=16, label="Neurons/Layer") 7lr = mo.ui.number(value=0.001, start=0.0001, stop=0.1, label="Learning Rate") 8 9# Train button 10train_btn = mo.ui.run_button(label="Train PINN") 11 12# In another cell: run training when button clicked 13if train_btn.value: 14 model = FeedForward( 15 input_dimensions=2, 16 output_dimensions=1, 17 layers=[neurons.value] * layers.value 18 ) 19 # ... train and visualize
Using context7 for Documentation
Query up-to-date PINA documentation directly:
# context7 Library ID (no resolve needed):
# - /mathlab/pina (official docs, 2345 snippets)
# Example: query-docs("/mathlab/pina", "FeedForward model parameters")
When to Use This Skill
✅ Use PINA when:
- Solving PDEs with neural networks
- Need to incorporate physics constraints
- Working with inverse problems
- Building neural operators (FNO, DeepONet)
- Reduced order modeling
- Scientific ML research
❌ Don't use PINA when:
- Pure data-driven tasks (use standard PyTorch)
- Not dealing with differential equations
- Need classical numerical solvers (FEM, FVM)
Reference Documentation
Detailed documentation organized by topic:
- Problem Types: ODE, Poisson, Wave, Inverse problems, custom equations
- Neural Operators: FNO, DeepONet, Kernel Neural Operator
- Custom Models: Hard constraints, Fourier features, periodic embeddings, POD-NN, GNNs
- Advanced Solvers: SAPINN, supervised solver, custom solvers, training strategies
- Visualization: Plotting techniques, error analysis, animations
Complete Examples
Ready-to-run example scripts:
- Poisson 2D: Complete 2D Poisson equation solver with visualization
- Wave Equation: Time-dependent wave equation with animations
- FNO Example: Fourier Neural Operator for operator learning
- Inverse Problem: Learn unknown parameters from data
Resources
- Documentation: https://mathlab.github.io/PINA/
- GitHub: https://github.com/mathLab/PINA
- Paper: https://joss.theoj.org/papers/10.21105/joss.04813
- Tutorials: https://github.com/mathLab/PINA/tree/master/tutorials