Model summary
Qwen3.5-9B PDE Solver is a low-rank adapter for Qwen3.5-9B that generates numerical solvers for partial
differential equations. Given an equation, its coefficients, a spatial grid and an initial state, the model
writes a Python function that returns the solution at every requested time. The adapter was trained with
reinforcement learning against a physics verifier that executes each generated program in a sandbox and
compares its output with a reference solution. A solution is counted as correct only if it executes, returns
the requested array, and its root-mean-square error over the full trajectory, divided by the range of the
reference, is at most 1%.
On ten equation families excluded from training, pass@1 increases from 9.0% for the base model to
55.7%, above two substantially larger open-weight models evaluated with the same verifier (GLM-5.3, 49.1%;
MiMo-V2.6-Pro, 45.6%). Details, analysis and the full training recipe are reported in the accompanying
research write-up.
Model details
Table | |
|---|
| Developed by | Jarrod Barnes |
| Model type | Low-rank adapter (LoRA, rank 32, alpha 32) for a causal language model |
| Base model | Qwen/Qwen3.5-9B |
| Trainable parameters | 86.6M |
| Language | English prompts, Python output |
| License | Apache 2.0, consistent with the base model |
| Context | Trained with 9,728 tokens total and up to 9,216 generated; 10,240 recommended for serving; thinking mode disabled |
| Release | October 2026, checkpoint at training update 256 |
| Research write-up | https://jbarnes850.github.io |
| Code, verifier and evaluation sets | Released with the research write-up |
Intended use
The model is intended for research on language models for scientific computing, for generating draft
numerical solvers for one- and two-dimensional time-dependent and steady PDEs on structured grids, and as a
baseline for verifier-based training and evaluation. Generated solvers are drafts. They should be validated
against the governing equation, known analytical limits, or an independent trusted method before use.
Out-of-scope use. The model has not been evaluated on three-dimensional problems, unstructured meshes,
complex geometries, multiphysics coupling, inverse problems or production simulation workloads. It should not
be used for safety-critical engineering decisions without independent verification.
Training
Data. Training problems were generated procedurally from eight PDE families following the RLVP
benchmark procedures (advection, Burgers, reaction-diffusion in one and two dimensions, diffusion-sorption,
Darcy flow, incompressible Navier-Stokes and shallow water), with three additional linear families in the
final phase (advection on non-unit domains, the Airy equation and hyperdiffusion). Each problem specifies the
equation, coefficients, grid, initial condition and, where the reference depends on it, the grid and boundary
convention. Each training phase used new problems. Before each phase, candidate problems were screened with
the current model and those already solved in at least six of eight attempts were removed. Families that no
independent solver passes at the 1% threshold were excluded.
Procedure. Training used asynchronous group-relative policy optimization in NeMo RL with the CISPO loss
and a MaxRL-style advantage, in which each program's reward minus the group mean is divided by the group mean
rather than its standard deviation. The reward assigns zero to any output no better than the best trivial
predictor for that problem, partial credit for improvement over that predictor on a logarithmic scale, and
full credit for meeting the 1% threshold. No supervised fine-tuning was applied; training starts from the
base model with a zero-initialized adapter.
Hyperparameters.
Table with columns: Setting, Value| Setting | Value |
|---|
| Updates | 256, in eight phases of 32 |
| Problems per update | 8 |
| Samples per problem | 16 |
| Total attempts | about 32,800 |
| Learning rate | 1e-6 for the first update of each phase, then 1e-5 |
| Optimizer | AdamW, weight decay 0.01, state carried across phases |
| KL penalty | 0.001, to the base model |
| Advantage normalization | group mean plus 0.01 |
| Sampling temperature |
Evaluation
Data. Two fixed evaluation sets were scored at every checkpoint with identical problems and random seeds.
The in-distribution set contains 288 new problems from six training families. The held-out set contains 135
problems from ten families never used in training (advection and advection-diffusion in two dimensions,
advection-diffusion, advection-reaction-diffusion, heat, Korteweg-de Vries and Cahn-Hilliard in one
dimension, Allen-Cahn, Gray-Scott and Darcy-reaction in two dimensions). Two further sets were generated and
sealed before the final checkpoint existed and were opened once.
Metric. A response is correct if it executes within 30 seconds, returns the requested shape, and its
root-mean-square error over all requested times, divided by the range of the reference, is at most 0.01. Pass@1
is the probability that a single sample is correct, estimated from eight samples per problem, averaged within
each family and then across families. Pass@k is the probability that at least one of k samples is correct.
Results.
Table with columns: Base, Update 128, Update 160, Update 256 | Base | Update 128 | Update 160 | Update 256 |
|---|
| Pass@1, in-distribution | 6.6% | 28.4% | 36.2% | 47.3% |
| Pass@1, held-out families | 9.0% | 31.6% | 39.8% | 55.7% |
| Pass@8, held-out families | 47.2% | 77.2% | 82.6% | 88.2% |
|
Residual-selected best of 8 keeps, among valid outputs, the one with the smallest residual of the governing
equation. This selection requires no reference solution.
Comparison with larger models on the held-out families, scored by the same verifier. The other
models were queried with up to 32,000 output tokens and reasoning enabled; this model generates at most 9,216
tokens without reasoning.
Table with columns: Model, Pass@1, Residual-selected best of 8| Model | Pass@1 | Residual-selected best of 8 |
|---|
| Qwen3.8-Max | 69.2% | 89.0% |
| GLM-5.3 | 49.1% | 88.9% |
| MiMo-V2.6-Pro | 45.6% | 78.0% |
| Qwen3.5-9B PDE Solver | 55.7% | 87.8% |
| Qwen3.5-9B (base) | 9.0% | 46.4% |
Limitations
- Much of the improvement concentrates on successes the base model already produced occasionally. With 64
samples per problem, pass@64 on the held-out families is 85.2% for the base model and 90.0% for this model,
whose pass@8 is 87.6%. Five held-out problems are solved by this model and by no base-model sample; none
shows the reverse.
- Performance is weakest on stiff nonlinear equations (Cahn-Hilliard, Korteweg-de Vries, Gray-Scott), where
41% to 75% of its answers still use explicit time stepping.
- On Darcy flow and its held-out reaction variant the model places the Dirichlet boundary one full cell outside
the outermost cell centers rather than half a cell. Accuracy on these families is near zero. All evaluated
frontier models show the same failure on the held-out variant.
- All results use a 1% error threshold, a 30-second time limit and NumPy and SciPy only. Behavior under other
budgets, libraries or problem classes is untested.
- Residual-based selection is computed on the evaluation grid and does not check initial or boundary
conditions. It can prefer outputs that satisfy the equation but violate those conditions, and its accuracy
peaks near 16 samples (86.3%) and declines with more (79.3% at 64).
How to use
The system prompt and the per-family grid conventions used in training and evaluation are included in this
repository (prompts/system.txt, prompts/grid-conventions.json). Generation used temperature 0.7, top-p 1.0
and at most 9,216 new tokens, with thinking disabled.
Serving with vLLM. Following the vLLM recipe for Qwen3.5, serve the base model text-only with the adapter
attached. A context of 10,240 tokens leaves room for the system prompt, the problem and a full 9,216-token
answer.
uv pip install "vllm==0.31.0" --torch-backend=autovllm serve Qwen/Qwen3.5-9B \ --enable-lora --lora-modules pde-solver=Jarrodbarnes/qwen3.5-9b-pde-solver --max-lora-rank 32 \ --max-model-len 10240 --language-model-only \ --default-chat-template-kwargs '{"enable_thinking": false}'
Requests use the OpenAI-compatible API with the adapter name as the model:
from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")response = client.chat.completions.create( model="pde-solver", messages=[ {"role": "system", "content": open("prompts/system.txt").read()}, {"role": "user", "content": open("problem.txt").read()}, # equation, signature, grid convention ], temperature=0.7, top_p=1.0, max_tokens=9216, n=8,)candidates = [choice.message.content for choice in response.choices]
Serving was verified with vLLM 0.31.0 using the vllm/vllm-openai:v0.31.0 image on one NVIDIA H100. The
adapter loads as pde-solver, and a sampled answer to an advection problem passed the verifier with a
relative error of 1e-15. A pip installation additionally requires a CUDA toolkit on the host, because vLLM
compiles kernels for this architecture at startup; the official Docker image includes it.
Loading with Transformers and PEFT.
import torchfrom transformers import AutoModelForImageTextToText, AutoTokenizerfrom peft import PeftModel base = "Qwen/Qwen3.5-9B"tokenizer = AutoTokenizer.from_pretrained(base)model = AutoModelForImageTextToText.from_pretrained(base, dtype=torch.bfloat16, device_map="auto")model = PeftModel.from_pretrained(model, "Jarrodbarnes/qwen3.5-9b-pde-solver")messages = [ {"role": "system", "content": open("prompts/system.txt").read()}, {"role": "user", "content": open("problem.txt").read()},]inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, enable_thinking=False, return_tensors="pt", return_dict=True).to(model.device)output = model.generate(**inputs, max_new_tokens=9216, do_sample=True, temperature=0.7, top_p=1.0)
Loading was verified with Transformers 5.19 and PEFT 0.21; all 248 adapter target modules map onto
Qwen3_5ForConditionalGeneration.
Compute
Training ran on Modal with one node of two NVIDIA H200 GPUs (one for the learner, one for generation) and a
16-core CPU verifier, for a total of about 26 hours of training wall-clock time.
Citation
@misc{barnes2026pdesolver, title = {What reinforcement learning really teaches a physics solver}, author = {Barnes, Jarrod}, year = {2026}, url = {https://jbarnes850.github.io}}
This work builds on Cai, P., Utkarsh, U., Edelman, A., Rackauckas, C. V. and Gómez-Bombarelli, R.
Reinforcement Learning with Verifiable Physics: Post-training LLMs with Continuous Rewards. arXiv:2607.10474,
2026.
Questions and issues can be raised in the code repository.