NEML2

In addition to the MOOSE native material models, MOOSE can also seamlessly interface with the external material modeling library NEML2 Hu and Messner (2025), Hu et al. (2024), and MESSNER et al. (2023).

NEML2, the New Engineering Material modeling Library, version 2, is an offshoot of NEML, an earlier material modeling code developed at Argonne National Laboratory. the library is provided as open source software under a MIT license.

NEML2 extends the key philosophy of its predecessor, i.e., material models are flexible, modular, and can be built from smaller blocks. It also provides modern features that do not exist in the framework of its predecessor such as material model vectorization, automatic differentiation, device-portable just-in-time compilation, operator fusion, lazy tensor evaluation, etc. Moreover, NEML2 can seamlessly integrate with the popular machine learning package PyTorch to take advantage of modern and fast-growing machine learning techniques.

Installation

NEML2 is built from source and installed as a Python package that lives in the same Python environment as PyTorch (a conda environment or a virtual environment). A single install provides both the C++ libraries MOOSE links against and the Python tooling (e.g. neml2-compile, used by the ahead-of-time compilation runtime). The workflow is: provide PyTorch, build and install NEML2, then configure MOOSE.

commentnote:NEML2 uses the PyTorch in your Python environment

The blessed way to enable NEML2 is a PyTorch installed in the active Python environment (a pip wheel, or a from-source build installed into that environment). MOOSE's libtorch setup script builds PyTorch from source and, with the --install-python-package option, can install the Python package needed by NEML2 into that environment. The --with-libtorch path given at configure time (below) points at the C++ libraries that ship inside the environment's PyTorch.

1. Provide PyTorch

NEML2 links against the PyTorch found in your active Python environment. Activate that environment first (so python3 and pip resolve to it), then make PyTorch available.

Recommended: install a PyTorch wheel with pip. Choose a version compatible with NEML2 and matching your CUDA toolkit:


pip install torch

See PyTorch download instructions for more details.

Alternative: build PyTorch from source. Only necessary when a suitable PyTorch is not already installed in the environment and a prebuilt wheel does not fit your needs — for example a specific CUDA architecture, a custom BLAS, or an unsupported platform. Activate the target conda environment, then use MOOSE's libtorch setup script with --install-python-package; without this option, the script installs only the C++ libraries and does not provide the Python package required by NEML2.


cd ~/projects/moose
./scripts/update_and_rebuild_libtorch.sh --install-python-package
python -c "import torch; print(torch.__version__)"
./scripts/update_and_rebuild_neml2.sh

This builds PyTorch against the same OpenBLAS used by MOOSE's PETSc, avoiding the BLAS/LAPACK conflict described below. If the active environment already has a suitable PyTorch installation, do not rebuild it; proceed directly to the NEML2 build in step 2.

warningwarning:BLAS/LAPACK ABI conflict between the PyTorch wheel and PETSc

PyTorch wheels bundle their own BLAS/LAPACK inside libtorch_cpu.so (it exports the standard LP64 symbols dgemm_, dgeev_, ... as well as ILP64 *_64_ variants). MOOSE's PETSc links its own OpenBLAS (e.g., petsc/arch-moose/lib/libopenblas.so.0), which exports the same LP64 symbol names. When a single MOOSE executable loads both libraries, the dynamic linker can interpose one library's BLAS/LAPACK onto the other's calls.

Is this harmful? It is configuration-dependent. Both are standard LP64 BLAS, so in many environments everything runs correctly (the bundled MOOSE-NEML2 test suite passes with no workaround). But if the two implementations disagree on an ABI detail — integer width, threading, or corner-case numerics — the interposition can produce wrong results or crashes in linear algebra, coming from either PETSc solves or PyTorch operators, and often silently.

If you observe such problems, force a single, consistent BLAS/LAPACK across the process with LD_PRELOAD, preloading the OpenBLAS that MOOSE/PETSc is built against so that PyTorch uses it too:


export LD_PRELOAD=$HOME/projects/moose/petsc/arch-moose/lib/libopenblas.so.0

This is safe because PyTorch works with any standard LP64 BLAS, while PETSc requires the specific OpenBLAS it was built with. Building PyTorch from source against the same OpenBLAS avoids the conflict entirely.

2. Build and install NEML2

With PyTorch available in the active environment, run:


cd ~/projects/moose
./scripts/update_and_rebuild_neml2.sh

The script updates the NEML2 submodule together with the submodules of three NEML2 Python dependencies that conda-forge either does not ship or ships only against its own PyTorch: nmhit (framework/contrib/neml2-hit), pyzag (framework/contrib/pyzag), and pyro-ppl (framework/contrib/pyro). Each is pinned to a release compatible with the NEML2 submodule. A plain git submodule update --init does not fetch these submodules; the script initializes them, which needs network access the first time.

The script then installs nmhit, pyzag, and pyro-ppl from these checkouts without network access, skipping any already installed at the checked-out version. A package without a checkout is used as installed, or, if it is not installed, is installed at its pinned version from PyPI. The script then builds NEML2 from source and installs it (non-editable) into the active environment's site-packages, next to PyTorch. Because every install uses --no-deps to leave your pinned PyTorch untouched, the remaining Python dependencies (the build tools scikit-build-core and nanobind, and the runtime dependencies of NEML2 and of these three packages) must already be in the environment. The moose-dev conda package provides them, and the script lists any that are missing before building NEML2. It also checks for an importable PyTorch and cmake, and on success prints the exact ./configure command to run next.

To use the submodules as they are currently checked out, e.g. without network access, pass --skip-submodule-update:


./scripts/update_and_rebuild_neml2.sh --skip-submodule-update

A dependency whose submodule is then not checked out is used as already installed in the environment (e.g. from PyPI); if it is not installed either, the script stops and prints the git submodule update command that fetches it.

schooltip

The script is customizable. Use the --help argument to print a detailed help message listing all options and influential environment variables.

3. Configure MOOSE


./configure --with-neml2 --with-libtorch=$(python3 -c 'import torch, os; print(os.path.dirname(torch.__file__))')

Given without a path, --with-neml2 automatically locates the NEML2 installed in the active Python environment. To override, pass an explicit path or set the NEML2_DIR environment variable:


./configure --with-neml2=/path/to/neml2 --with-libtorch=/path/to/torch

After that, follow the getting started instructions to build MOOSE as usual. The make check_neml2 command can be used to check whether NEML2 is successfully enabled within MOOSE and to inspect the additional compile/link flags.

Using NEML2 in a MOOSE simulation

A dedicated input file syntax block is reserved for MOOSE-NEML2 interaction. The entry point to the syntax block is [NEML2]. Please refer to the NEML2 syntax documentation for more details.

Citing NEML2


@article{neml2softwarex,
  title = {NEML2: An efficient and modular multiphysics constitutive modeling library for hybrid computing environments},
  journal = {SoftwareX},
  volume = {31},
  pages = {102302},
  year = {2025},
  issn = {2352-7110},
  doi = {https://doi.org/10.1016/j.softx.2025.102302},
  url = {https://www.sciencedirect.com/science/article/pii/S2352711025002687},
  author = {Tianchen Hu and Mark C. Messner},
  keywords = {Constitutive model, GPU, Multiphysics}
}

@techreport{neml2osti,
  author      = {Tianchen Hu and Mark C.  Messner and Daniel Schwen and Lynn B.  Munday and Dewen Yushu},
  title       = {NEML2: A High Performance Library for Constitutive Modeling},
  institution = {Argonne National Laboratory (ANL), Argonne, IL (United States); Idaho National Laboratory (INL), Idaho Falls, ID (United States)},
  doi         = {10.2172/2440430},
  url         = {https://www.osti.gov/biblio/2440430},
  place       = {United States},
  year        = {2024},
  month       = {09}
}

@misc{osti_1961125,
  author = {MESSNER, MARK and HU, TIANCHEN and US DOE NE-NEAMS},
  title  = {NEML2 - THE NEW ENGINEERING MATERIAL MODEL LIBRARY, VERSION 2},
  doi    = {10.11578/dc.20230314.1},
  url    = {https://www.osti.gov/biblio/1961125},
  place  = {United States},
  year   = {2023},
  month  = {01}
}

References

  1. Tianchen Hu and Mark C. Messner. Neml2: an efficient and modular multiphysics constitutive modeling library for hybrid computing environments. SoftwareX, 31:102302, 2025. URL: https://www.sciencedirect.com/science/article/pii/S2352711025002687, doi:https://doi.org/10.1016/j.softx.2025.102302.[Export]
  2. Tianchen Hu, Mark C. Messner, Daniel Schwen, Lynn B. Munday, and Dewen Yushu. Neml2: a high performance library for constitutive modeling. Technical Report, Argonne National Laboratory (ANL), Argonne, IL (United States); Idaho National Laboratory (INL), Idaho Falls, ID (United States), 09 2024. URL: https://www.osti.gov/biblio/2440430, doi:10.2172/2440430.[Export]
  3. MARK MESSNER, TIANCHEN HU, and US DOE NE-NEAMS. Neml2 - the new engineering material model library, version 2. 01 2023. URL: https://www.osti.gov/biblio/1961125, doi:10.11578/dc.20230314.1.[Export]