DynEarthSol, DES in short, is a finite element code that solves the momentum balance and the heat transfer in Lagrangian form using unstructured meshes, in two or three dimensions. It can be used to study the long-term deformation of Earth's lithosphere and problems alike.
This repository uses Git submodules for three libraries: nanoflann (always),
mmg (with usemmg=1) and knn-bvh (with openacc=1). make initializes the
ones a build needs, fetching them over the internet before compiling.
For environments without internet access (such as certain HPC compute nodes), pre-downloading all dependencies is highly recommended. To ensure all necessary source files are downloaded upfront, clone the repository with its submodules using the --recurse-submodules flag:
git clone --recurse-submodules https://github.com/GeoFLAC/DynEarthSol.gitIf you have already cloned the repository without the submodules, you can initialize and update them by running the following command inside the DynEarthSol directory:
git submodule update --init --recursiveInstall the dependencies with your package manager; the build finds them on its own, with no paths to edit and none to pass on the command line.
# macOS (Homebrew) -- libomp because Apple clang ships no OpenMP runtime
brew install boost libomp
# Debian / Ubuntu
sudo apt install g++ make libboost-program-options-dev
# Fedora / RHEL
sudo dnf install gcc-c++ make boost-develThe requirements in detail:
- You will need a C++11 compiler. CI builds with g++ 8 through 15, Apple clang and nvc++.
- You will need
Boost::Program_options(1.42 or newer). Packaged versions are found automatically. On macOS the search order is the Homebrewboostkeg, then MacPorts, then the Homebrew prefix itself, then an activated conda environment; elsewhere it is the conda environment, then the system Boost the compiler finds on its own. A prefix is accepted only if it holds both the headers and the library. Package managers come before conda deliberately: a shell that auto-activatesbasehas conda on for everything, so it is the weaker signal of intent, but a conda Boost is still used when it is the only one installed.- To build Boost yourself: download the source from www.boost.org, run
./bootstrap.shthen./b2 --with-program_options -qin the untarred directory, and point the build at it withmake BOOST_ROOT_DIR=/path/to/boost. A build directory is recognised by itsstage/subdirectory, so name the untarred directory, notstage/lib.
- To build Boost yourself: download the source from www.boost.org, run
- The Python tools (
2vtk.py,Dynearthsol.py) need Python 3 with NumPy and SciPy, plus h5py to read vtkhdf output. - macOS users: Apple clang has no built-in OpenMP, so the runtime has to
come from somewhere;
brew install libompis the whole answer for most people. See OpenMP on macOS for the search order, the overrides, and how to build LLVM OpenMP from source when a package manager is not an option.
From the repository root:
make ndims=2 # 2D executable, dynearthsol2d
make # 3D executable, dynearthsol3dThat is the whole procedure. make config prints the compiler and every
dependency path the build resolved to; it is the quickest way to see that
something was found somewhere you did not expect, and the most useful thing to
paste into a bug report. The subsections below cover the cases where the
defaults are not what you want.
- Options go on the command line (
make ndims=2 hdf5=1) or into the corresponding variable at the top of theMakefile; the command line wins. Changing a flag rebuilds what it reaches, so nomake cleanis needed. make check-depsverifies the external libraries, including their architecture, without building.BOOST_ROOT_DIR,HDF5_INCLUDE_DIR,HDF5_LIB_DIRandNVHPC_DIRsit together in an Optional paths block near the top of theMakefile. All may stay blank; set one only to force a specific install, which skips detection for that dependency. Every other dependency's path is declared beside the feature that uses it (OPENMP_*,EXO_*,MMG_*, the GoSPL group). An exported value is honoured too, which is how a module file or a conda activation hook names a prefix once; the catch is that a stale export in a shell profile silently defeats a good package-manager install.make configshows which prefix was used, and an emptyBOOST_ROOT_DIR=on the command line forces detection.opt=2is the default optimized build;opt=3adds-march=native -O3;opt=0is for debugging;opt=-1adds-fsanitize=address, which reports where a memory error occurs and where the memory was allocated without gdb or valgrind, but cannot be combined with valgrind.openmp=0builds a single-threaded executable, which is what valgrind needs.
- nanoflann: header-only KD-tree for nearest-neighbour searches on the CPU. Always required.
- mmg: mesh optimization during remeshing.
Required with
usemmg=1;makeconfigures and builds it undermmg/build. - knn-bvh: K-nearest-neighbour searches
on Bounding Volume Hierarchies, the GPU counterpart of nanoflann. Required with
openacc=1.
- Exodus,
useexo=1, for importing a mesh in the ExodusII format. 3D only.- Suggested building procedure, run in the root directory of DES; it
downloads and builds NetCDF and HDF5, then Exodus, with headers and libraries
landing in
./seacas/includeand./seacas/lib:git clone https://github.com/sandialabs/seacas.git cd seacas && export ACCESS=`pwd` COMPILER=gnu MATIO=NO GNU_PARALLEL=NO CGNS=NO FMT=NO ./install-tpl.sh mkdir build; cd build ../cmake-exodus make; make install
EXO_INCLUDEandEXO_LIB_DIRoverride those defaults.
- Suggested building procedure, run in the root directory of DES; it
downloads and builds NetCDF and HDF5, then Exodus, with headers and libraries
landing in
- MMG,
usemmg=1, for mesh optimization during remeshing, in 2D and 3D. It is themmgsubmodule:make usemmg=1initializes it and buildslibmmg2dorlibmmg3dundermmg/build, so nothing is installed by hand. The configure step ignores an exportedCFLAGS; a tree configured earlier keeps its cached flags untilmmg/buildis removed.MMG_INCLUDEandMMG_LIB_DIRpoint at a different build. - HDF5,
hdf5=1, for writing results in the HDF5-based vtkhdf format, which is compressed (up to 50 % smaller) and opens directly in ParaView.- Install it with
brew install hdf5(macOS),apt install libhdf5-dev(Debian/Ubuntu) ordnf install hdf5-devel(Fedora/RHEL). The build locates it viapkg-configand then the usual install layouts, picking the prefix that matches the host architecture: on a Mac that has used both Homebrew prefixes,h5ccandpkg-configonPATHare often the x86_64 ones. HDF5_INCLUDE_DIRandHDF5_LIB_DIRforce one specific HDF5, an HPC module, a conda env or a hand-built copy:make hdf5=1 HDF5_INCLUDE_DIR=/prefix/include HDF5_LIB_DIR=/prefix/lib. Either one alone is enough; the other is still detected.
- Install it with
- GoSPL (Global Scalable Paleo Landscape
Evolution),
use_gospl=1, for two-way coupling with a surface process model. GoSPL handles erosion, deposition and hillslope diffusion; DES handles tectonics. At each coupling event DES surface velocities are passed to GoSPL, which returns the erosion/deposition increment applied to DES surface nodes.- Requires a GoSPL conda environment, following
the GoSPL installation procedure,
and the gospl_extensions C++
interface library:
git clone https://github.com/GeoFLAC/gospl_extensions.git ~/opt/gospl_extensions cd ~/opt/gospl_extensions/cpp_interface conda activate gospl make install-local
GOSPL_EXT_DIRandCONDA_ENV_PATHoverride the defaults (~/opt/gospl_extensionsand~/miniconda3/envs/gospl).make use_gospl=1also generates thedynearthsol-gosplwrapper script.- See
gospl_driver/README.mdfor build, runtime and coupling details, andgospl_driver/examples/for example configs. The Docker image below ships the whole stack ready to run.
- Requires a GoSPL conda environment, following
the GoSPL installation procedure,
and the gospl_extensions C++
interface library:
Apple clang implements the OpenMP pragmas but ships no OpenMP runtime, so one has to be installed. Almost always this is enough:
brew install libompNothing else to configure: make locates the header and the library itself.
make config reports which one it picked.
-
Search order, highest priority first:
external/openmp-installin the source tree — an LLVM OpenMP built here by hand (see below) keeps taking priority over anything installed system-wide- Homebrew
libomp - Homebrew
llvm - MacPorts
libomp - the activated conda environment,
$CONDA_PREFIX
omp.handlibomp.dylibare searched separately over that same list, because Homebrew'sllvmkeeps itsomp.hunderlib/clang/<version>/includerather than beside the library. Whichever provider is installed therefore supplies both — but a provider holding only one half is skipped for that half alone, somake configis worth a glance if you have several installed.Homebrew is looked for at the prefix matching the machine's architecture --
/opt/homebrewon Apple Silicon,/usr/localon Intel -- and never viaPATH. On a Mac that has run both,PATHregularly offers the other one's tools, and building against those produces libraries of the wrong architecture. PassBREW_PREFIX=/your/prefixif yours is somewhere else. -
Overrides, when the runtime is somewhere the search does not look, or when you want a specific one. Set these on the command line, or edit them in the clang++ branch of the
Makefile, where the OpenMP search lives:make OPENMP_ROOT_DIR=/prefix # /prefix/include + /prefix/lib make OPENMP_INCLUDE_DIR=... OPENMP_LIB_DIR=... # when they are not siblings
The second form is what Homebrew's
llvmneeds if named explicitly, for the reason given above. The exported-variable behaviour is the same as for the Optional paths block. -
Thread-wait performance on Apple Silicon. LLVM
libomphardcodes hybrid-CPU detection for all Apple Silicon, setting thread blocktime to 0 µs: threads yield immediately after each parallel region instead of spin-waiting, which cuts CPU utilisation to ~250 % on a 6-core Mac against ~600 % on Linux. DES therefore setsOMP_WAIT_POLICY=activeat startup on macOS unlessOMP_WAIT_POLICYorKMP_BLOCKTIMEis already set, and prints a notice saying so. To override:export OMP_WAIT_POLICY=passive # yield immediately, lower power export KMP_BLOCKTIME=20 # fine-grained control (ms, libomp only)
-
Building LLVM OpenMP from source, if a package manager is not an option. The result lands in
external/openmp-install, which the search prefers, so no build variable has to be set afterwards. (LLVM OpenMP 19.1.7 or newer will suffice; replacearm64withx86_64on an Intel Mac.)mkdir -p external && cd external curl -L https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.7/cmake-19.1.7.src.tar.xz -o cmake-19.1.7.src.tar.xz tar xf cmake-19.1.7.src.tar.xz curl -L https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.7/openmp-19.1.7.src.tar.xz -o openmp-19.1.7.src.tar.xz tar xf openmp-19.1.7.src.tar.xz mkdir -p openmp-19.1.7.src/build && cd openmp-19.1.7.src/build cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../../openmp-install \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_MODULE_PATH=$(pwd)/../../cmake-19.1.7.src/Modules \ -DCMAKE_OSX_ARCHITECTURES=arm64 \ -DLIBOMP_INSTALL_ALIASES=OFF \ .. make -j4 && make install && cd ../../
- Build the image.
build.shsets the dimension (NDIMS=2) and the compiler (gcc-11; alsogcc-8,clang-14) at its top; edit them there or pass them in the environment../build.sh
- Run it
docker run --rm -it dynearthsol/gcc-11
GOSPL=1 ./build.shbuildsdynearthsol/gcc-11-gosplinstead: a 3D executable with GoSPL coupling, thegosplconda environment andgospl_extensionsincluded, so no conda setup is needed on the host. Mount a directory holding the cfg and the GoSPL YAML and rundynearthsol-gosplinside it; seegospl_driver/README.md.docker/Dockerfile.cudais the NVHPC image the GPU CI builds in.
Here are a few practical examples for common build configurations (run these from the project root):
# default optimized 3D build
make
# show the compiler, flags and dependency paths the build resolved to
make config
# check the external libraries are present, without building
make check-deps
# debugging build (no optimizations, no OpenMP)
make opt=0 openmp=0
# build 2D version
make ndims=2
# enable MMG mesh optimization (builds the mmg submodule)
make usemmg=1
# enable Exodus mesh import, 3D only (requires seacas/exodus libs)
make useexo=1
# enable HDF5-based vtkhdf output support (requires HDF5)
make hdf5=1
# enable GoSPL surface process coupling (requires gospl_extensions and gospl conda env)
make use_gospl=1
# NVHPC/profiler build (uses nvc++ when set)
make nprof=1
# embed the uncommitted code changes in the executable (off by default)
make snapshot_diff=1
# OpenACC build (NVHPC compiler)
make openacc=1
# OpenACC targeting a specific GPU (else from nvidia-smi, default 80; see make config)
make openacc=1 GPU_CC=90- Execute
dynearthsol2d input.cfg(ordynearthsol3d). The input file is required;-hor--helplists every parameter with its description. - The input format is documented in
examples/defaults.cfg, and working cases are underexamples/. - Process exit codes are two digits whose first digit says who fixes it: 1x the input, 2x the environment, 3x-6x the code. The table is in CONTRIBUTING.md.
- The input file generator builds a cfg from a web form.
- Benchmark cases with analytical solutions are under
benchmarks/; the regression cases the developers compare against are underbenchmarks-cores/. - Provenance: every executable, run and frame records where it came from:
strings <exe> | grep '^build\.snapshot\.'shows the build,<modelname>.manifesteach run, and every frame its own origin. The fields are described in doc/provenance.md. - Running with GoSPL: set
surface_process_option = 11in the cfg and use the generated wrapper; in the Docker image the environment is already active.Seeconda activate gospl ./dynearthsol-gospl your_input.cfg
gospl_driver/README.mdandgospl_driver/examples/for the details.
- Run
2vtk.py modelnameto convert the binary output to VTK files;2vtk.py -hlists the options, among them markers (-m), principal stresses (-p) and full tensors (-t). - What a frame contains is set in the input file (
has_marker_output,is_outputting_averaged_fields, ... in the[sim]section ofexamples/defaults.cfg), not by editing sources. - With
hdf5=1the output is already.vtkhdf, which ParaView opens directly;2vtk.py -uadds the derived fields to it in place. Plain VTK files open in ParaView or VisIt.
Bug reports, comments and suggestions are welcome on the issue tracker; a template asks for what a fix needs. Development conventions -- building, regression tests, commit messages, pull requests, releases -- are in CONTRIBUTING.md, and user-visible changes per release in CHANGELOG.md. AI-assisted contributions are welcome under the policy there; you remain responsible for what your assistant produces. An assistant working in a checkout reads AGENTS.md, which points it at the parameter reference, the templates and the conventions.
Cite the DynEarthSol v2.0 paper and the version you used. CITATION.cff carries the version DOI, and GitHub renders it under Cite this repository; the badge above is the concept DOI that always resolves to the latest release.
This program is free software: you can redistribute it and/or modify it under the terms of the MIT / X Windows System license. See LICENSE for the full text.
The files under 3x3-C/, tetgen/ and triangle/ are distributed under their
own licenses. The submodules knn-bvh, mmg and nanoflann are separate
projects with their own.