build(meson): updated build system. Note that this build system should be able to bring in MFEM and all needed deps automatically (tested on ubuntu, fedora, and macos)

This commit is contained in:
2026-11-09 13:50:06 -05:00
parent 811bbd9694
commit 829e53d56e
6 changed files with 3155 additions and 182 deletions

2936
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

164
justfile
View File

@@ -1,14 +1,11 @@
set shell := ["bash", "-euo", "pipefail", "-c"] set shell := ["bash", "-euo", "pipefail", "-c"]
meson_bin := env_var_or_default("MESON_BIN", "meson") meson_bin := env_var_or_default("MESON_BIN", "meson")
python_bin := env_var_or_default("PYTHON", "python3")
jobs := env_var_or_default("MFEM_JOBS", "4") jobs := env_var_or_default("MFEM_JOBS", "4")
allow_preinstalled := env_var_or_default("MFEM_ALLOW_PREINSTALLED", "false") allow_preinstalled := env_var_or_default("MFEM_ALLOW_PREINSTALLED", "false")
dependency_prefix := env_var_or_default("MFEM_DEPENDENCY_PREFIX", "") dependency_prefix := env_var_or_default("MFEM_DEPENDENCY_PREFIX", "")
cuda_home := env_var_or_default("CUDA_HOME", "") cuda_home := env_var_or_default("CUDA_HOME", "")
cuda_arch := env_var_or_default("MFEM_CUDA_ARCH", "native") cuda_arch := env_var_or_default("MFEM_CUDA_ARCH", "native")
web_port := env_var_or_default("MFEM_WEB_PORT", "8000")
macos_target := env_var_or_default("MACOSX_DEPLOYMENT_TARGET", "11.0")
project_root := justfile_directory() project_root := justfile_directory()
build_root := project_root + "/" + env_var_or_default("MFEM_BUILD_ROOT", "build") build_root := project_root + "/" + env_var_or_default("MFEM_BUILD_ROOT", "build")
@@ -19,22 +16,12 @@ parallel_dir := build_root + "/parallel"
debug_dir := build_root + "/debug" debug_dir := build_root + "/debug"
cuda_dir := build_root + "/cuda" cuda_dir := build_root + "/cuda"
hip_dir := build_root + "/hip" hip_dir := build_root + "/hip"
wasm_dir := build_root + "/emscripten"
wasm_cache := build_root + "/emscripten-cache"
basic_install := install_root + "/basic" basic_install := install_root + "/basic"
serial_install := install_root + "/serial" serial_install := install_root + "/serial"
parallel_install := install_root + "/parallel" parallel_install := install_root + "/parallel"
debug_install := install_root + "/debug" debug_install := install_root + "/debug"
cuda_install := install_root + "/cuda" cuda_install := install_root + "/cuda"
hip_install := install_root + "/hip" hip_install := install_root + "/hip"
benchmark_trials := env_var_or_default("MFEM_BENCH_TRIALS", "5")
benchmark_mesh_n := env_var_or_default("MFEM_BENCH_MESH_N", "48")
benchmark_order := env_var_or_default("MFEM_BENCH_ORDER", "3")
benchmark_applications := env_var_or_default("MFEM_BENCH_APPLICATIONS", "50")
benchmark_minimum_apply_seconds := env_var_or_default("MFEM_BENCH_MIN_SECONDS", "1.0")
benchmark_max_applications := env_var_or_default("MFEM_BENCH_MAX_APPLICATIONS", "1000000")
benchmark_omp_threads := env_var_or_default("MFEM_BENCH_OMP_THREADS", "8")
benchmark_mpi_ranks := env_var_or_default("MFEM_BENCH_MPI_RANKS", "4")
cuda_cc := env_var_or_default("MFEM_CUDA_CC", env_var_or_default("CC", "cc")) cuda_cc := env_var_or_default("MFEM_CUDA_CC", env_var_or_default("CC", "cc"))
cuda_cxx := env_var_or_default("MFEM_CUDA_CXX", env_var_or_default("CXX", "c++")) cuda_cxx := env_var_or_default("MFEM_CUDA_CXX", env_var_or_default("CXX", "c++"))
@@ -54,7 +41,6 @@ configure dir install_dir buildtype profile allow *extra:
"-Dallow_preinstalled={{ allow }}" "-Dallow_preinstalled={{ allow }}"
"-Ddependency_prefix={{ dependency_prefix }}" "-Ddependency_prefix={{ dependency_prefix }}"
"-Djobs={{ jobs }}" "-Djobs={{ jobs }}"
"-Dbuild_examples=true"
"-Dbuild_tests=true" "-Dbuild_tests=true"
) )
if [[ -f "{{ dir }}/meson-private/coredata.dat" ]]; then if [[ -f "{{ dir }}/meson-private/coredata.dat" ]]; then
@@ -71,7 +57,7 @@ basic: (configure basic_dir basic_install "release" "minimal" allow_preinstalled
serial: (configure serial_dir serial_install "release" "portable" allow_preinstalled "-Dmfem_mpi=disabled" "-Dmfem_metis=disabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled") (build-and-test serial_dir) serial: (configure serial_dir serial_install "release" "portable" allow_preinstalled "-Dmfem_mpi=disabled" "-Dmfem_metis=disabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled") (build-and-test serial_dir)
parallel: (configure parallel_dir parallel_install "release" "portable" allow_preinstalled "-Dmfem_mpi=enabled" "-Dmfem_sundials=enabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled" "-Dbuild_benchmarks=true") (build-and-test parallel_dir) parallel: (configure parallel_dir parallel_install "release" "portable" allow_preinstalled "-Dmfem_mpi=enabled" "-Dmfem_sundials=enabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled") (build-and-test parallel_dir)
debug: (configure debug_dir debug_install "debug" "portable" allow_preinstalled) (build-and-test debug_dir) debug: (configure debug_dir debug_install "debug" "portable" allow_preinstalled) (build-and-test debug_dir)
@@ -117,8 +103,6 @@ cuda:
"-Dallow_preinstalled={{ allow_preinstalled }}" "-Dallow_preinstalled={{ allow_preinstalled }}"
"-Ddependency_prefix={{ dependency_prefix }}" "-Ddependency_prefix={{ dependency_prefix }}"
"-Djobs={{ jobs }}" "-Djobs={{ jobs }}"
"-Dbuild_examples=true"
"-Dbuild_benchmarks=true"
"-Dbuild_tests=true" "-Dbuild_tests=true"
"-Dmfem_cuda=enabled" "-Dmfem_cuda=enabled"
"-Dmfem_hip=disabled" "-Dmfem_hip=disabled"
@@ -133,152 +117,6 @@ cuda:
hip: (configure hip_dir hip_install "release" "portable" allow_preinstalled "-Dmfem_hip=enabled" "-Dmfem_cuda=disabled") (build-and-test hip_dir) hip: (configure hip_dir hip_install "release" "portable" allow_preinstalled "-Dmfem_hip=enabled" "-Dmfem_cuda=disabled") (build-and-test hip_dir)
emscripten:
#!/usr/bin/env bash
set -euo pipefail
mkdir -p "{{ wasm_cache }}"
setup_args=(
"{{ wasm_dir }}"
"--cross-file={{ project_root }}/cross/wasm32.ini"
"--prefix={{ install_root }}/emscripten"
"--buildtype=release"
"-Dfeature_profile=portable"
"-Dallow_preinstalled=false"
"-Djobs={{ jobs }}"
"-Dbuild_python=false"
"-Dbuild_examples=true"
"-Dbuild_tests=true"
)
if [[ -f "{{ wasm_dir }}/meson-private/coredata.dat" ]]; then
setup_args=(--reconfigure "${setup_args[@]}")
fi
EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" setup "${setup_args[@]}"
EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" compile -C "{{ wasm_dir }}"
EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" test -C "{{ wasm_dir }}" --print-errorlogs
serve-emscripten port=web_port: emscripten
@echo "MFEM browser demo: http://0.0.0.0:{{ port }}"
"{{ python_bin }}" -m http.server "{{ port }}" --bind 0.0.0.0 --directory "{{ wasm_dir }}/web"
python:
mkdir -p "{{ project_root }}/dist"
MACOSX_DEPLOYMENT_TARGET="{{ macos_target }}" "{{ python_bin }}" -m build --wheel --no-isolation --outdir "{{ project_root }}/dist"
run-serial: serial
"{{ serial_dir }}/examples/mfem-serial-poisson"
run-parallel ranks="4": parallel
"{{ python_bin }}" "{{ project_root }}/tools/run_mpi_test.py" --launcher "{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" --processes "{{ ranks }}" "{{ parallel_dir }}/examples/mfem-parallel-hypre"
run-cuda ranks="2": cuda
"{{ python_bin }}" "{{ project_root }}/tools/run_mpi_test.py" --launcher "{{ cuda_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" --processes "{{ ranks }}" "{{ cuda_dir }}/examples/mfem-parallel-hypre" cuda
benchmark: benchmark-cpu
benchmark-cpu: parallel
#!/usr/bin/env bash
set -euo pipefail
launcher="{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec"
dep_prefix="{{ dependency_prefix }}"
if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then
for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do
[[ -x "$candidate" ]] && launcher="$candidate" && break
done
fi
if [[ ! -x "$launcher" ]]; then
launcher="$(command -v mpiexec || command -v mpirun || true)"
fi
[[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; }
if [[ -n "$dep_prefix" ]]; then
export PATH="$dep_prefix/bin:$PATH"
if [[ "$(uname -s)" == Darwin ]]; then
export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}"
else
export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}"
fi
fi
"{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \
--executable "{{ parallel_dir }}/benchmarks/mfem-backend-benchmark" \
--launcher "$launcher" \
--cases cpu,ceed-cpu,omp,mpi \
--omp-threads "{{ benchmark_omp_threads }}" \
--mpi-ranks "{{ benchmark_mpi_ranks }}" \
--trials "{{ benchmark_trials }}" \
--mesh-n "{{ benchmark_mesh_n }}" \
--order "{{ benchmark_order }}" \
--applications "{{ benchmark_applications }}" \
--minimum-apply-seconds "{{ benchmark_minimum_apply_seconds }}" \
--max-applications "{{ benchmark_max_applications }}" \
--output-dir "{{ parallel_dir }}/benchmarks/results"
benchmark-cuda: cuda
#!/usr/bin/env bash
set -euo pipefail
launcher="{{ cuda_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec"
dep_prefix="{{ dependency_prefix }}"
if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then
for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do
[[ -x "$candidate" ]] && launcher="$candidate" && break
done
fi
if [[ ! -x "$launcher" ]]; then
launcher="$(command -v mpiexec || command -v mpirun || true)"
fi
[[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; }
if [[ -n "$dep_prefix" ]]; then
export PATH="$dep_prefix/bin:$PATH"
if [[ "$(uname -s)" == Darwin ]]; then
export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}"
else
export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}"
fi
fi
"{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \
--executable "{{ cuda_dir }}/benchmarks/mfem-backend-benchmark" \
--launcher "$launcher" \
--cases cpu,ceed-cpu,omp,mpi,cuda,ceed-cuda \
--omp-threads "{{ benchmark_omp_threads }}" \
--mpi-ranks "{{ benchmark_mpi_ranks }}" \
--trials "{{ benchmark_trials }}" \
--mesh-n "{{ benchmark_mesh_n }}" \
--order "{{ benchmark_order }}" \
--applications "{{ benchmark_applications }}" \
--minimum-apply-seconds "{{ benchmark_minimum_apply_seconds }}" \
--max-applications "{{ benchmark_max_applications }}" \
--output-dir "{{ cuda_dir }}/benchmarks/results"
benchmark-quick: parallel
#!/usr/bin/env bash
set -euo pipefail
launcher="{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec"
dep_prefix="{{ dependency_prefix }}"
if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then
for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do
[[ -x "$candidate" ]] && launcher="$candidate" && break
done
fi
if [[ ! -x "$launcher" ]]; then
launcher="$(command -v mpiexec || command -v mpirun || true)"
fi
[[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; }
if [[ -n "$dep_prefix" ]]; then
export PATH="$dep_prefix/bin:$PATH"
if [[ "$(uname -s)" == Darwin ]]; then
export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}"
else
export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}"
fi
fi
"{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \
--executable "{{ parallel_dir }}/benchmarks/mfem-backend-benchmark" \
--launcher "$launcher" \
--cases cpu,ceed-cpu,omp,mpi \
--omp-threads "{{ benchmark_omp_threads }}" \
--mpi-ranks "{{ benchmark_mpi_ranks }}" \
--trials 1 --mesh-n 16 --order 2 --applications 5 \
--minimum-apply-seconds 0 \
--output-dir "{{ parallel_dir }}/benchmarks/quick-results"
install-basic: basic install-basic: basic
"{{ meson_bin }}" install -C "{{ basic_dir }}" "{{ meson_bin }}" install -C "{{ basic_dir }}"

3
llvm_compiler.ini Normal file
View File

@@ -0,0 +1,3 @@
[binaries]
c = '/opt/homebrew/opt/llvm/bin/clang'
cpp = '/opt/homebrew/opt/llvm/bin/clang++'

View File

@@ -1,11 +1,11 @@
project( project(
'meson-mfem-template', 'serif',
['c', 'cpp'], ['c', 'cpp'],
version: '0.1.0', version: '0.1.0',
meson_version: '>=1.9.1', meson_version: '>=1.9.1',
default_options: [ default_options: [
'c_std=c11', 'c_std=c11',
'cpp_std=c++23', 'cpp_std=c++26',
'warning_level=2', 'warning_level=2',
], ],
) )
@@ -35,13 +35,42 @@ endif
subdir('build-check') subdir('build-check')
subdir('build-config') subdir('build-config')
subdir('include/meson_mfem_template') # Stellar mesh construction uses the bundled STROID with the same MFEM and C++ ABI.
stroid_project = subproject('stroid', default_options: [
'build_tests=false',
'build_tools=false',
'build_python=false',
'pkg_config=false',
])
stroid_dep = stroid_project.get_variable('stroid_dep')
subdir('src') subdir('src')
# Register the original library first: RayFEM's archive reader depends on SERiF.
# Only downstream consumers receive RayFEM, keeping the library graph acyclic.
meson.override_dependency('serif', declare_dependency(
dependencies: serif_dep,
variables: {'libdir': fs.parent(serif_lib.full_path())},
))
rayfem_project = subproject('rayfem', default_options: [
'mfem_provider=external',
'serif=enabled',
'build_viewer=enabled',
'build_examples=disabled',
'build_tests=disabled',
])
rayfem_dep = rayfem_project.get_variable('rayfem_dep')
serif_dep = declare_dependency(dependencies: [serif_dep, rayfem_dep])
subdir('tests') subdir('tests')
summary( summary(
{ {
'MFEM provider': mfem_provider, 'MFEM provider': mfem_provider,
'build type': get_option('buildtype'),
'optimization': get_option('optimization'),
'debug symbols': get_option('debug'),
'bundled MFEM debug checks': mfem_provider == 'system' ? 'external' : mfem_debug_checks.to_string(),
'dependency profile': get_option('feature_profile'), 'dependency profile': get_option('feature_profile'),
'allow preinstalled': get_option('allow_preinstalled'), 'allow preinstalled': get_option('allow_preinstalled'),
'parallel MPI/Hypre': mfem_has_mpi, 'parallel MPI/Hypre': mfem_has_mpi,
@@ -55,9 +84,10 @@ summary(
'libCEED': mfem_features.get('ceed'), 'libCEED': mfem_features.get('ceed'),
'FMS': mfem_features.get('fms'), 'FMS': mfem_features.get('fms'),
'Algoim': mfem_features.get('algoim'), 'Algoim': mfem_features.get('algoim'),
'SparseDirect backend': serif_sparse_direct_backend,
'Python bindings': get_option('build_python'), 'Python bindings': get_option('build_python'),
'tests': get_option('build_tests'), 'tests': get_option('build_tests'),
}, },
section: 'meson-mfem-template ' + meson.project_version(), section: 'serif ' + meson.project_version(),
bool_yn: true, bool_yn: true,
) )

View File

@@ -3,7 +3,7 @@ option('feature_profile', type: 'combo', choices: ['minimal', 'portable', 'full'
option('build_python', type: 'boolean', value: false, description: 'Build the nanobind Python extension and install native assets inside the Python package.') option('build_python', type: 'boolean', value: false, description: 'Build the nanobind Python extension and install native assets inside the Python package.')
option('build_tests', type: 'boolean', value: true, description: 'Register serial, parallel, and Python smoke tests when applicable.') option('build_tests', type: 'boolean', value: true, description: 'Register serial, parallel, and Python smoke tests when applicable.')
option('build_checks', type: 'boolean', value: true, description: 'Build the compile-time checks for SERiF type invariants.') option('build_checks', type: 'boolean', value: true, description: 'Build the compile-time checks for SERiF type invariants.')
option('sandbox_expected_errors', type: 'array', value: ['finite_sandbox:NON_FINITE_VALUE_ERROR', 'quadrature_sandbox:INVALID_QUADRATURE_ORDER'], description: 'Intentional error examples, as sandbox_name:ERROR_CODE. Other sandboxes must exit successfully.') option('sandbox_expected_errors', type: 'array', value: ['finite_sandbox:NON_FINITE_VALUE_ERROR', 'quadrature_sandbox:INVALID_QUADRATURE_ORDER', 'eos_sandbox:EOS_OUTSIDE_DOMAIN'], description: 'Intentional error examples, as sandbox_name:ERROR_CODE. Other sandboxes must exit successfully.')
option('install_mfem', type: 'boolean', value: true, description: 'Install the source-built MFEM bundle and its runtime dependencies.') option('install_mfem', type: 'boolean', value: true, description: 'Install the source-built MFEM bundle and its runtime dependencies.')
option('dependency_prefix', type: 'string', value: '', description: 'Explicit prefix containing optional TPLs. Used even when allow_preinstalled=false.') option('dependency_prefix', type: 'string', value: '', description: 'Explicit prefix containing optional TPLs. Used even when allow_preinstalled=false.')
option('jobs', type: 'integer', min: 1, max: 1024, value: 4, description: 'Parallel jobs for the CMake/Make source bundle.') option('jobs', type: 'integer', min: 1, max: 1024, value: 4, description: 'Parallel jobs for the CMake/Make source bundle.')
@@ -13,6 +13,8 @@ option('mfem_precision', type: 'combo', choices: ['double', 'single'], value: 'd
option('python_install_native', type: 'boolean', value: true, description: 'Install MFEM headers, CMake/pkg-config data, and runtime libraries under the Python package.') option('python_install_native', type: 'boolean', value: true, description: 'Install MFEM headers, CMake/pkg-config data, and runtime libraries under the Python package.')
option('macos_deployment_target', type: 'string', value: '', description: 'Minimum macOS version for native artifacts (15.0 supports C++23 std::print); ignored on other systems. Empty uses the toolchain default.') option('macos_deployment_target', type: 'string', value: '', description: 'Minimum macOS version for native artifacts (15.0 supports C++23 std::print); ignored on other systems. Empty uses the toolchain default.')
option('sparse_direct', type: 'combo', choices: ['auto', 'accelerate', 'umfpack', 'none'], value: 'auto', description: 'Backend of the SparseDirect preconditioner inverse. auto: Accelerate on macOS, else UMFPACK when found, else none (minimal profile: none). Explicit choices are required to be available. none keeps the strategy but makes its preparation fail.')
option('magic_enum_hash', type: 'boolean', value: false, description: 'Enable hash support in magic_enum. This is a compile-time option that enables std::hash for magic_enum types.') option('magic_enum_hash', type: 'boolean', value: false, description: 'Enable hash support in magic_enum. This is a compile-time option that enables std::hash for magic_enum types.')
option('mfem_mpi', type: 'feature', value: 'auto', description: 'MPI parallel MFEM; implies Hypre.') option('mfem_mpi', type: 'feature', value: 'auto', description: 'MPI parallel MFEM; implies Hypre.')

View File

@@ -1,27 +1,143 @@
subdir('include/serif')
include_dir = include_directories('include') include_dir = include_directories('include')
# TODO: Really we should make a dependency graph between the various modules serif_core_sources = files(
# and then make sublibraries for each module that build themselves in the correct order 'lib/serif/utils/serialize/archive.cpp',
# and then link together at the end. 'lib/serif/utils/serialize/top.cpp',
serif_sources = files( 'lib/serif/utils/serialize/format.cpp',
'lib/serif/utils/serialize/provenance.cpp',
'lib/serif/solver/nonlinear/options.cpp',
'lib/serif/solver/linear/linear.cpp',
'lib/serif/solver/seed/polytrope.cpp',
'lib/serif/solver/seed/fitted.cpp',
'lib/serif/model/specifications.cpp',
'lib/serif/discretization/blocks/system_layout.cpp',
'lib/serif/utils/laneemden/solution.cpp',
'lib/serif/utils/laneemden/scaling.cpp',
'lib/serif/solver/normalization/dimensionless.cpp',
'lib/serif/solver/normalization/diagonal.cpp',
'lib/serif/solver/normalization/riesz_factors.cpp',
'lib/serif/solver/normalization/scales.cpp',
'lib/serif/solver/normalization/validation.cpp',
'lib/serif/solver/normalization/packing.cpp',
'lib/serif/discretization/domain/mesh/topology.cpp', 'lib/serif/discretization/domain/mesh/topology.cpp',
'lib/serif/discretization/domain/schema/validation/results.cpp', 'lib/serif/discretization/domain/schema/validation/results.cpp',
'lib/serif/discretization/quadrature/policy.cpp', 'lib/serif/discretization/quadrature/policy.cpp',
'lib/serif/eos/models/polytropic.cpp', 'lib/serif/eos/models/polytropic.cpp',
'lib/serif/mapping/compactification/kelvin.cpp', 'lib/serif/geometry/surface/isobaric.cpp',
'lib/serif/mapping/data.cpp', 'lib/serif/geometry/deformation/determinant_polynomial.cpp',
'lib/serif/mapping/domain_mapper.cpp', 'lib/serif/geometry/deformation/harmonics.cpp',
'lib/serif/mapping/transformations.cpp', 'lib/serif/geometry/deformation/radial_extension.cpp',
'lib/serif/mapping/volume_cache.cpp', 'lib/serif/geometry/deformation/radial_interpolation.cpp',
'lib/serif/mapping/evaluator.cpp', 'lib/serif/geometry/deformation/surface_embedding.cpp',
'lib/serif/mapping/coefficients.cpp'
) )
serif_mfem_sources = files(
'lib/serif/backend/mfem/runtime.cpp',
'lib/serif/backend/mfem/model/finite_elements.cpp',
'lib/serif/backend/mfem/serialize/resources.cpp',
'lib/serif/backend/mfem/serialize/top.cpp',
'lib/serif/backend/mfem/solver/linear/solve.cpp',
'lib/serif/backend/mfem/operators/actions.cpp',
'lib/serif/backend/mfem/model/deformation.cpp',
'lib/serif/backend/mfem/model/system.cpp',
'lib/serif/backend/mfem/model/scalar_row.cpp',
'lib/serif/backend/mfem/model/surface_potential.cpp',
'lib/serif/backend/mfem/model/system_selection.cpp',
'lib/serif/backend/mfem/operators/replaced_rows.cpp',
'lib/serif/backend/mfem/discretization/element_coordinates.cpp',
'lib/serif/backend/mfem/operators/linearized_block.cpp',
'lib/serif/backend/mfem/solver/preconditioner/border.cpp',
'lib/serif/backend/mfem/solver/preconditioner/coupling.cpp',
'lib/serif/backend/mfem/solver/preconditioner/coupling_selection.cpp',
'lib/serif/backend/mfem/solver/preconditioner/inverse/amg.cpp',
'lib/serif/backend/mfem/solver/preconditioner/inverse/dense.cpp',
'lib/serif/backend/mfem/solver/preconditioner/inverse/diagonal.cpp',
'lib/serif/backend/mfem/solver/preconditioner/inverse/sparse_direct.cpp',
'lib/serif/backend/mfem/solver/preconditioner/inverse/validation.cpp',
'lib/serif/backend/mfem/solver/preconditioner/solver.cpp',
'lib/serif/backend/mfem/projection/radial.cpp',
'lib/serif/backend/mfem/solver/normalization/operators.cpp',
'lib/serif/backend/mfem/discretization/mass_diagonal.cpp',
'lib/serif/backend/mfem/discretization/basis_evaluation.cpp',
'lib/serif/backend/mfem/discretization/reconstruction.cpp',
'lib/serif/backend/mfem/discretization/boundary_trace.cpp',
'lib/serif/backend/mfem/mapping/compactification/kelvin.cpp',
'lib/serif/backend/mfem/mapping/data.cpp',
'lib/serif/backend/mfem/mapping/domain_mapper.cpp',
'lib/serif/backend/mfem/mapping/transformations.cpp',
'lib/serif/backend/mfem/mapping/volume_cache.cpp',
'lib/serif/backend/mfem/mapping/evaluator.cpp',
'lib/serif/backend/mfem/geometry/deformation/geometry_step.cpp',
'lib/serif/backend/mfem/geometry/deformation/inputs.cpp',
'lib/serif/backend/mfem/geometry/deformation/radial_interpolation.cpp',
'lib/serif/backend/mfem/geometry/deformation/radial_locator.cpp',
'lib/serif/backend/mfem/geometry/deformation/reference_geometry.cpp',
'lib/serif/backend/mfem/geometry/deformation/surface_metric.cpp',
'lib/serif/backend/mfem/shared/reference_tracking.cpp',
'lib/serif/backend/mfem/shared/parallel.cpp',
'lib/serif/backend/mfem/discretization/topology.cpp',
)
# The core deliberately receives no MFEM headers or link dependencies.
serif_core_lib = static_library(
'serif_core',
serif_core_sources,
include_directories: include_dir,
dependencies: [nameof_dep, magic_enum_dep],
pic: true,
)
serif_core_dep = declare_dependency(
include_directories: include_dir,
link_with: serif_core_lib,
dependencies: [nameof_dep, magic_enum_dep],
)
# Backend of the SparseDirect preconditioner inverse (option sparse_direct). Exactly one implementation of
# inverse/direct_lu.hpp is compiled into serif_direct_lu and linked whole into libserif.
direct_lu_root = 'lib/serif/backend/mfem/solver/preconditioner/inverse/'
sparse_direct = get_option('sparse_direct')
accelerate_dep = dependency('appleframeworks', modules: ['Accelerate'], required: false)
# Accelerate's sparse LU (macOS 15.5 SDK or newer); its availability is also checked at run time.
accelerate_lu_ok = host_machine.system() == 'darwin' and accelerate_dep.found() and cpp.compiles(
'#include <Accelerate/Accelerate.h>\nint main() { return SparseFactorizationLU == 80 ? 0 : 1; }',
args: ['-std=c++20'], dependencies: accelerate_dep, name: 'Accelerate sparse LU')
umfpack_dep = dependency('UMFPACK', required: sparse_direct == 'umfpack')
if sparse_direct == 'auto'
if get_option('feature_profile') == 'minimal'
sparse_direct = 'none'
elif accelerate_lu_ok
sparse_direct = 'accelerate'
elif umfpack_dep.found()
sparse_direct = 'umfpack'
else
sparse_direct = 'none'
endif
elif sparse_direct == 'accelerate' and not accelerate_lu_ok
error('sparse_direct=accelerate needs macOS with an SDK providing Accelerate SparseFactorizationLU (macOS 15.5 SDK).')
endif
if sparse_direct == 'accelerate'
# Accelerate's headers include CoreGraphics, which is not valid C++26, so this one file is built as C++20.
serif_direct_lu_lib = static_library('serif_direct_lu', direct_lu_root + 'direct_lu_accelerate.cpp',
dependencies: accelerate_dep, override_options: ['cpp_std=c++20'], pic: true)
direct_lu_deps = [accelerate_dep]
elif sparse_direct == 'umfpack'
serif_direct_lu_lib = static_library('serif_direct_lu', direct_lu_root + 'direct_lu_umfpack.cpp',
dependencies: umfpack_dep, pic: true)
direct_lu_deps = [umfpack_dep]
else
serif_direct_lu_lib = static_library('serif_direct_lu', direct_lu_root + 'direct_lu_none.cpp', pic: true)
direct_lu_deps = []
endif
serif_sparse_direct_backend = sparse_direct
serif_lib = library( serif_lib = library(
'serif', 'serif',
serif_sources, serif_mfem_sources,
link_whole: [serif_core_lib, serif_direct_lu_lib],
include_directories: include_dir, include_directories: include_dir,
dependencies: [mfem_dep, nameof_dep, magic_enum_dep], dependencies: [mfem_dep, nameof_dep, magic_enum_dep, stroid_dep] + direct_lu_deps,
build_rpath: mfem_runtime_prefix == '' ? '' : mfem_runtime_prefix / 'lib', build_rpath: mfem_runtime_prefix == '' ? '' : mfem_runtime_prefix / 'lib',
) )
@@ -33,10 +149,49 @@ serif_dep = declare_dependency(
if get_option('build_checks') if get_option('build_checks')
checks_srcs = files( checks_srcs = files(
'compile_time_checks/serif/solver/continuation.cpp',
'compile_time_checks/serif/solver/public_contracts.cpp',
'compile_time_checks/serif/model/description.cpp',
'compile_time_checks/serif/model/finite_elements.cpp',
'compile_time_checks/serif/model/state.cpp',
'compile_time_checks/serif/model/scalar_row.cpp',
'compile_time_checks/serif/model/normalization.cpp',
'compile_time_checks/serif/model/density_primal.cpp',
'compile_time_checks/serif/model/barotropic_density.cpp',
'compile_time_checks/serif/model/validation.cpp',
'compile_time_checks/serif/model/execution_validation.cpp',
'compile_time_checks/serif/solver/preconditioner/layout.cpp',
'compile_time_checks/serif/solver/preconditioner/coupling.cpp',
'compile_time_checks/serif/solver/preconditioner/inverses.cpp',
'compile_time_checks/serif/utils/laneemden.cpp',
'compile_time_checks/serif/utils/projection.cpp',
'compile_time_checks/serif/solver/normalization/dimensionless.cpp',
'compile_time_checks/serif/solver/normalization/plan.cpp',
'compile_time_checks/serif/solver/normalization/algebra.cpp',
'compile_time_checks/serif/geometry/surface_storage_meanfield.cpp',
'compile_time_checks/serif/operators/coordinate_identity_meanfield.cpp',
'compile_time_checks/serif/geometry/deformation_meanfield.cpp',
'compile_time_checks/serif/discretization/fields_meanfield.cpp',
'compile_time_checks/serif/eos/consumers_meanfield.cpp',
'compile_time_checks/serif/dimensions/catalogue_meanfield.cpp',
'compile_time_checks/serif/utils/dependencies/binding.cpp',
'compile_time_checks/serif/utils/dependencies/key_list.cpp',
'compile_time_checks/serif/utils/dependencies/dependency_context.cpp',
'compile_time_checks/serif/utils/dependencies/computation_graph.cpp',
'compile_time_checks/serif/utils/dependencies/mixed_errors.cpp',
'compile_time_checks/serif/operators/computation_owners.cpp',
'compile_time_checks/serif/operators/plan.cpp',
'compile_time_checks/serif/dimensions/quantities.cpp',
'compile_time_checks/serif/backend/mfem/discretization/quadrature/mfem_static_order.cpp',
'compile_time_checks/serif/geometry/surface.cpp',
'compile_time_checks/serif/geometry/surface_boundary.cpp',
'compile_time_checks/serif/geometry/deformation.cpp',
'compile_time_checks/serif/eos/evaluation.cpp',
'compile_time_checks/serif/eos/models/traits.cpp',
'compile_time_checks/serif/discretization/forms/forms.cpp', 'compile_time_checks/serif/discretization/forms/forms.cpp',
'compile_time_checks/serif/discretization/forms/operands.cpp', 'compile_time_checks/serif/discretization/forms/operands.cpp',
'compile_time_checks/serif/discretization/blocks/fields.cpp', 'compile_time_checks/serif/discretization/blocks/fields.cpp',
'compile_time_checks/serif/discretization/quadrature/backend/mfem/mfem_resolver.cpp', 'compile_time_checks/serif/backend/mfem/discretization/quadrature/mfem_resolver.cpp',
) )
# We only make this a lib since we really dont need it to link to anything latter. This is just compiled # We only make this a lib since we really dont need it to link to anything latter. This is just compiled
@@ -58,3 +213,12 @@ if get_option('build_checks')
dependencies: [mfem_dep, magic_enum_dep], dependencies: [mfem_dep, magic_enum_dep],
) )
endif endif
if get_option('build_checks')
serif_core_checks = static_library(
'serif_core_checks',
'compile_time_checks/serif/backend_independent.cpp',
include_directories: include_dir,
dependencies: [nameof_dep, magic_enum_dep],
)
endif