# Differentiable Fortran Without the Rewrite

> Source: <https://sourcefeed.dev/a/differentiable-fortran-without-the-rewrite>
> Published: 2026-07-16 00:56:33+00:00

[AI](https://sourcefeed.dev/c/ai)Article

# Differentiable Fortran Without the Rewrite

LFortran and Enzyme turn validated simulation code into exact-gradient layers for JAX.

[Mariana Souza](https://sourcefeed.dev/u/mariana_souza)

Decades of production physics live in Fortran. CFD, climate, aerospace, and nuclear codes were validated over years of use, yet they sit behind a wall modern ML pipelines cannot cross: they do not expose gradients. Inverse problems, hybrid AI-physics models, and gradient-based design all need those derivatives. The usual answers are painful. Hand-written adjoints take months of expert work and drift out of sync. Finite differences scale poorly and lose accuracy on stiff systems. A full rewrite in [JAX](https://jax.readthedocs.io) or PyTorch throws away the validation investment.

There is a third path that is starting to work. Compile the existing Fortran with [LFortran](https://lfortran.org), differentiate the resulting LLVM IR with [Enzyme](https://enzyme.mit.edu), and wrap the result so it behaves like a native JAX primitive. The stack is experimental, but it already produces exact gradients through multi-step time loops on a real heat solver. For teams that own large Fortran bases, that is a genuine shift in what is possible.

## Why legacy gradients matter now

Scientific machine learning has moved past pure black-box surrogates. Differentiable physics engines let you train neural closures inside a solver, solve inverse heat-transfer problems, or optimize shapes under PDE constraints. Those workflows assume the forward model can be differentiated end-to-end. When the model is 50,000 lines of Fortran 90, that assumption fails.

Enzyme changes the economics. It performs automatic differentiation at the LLVM IR level, so any language that can emit LLVM becomes differentiable without source rewrites. LFortran is the missing piece for Fortran: it targets LLVM cleanly enough that Enzyme can see the arithmetic, loops, and array accesses of a typical scientific kernel. The combination means the derivative code is generated from the same IR that will actually run, rather than from a separate high-level model that may not match the production binary.

This is not the same as source-to-source AD tools that require language subsets or heavy annotation. Because the transform happens after the front-end, temperature-dependent material models, harmonic-mean face conductivities, and explicit Euler time loops all become differentiable as ordinary floating-point operations.

## What the pipeline actually does

The demonstration case is a 220-line Fortran 90 solver for 2D transient heat conduction with temperature-dependent conductivity:

```
ρ cp ∂T/∂t = ∇ · (k(T) ∇T) + Q
```

where `k(T) = k0 + k1 · T`

. Time integration is explicit Euler over many steps. The core stencil uses harmonic means of conductivity at cell faces and applies convection and fixed-temperature boundary conditions. Nothing exotic, yet the nonlinear material model and the multi-step loop already exercise the kinds of control flow that break naive AD approaches.

Compilation proceeds roughly as follows. LFortran lowers the Fortran source to LLVM IR. Enzyme then inserts the reverse-mode (or forward-mode) derivative instructions into that IR. The differentiated object is linked and exposed to Python. A thin wrapper, in the Tesseract system, registers the call as a custom JAX primitive so that `jax.grad`

and `jax.vmap`

treat the Fortran solve like any other differentiable layer.

The result is not approximate. Gradients through the entire time loop match analytic reference values. That match is the real proof point: the reverse-mode tape is correctly tracking every intermediate temperature and every temperature-dependent conductivity evaluation across hundreds of steps.

## Sharp edges you will hit

The work is still experimental. Gradients can return NaN until the right LLVM flags and Enzyme options are dialed in. Developers report manually comparing IR dumps to locate places where a transform silently dropped a value or where Fortran’s pass-by-reference semantics produced unexpected aliasing. Work arrays that look like pure scratch space sometimes need to be treated carefully so that Enzyme does not free or overwrite them before the reverse pass needs them.

Performance trade-offs also appear. Enzyme’s reverse mode stores intermediates; long time loops therefore increase memory traffic. Checkpointing strategies that are common in hand-written adjoints are not yet automatic at this level. Vectorization and OpenMP that the original Fortran relied on may need re-tuning after differentiation, because the reverse sweep has different memory access patterns.

None of these issues are fatal. They are the cost of treating decades-old code as a first-class citizen of a modern AD system rather than a black box.

## What this means for developers in practice

If your team already maintains a validated Fortran solver and you need gradients for optimization or hybrid training, the LFortran-plus-Enzyme route is worth a serious pilot. Start with a self-contained kernel of a few hundred lines that already builds under a modern Fortran compiler. Confirm that LFortran can lower it to clean IR. Run Enzyme on a single time step first, then on the full multi-step loop. Once the numeric gradients match finite differences or an analytic test case, wrap the entry point for JAX.

You do not throw away the original build system. The differentiated binary can sit beside the production binary; only the Python or JAX side of the pipeline changes. That matters for groups that must keep certification or regression suites intact.

The approach competes with three established alternatives:

- Hand-written adjoints remain the gold standard for performance and memory control, but they are expensive to write and maintain.
- Finite differences stay useful for verification and for codes that cannot yet be differentiated, yet they scale linearly with parameter count.
- Pure rewrites in JAX or Julia give the cleanest AD experience and better composability with neural networks, but they require re-validating physics that may have taken years to trust.

LFortran plus Enzyme sits between the second and third options. You keep the original source and still obtain exact reverse-mode gradients. The price is toolchain complexity and the occasional IR-level debugging session.

For green-field work the calculus is different. If you are writing a new solver today and expect heavy use of gradients, a native differentiable language or a carefully structured JAX/PyTorch implementation is still cleaner. The Fortran path shines when the code already exists, is large, and is trusted.

## Where the space is heading

The same LLVM-level idea already works for C and C++. Once the Fortran path stabilizes, mixed-language scientific stacks become differentiable end-to-end without language silos. That opens practical hybrid models: a neural network that predicts a closure term can be trained by back-propagating through a full Fortran time-stepper that still owns the conserved variables and the stable numerical scheme.

Broader adoption will depend on packaging. Most scientific groups will not want to hand-craft Enzyme passes. Higher-level tooling that hides the IR details, provides automatic checkpointing, and integrates cleanly with existing CMake or Make builds will decide whether this stays a research curiosity or becomes a standard option next to finite differences.

The early results already show that the oldest widely used scientific language and the newest automatic-differentiation engines can share a single IR and produce correct gradients. For any developer sitting on a wall of validated Fortran, that is no longer a theoretical possibility. It is an experimental but working path that is ready for careful, high-value pilots.

## Sources & further reading

-
[Differentiable Fortran with LFortran and Enzyme](https://docs.pasteurlabs.ai/projects/tesseract-core/latest/blog/2026-07-09-enzyme-lfortran-autodiff.html)— docs.pasteurlabs.ai

[Mariana Souza](https://sourcefeed.dev/u/mariana_souza)· Senior Editor

Mariana covers the fast-moving world of machine learning and generative AI, with a particular focus on how these technologies are reshaping development workflows. When she isn't stress-testing the latest foundation models, she's usually at a local hackathon.

## Discussion 0

No comments yet

Be the first to weigh in.
