A from-scratch C++ matrix-free finite-element library, built mirroring libCEED's architecture (and, through it, Ratel).
Everything is hand-written here rather than pulled in as a libCEED dependency. The core library has no dependencies: no MPI, no PETSc, no CUDA. The CUDA part is optional and off by default.
Basis (include/basis.hpp, src/basis.cpp)
- 1D Gauss-Legendre and Gauss-Lobatto quadrature
- Lagrange interpolation/derivative matrices via Fornberg's algorithm
TensorBasis: tensor-product H1 Lagrange basis fordim= 1, 2, 3, arbitrary node/quadrature order,num_compfields,GaussorGaussLobattoquadrature (libCEED'sCeedBasisCreateTensorH1Lagrange)
Tensor contraction (include/tensor-contract.hpp, src/tensor-contract.cpp)
tensor_contract_apply: the single batched-contraction primitive (libCEED'sCeedTensorContractApply)tensor_basis_apply_interp/tensor_basis_apply_grad: sum-factorized evaluation at quadrature points, batched overnum_compfields andnum_elemelements, withContractMode::Transpose(the adjoint)tensor_basis_apply_weight: tensor-product quadrature weightstensor_basis_apply: dispatches byEvalMode(Interp,Grad,Weight; libCEED'sCeedBasisApply)
Element restriction (include/elem-restriction.hpp, src/elem-restriction.cpp)
elem_restriction_create(offsets, validated) andelem_restriction_create_strided(for quadrature-point data such as qdata; backend strides or user strides)elem_restriction_apply: gather (L-vector to E-vector) and its adjoint, scatter-add. The E-vector layout matches the basis apply functions, so the output feeds straight into themelem_restriction_get_multiplicity
QFunction (include/qfunction.hpp, src/qfunction.cpp)
- The pointwise kernel: a plain function pointer called on a batch of
Qpoints, with named input/output fields (size andEvalMode), field layout[size][Q], and an optional trivially copyable context (libCEED'sCeedQFunction) include/qfunctions/mass.hpp:build_mass(qdata = det(J) * w, dim 1-3) andapply_mass(v = qdata * u)
Operator (include/operator.hpp, src/operator.cpp)
- Ties each QFunction field to a restriction, a basis and a vector (active,
passive or none), with the consistency checks of libCEED's
CeedOperatorSetField operator_apply: restrict, basis evaluation, QFunction, basis transpose, restrict transpose (scatter-add), batched over all elements (libCEED'sCeedOperatorApply)
CUDA infrastructure (include/cuda/, src/cuda/; optional, -DFE_DEMO_CUDA=ON)
CUDA_CHECK/CUDA_CHECK_LAUNCH: turn CUDA errors into exceptions with file and lineDeviceArray<T>: move-only owner of a GPU allocation, with explicit host/device copiesdevice_info: device limits (shared memory, threads per block, SMs) and free memory
include/eval-mode.hpp holds EvalMode (None, Interp, Grad, Weight) and
include/transpose-mode.hpp holds ContractMode (NoTranspose / Transpose;
libCEED's CeedTransposeMode).
- C++17 compiler
- CMake >= 3.20
Catch2 is fetched automatically via CMake's FetchContent.
cmake -S . -B build
cmake --build build -j
./build/fe_demo_testCUDA (optional; needs the CUDA toolkit and a GPU, built for the GPU in the
machine unless -DCMAKE_CUDA_ARCHITECTURES=... is given):
cmake -S . -B build-cuda -DFE_DEMO_CUDA=ON
cmake --build build-cuda -j
./build-cuda/fe_demo_cuda_testRun a subset of the tests by tag or name:
./build/fe_demo_test "[operator]"
./build/fe_demo_test "[qfunction]"
./build/fe_demo_test "[elem-restriction]"
./build/fe_demo_test "[manufactured]"
./build/fe_demo_test --list-tests