--- name: select-trainer description: >- Guides users through configuring the PINA Trainer for solver training, including batching strategy, data splitting, and Lightning options. Use when the user asks "how do I train", "how to train", "set up training", "trainer", "Trainer", "train my model", "fit", "training loop", or similar. Also triggers when the user mentions batching, training configuration, train/val/test split, or is confused about how to start training. license: MIT compatibility: opencode, codex, claude metadata: audience: users workflow: training-setup --- # Configure Training for a PINA Solver > [!IMPORTANT] > Read [RULES.md](../RULES.md) before using this skill — it applies to all skills. Use this skill to set up and run training once a solver has been chosen. PINA's `Trainer` wraps Lightning's `Trainer` with PINA-specific defaults: data splitting across conditions, batching strategies, device placement for inverse parameters, and gradient tracking for physics-informed solvers. ## Step 1 — Understand what the trainer needs The trainer needs three things. If any are missing, ask the user: 1. **Solver** (required) — already chosen and instantiated. 2. **Domain discretisation** — all `DomainEquationCondition` domains must be sampled before the trainer can create dataloaders. 3. **Training config** — epochs, batch size, accelerator, device. ### Domain discretisation Physics-informed problems use `domain=...` in their conditions. The trainer requires every such domain to have been sampled: ```python problem.discretise_domain(n=1000, mode="random") ``` If you forget, the trainer raises a clear error listing which domains are missing. ## Step 2 — Configure the trainer The constructor has two groups of parameters: PINA-specific and Lightning `**kwargs` passed through to the parent class. ### PINA-specific parameters | Parameter | Default | What it controls | |---|---|---| | `solver` | — (required) | The solver instance to train | | `batch_size` | `None` | `None` = full batch; int = mini-batches | | `train_size` / `val_size` / `test_size` | `1.0 / 0.0 / 0.0` | Fraction split per condition | | `batching_mode` | `"common_batch_size"` | How batches are built across conditions (see below) | | `automatic_batching` | `False` | `True` = Lightning's default collation; `False` = direct subset retrieval | | `num_workers` | `0` | Dataloader workers | | `pin_memory` | `False` | Pin memory for faster GPU transfer | | `shuffle` | `True` | Shuffle before splitting | ### Batching modes The mode controls how condition data is assembled into batches: | Mode | Behaviour | When to use | |---|---|---| | `"common_batch_size"` | Each condition supplies `batch_size` points per batch | Default — works for most cases | | `"proportional"` | Batch sizes are scaled by condition dataset sizes | Unbalanced datasets (e.g., many interior points but few boundary points) | | `"separate_conditions"` | Iterates through each condition separately | Each condition's data is heterogeneous (e.g., one is pointwise, another is a graph) | ### Common Lightning kwargs These are passed as `**kwargs` and fully documented by PyTorch Lightning. Key ones for PINA users: | Kwarg | What it does | |---|---| | `max_epochs` | Number of training epochs | | `accelerator` | `"cpu"`, `"gpu"`, `"mps"` (Apple Silicon) | | `devices` | Device index or count (e.g., `1`, `[0]`, `"auto"`) | | `precision` | `"16-mixed"`, `"32"`, `"64"`, `"bf16-mixed"` | | `enable_progress_bar` | `True` / `False` | | `gradient_clip_val` | Gradient clipping threshold | | `callbacks` | List of Lightning callbacks (e.g., `ModelCheckpoint`, `EarlyStopping`) | ## Step 3 — Train and test Usage is uniform regardless of solver type: ```python from pina import Trainer trainer = Trainer( solver=solver, max_epochs=1000, batch_size=32, accelerator="cpu", train_size=0.8, val_size=0.1, test_size=0.1, ) trainer.train() # Lightning fit() trainer.test() # Lightning test() — optional ``` ## Templates ### Full-batch physics-informed ```python problem.discretise_domain(n=5000, mode="random") trainer = Trainer( solver=solver, max_epochs=10000, batch_size=None, # full batch — no mini-batching accelerator="cpu", ) trainer.train() ``` ### Mini-batch supervised ```python trainer = Trainer( solver=solver, max_epochs=500, batch_size=64, train_size=0.8, val_size=0.1, test_size=0.1, accelerator="gpu", devices=1, num_workers=4, shuffle=True, ) trainer.train() trainer.test() ``` ### Unbalanced conditions (proportional batching) ```python trainer = Trainer( solver=solver, batch_size=512, batching_mode="proportional", max_epochs=1000, ) ``` ## Checklist - [ ] Solver already chosen and instantiated (see **select-solver** skill) - [ ] All domains discretised: `problem.discretise_domain(n=..., mode="...")` - [ ] Batch size decided: `None` for full-batch, an int for mini-batches - [ ] Batching mode selected based on condition balance - [ ] Train/val/test split configured - [ ] Accelerator and device chosen - [ ] Training started: `trainer.train()`