Skip to content

Commit 421a637

Browse files
authored
Merge pull request #292 from awslabs/simlapointe/transient-adapt-dt
Adaptive time-stepping for transient solver using SUNDIALS
2 parents 7b4f4b2 + d3d18d7 commit 421a637

25 files changed

+1730
-1348
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ The format of this changelog is based on
4242
- Nonconformal adaptation is now supported for WavePort boundary conditions. This was
4343
achieved through a patch applied to MFEM to support `mfem::ParSubMesh` on external
4444
nonconformal surface subdomains.
45+
- Added adaptive time-stepping capability for transient simulations. The new ODE integrators
46+
rely on the SUNDIALS library and can be specified by setting the
47+
`config["Solver"]["Transient"]["Type"]` option to `"CVODE"` or `"ARKODE"`.
4548

4649
## [0.13.0] - 2024-05-20
4750

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ set(PALACE_WITH_GSLIB ON CACHE BOOL "Build with GSLIB library for high-order fie
3737
set(PALACE_WITH_STRUMPACK_BUTTERFLYPACK OFF CACHE BOOL "Build with ButterflyPACK support for STRUMPACK solver")
3838
set(PALACE_WITH_STRUMPACK_ZFP OFF CACHE BOOL "Build with ZFP support for STRUMPACK solver")
3939

40+
set(PALACE_WITH_SUNDIALS ON CACHE BOOL "Build with SUNDIALS differential/algebraic equations solver")
41+
4042
set(ANALYZE_SOURCES_CLANG_TIDY OFF CACHE BOOL "Run static analysis checks using clang-tidy")
4143
set(ANALYZE_SOURCES_CPPCHECK OFF CACHE BOOL "Run static analysis checks using cppcheck")
4244

cmake/ExternalGitTags.cmake

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,17 @@ set(EXTERN_EIGEN_URL
265265
"https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz" CACHE STRING
266266
"URL for external Eigen build"
267267
)
268+
269+
# SUNDIALS
270+
set(EXTERN_SUNDIALS_URL
271+
"https://github.com/LLNL/sundials.git" CACHE STRING
272+
"URL for external SUNDIALS build"
273+
)
274+
set(EXTERN_SUNDIALS_GIT_BRANCH
275+
"main" CACHE STRING
276+
"Git branch for external SUNDIALS build"
277+
)
278+
set(EXTERN_SUNDIALS_GIT_TAG
279+
"aaeab8d907c6b7dfca86041401fdc1448f35f826" CACHE STRING
280+
"Git tag for external SUNDIALS build"
281+
)

cmake/ExternalMFEM.cmake

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ if(PALACE_BUILD_EXTERNAL_DEPS)
1717
if(PALACE_WITH_SUPERLU)
1818
list(APPEND MFEM_DEPENDENCIES superlu_dist)
1919
endif()
20+
if(PALACE_WITH_SUNDIALS)
21+
list(APPEND MFEM_DEPENDENCIES sundials)
22+
endif()
2023
else()
2124
set(MFEM_DEPENDENCIES)
2225
endif()
@@ -87,6 +90,7 @@ list(APPEND MFEM_OPTIONS
8790
"-DMFEM_USE_LIBUNWIND=${PALACE_MFEM_WITH_LIBUNWIND}"
8891
"-DMFEM_USE_METIS_5=YES"
8992
"-DMFEM_USE_CEED=NO"
93+
"-DMFEM_USE_SUNDIALS=${PALACE_WITH_SUNDIALS}"
9094
)
9195
if(PALACE_WITH_STRUMPACK OR PALACE_WITH_MUMPS)
9296
list(APPEND MFEM_OPTIONS
@@ -297,6 +301,30 @@ Intel C++ compiler for MUMPS and STRUMPACK dependencies")
297301
"-DMUMPS_REQUIRED_LIBRARIES=${SCALAPACK_LIBRARIES}$<SEMICOLON>${STRUMPACK_MUMPS_GFORTRAN_LIBRARY}"
298302
)
299303
endif()
304+
305+
# Configure SUNDIALS
306+
if(PALACE_WITH_SUNDIALS)
307+
set(SUNDIALS_REQUIRED_PACKAGES "LAPACK" "BLAS" "MPI")
308+
if(PALACE_WITH_OPENMP)
309+
list(APPEND SUNDIALS_REQUIRED_PACKAGES "OpenMP")
310+
endif()
311+
if(PALACE_WITH_CUDA)
312+
list(APPEND SUNDIALS_REQUIRED_PACKAGES "CUDAToolkit")
313+
list(APPEND SUNDIALS_REQUIRED_LIBRARIES ${SUPERLU_STRUMPACK_CUDA_LIBRARIES})
314+
endif()
315+
string(REPLACE ";" "$<SEMICOLON>" SUNDIALS_REQUIRED_PACKAGES "${SUNDIALS_REQUIRED_PACKAGES}")
316+
string(REPLACE ";" "$<SEMICOLON>" SUNDIALS_REQUIRED_LIBRARIES "${SUNDIALS_REQUIRED_LIBRARIES}")
317+
list(APPEND MFEM_OPTIONS
318+
"-DSUNDIALS_DIR=${CMAKE_INSTALL_PREFIX}"
319+
"-DSUNDIALS_REQUIRED_PACKAGES=${SUNDIALS_REQUIRED_PACKAGES}"
320+
)
321+
if(NOT "${SUNDIALS_REQUIRED_LIBRARIES}" STREQUAL "")
322+
list(APPEND MFEM_OPTIONS
323+
"-DSUNDIALS_REQUIRED_LIBRARIES=${SUNDIALS_REQUIRED_LIBRARIES}"
324+
)
325+
endif()
326+
endif()
327+
300328
else()
301329
# Help find dependencies for the internal MFEM build
302330
# If we trust MFEM's Find<PACKAGE>.cmake module, we can just set <PACKAGE>_DIR and, if
@@ -309,6 +337,7 @@ else()
309337
"SuperLUDist"
310338
"STRUMPACK"
311339
"MUMPS"
340+
"SUNDIALS"
312341
)
313342
foreach(DEP IN LISTS PALACE_MFEM_DEPS)
314343
set(${DEP}_DIR "" CACHE STRING "Path to ${DEP} build or installation directory")

cmake/ExternalSUNDIALS.cmake

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
#
5+
# Build SUNDIALS
6+
#
7+
8+
# Force build order
9+
set(SUNDIALS_DEPENDENCIES)
10+
11+
set(SUNDIALS_OPTIONS ${PALACE_SUPERBUILD_DEFAULT_ARGS})
12+
list(APPEND SUNDIALS_OPTIONS
13+
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
14+
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
15+
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
16+
"-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
17+
"-DEXAMPLES_ENABLE_C=OFF"
18+
"-DEXAMPLES_ENABLE_CXX=OFF"
19+
"-DEXAMPLES_ENABLE_CUDA=OFF"
20+
"-DEXAMPLES_INSTALL=OFF"
21+
"-DENABLE_MPI=ON"
22+
)
23+
24+
if(PALACE_WITH_OPENMP)
25+
list(APPEND SUNDIALS_OPTIONS
26+
"-DENABLE_OPENMP=ON"
27+
)
28+
else()
29+
list(APPEND SUNDIALS_OPTIONS
30+
"-DENABLE_OPENMP=OFF"
31+
)
32+
endif()
33+
34+
# Configure LAPACK dependency
35+
if(NOT "${BLAS_LAPACK_LIBRARIES}" STREQUAL "")
36+
list(APPEND SUNDIALS_OPTIONS
37+
"-DENABLE_LAPACK=ON"
38+
"-DLAPACK_LIBRARIES=${BLAS_LAPACK_LIBRARIES}"
39+
"-DLAPACK_WORKS:BOOL=TRUE"
40+
)
41+
endif()
42+
43+
if(PALACE_WITH_CUDA)
44+
list(APPEND SUNDIALS_OPTIONS
45+
"-DCMAKE_CUDA_ARCHITECTURES=${CMAKE_CUDA_ARCHITECTURES}"
46+
"-DENABLE_CUDA=ON"
47+
)
48+
endif()
49+
50+
string(REPLACE ";" "; " SUNDIALS_OPTIONS_PRINT "${SUNDIALS_OPTIONS}")
51+
message(STATUS "SUNDIALS_OPTIONS: ${SUNDIALS_OPTIONS_PRINT}")
52+
53+
54+
include(ExternalProject)
55+
ExternalProject_Add(sundials
56+
DEPENDS ${SUNDIALS_DEPENDENCIES}
57+
GIT_REPOSITORY ${EXTERN_SUNDIALS_URL}
58+
GIT_TAG ${EXTERN_SUNDIALS_GIT_TAG}
59+
SOURCE_DIR ${CMAKE_BINARY_DIR}/extern/sundials
60+
BINARY_DIR ${CMAKE_BINARY_DIR}/extern/sundials-build
61+
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
62+
PREFIX ${CMAKE_BINARY_DIR}/extern/sundials-Cmake
63+
UPDATE_COMMAND ""
64+
CONFIGURE_COMMAND ${CMAKE_COMMAND} <SOURCE_DIR> "${SUNDIALS_OPTIONS}"
65+
TEST_COMMAND ""
66+
)

docs/src/config/solver.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ error tolerance.
208208
"ExcitationWidth": <float>,
209209
"MaxTime": <float>,
210210
"TimeStep": <float>,
211-
"SaveStep": <int>
211+
"SaveStep": <int>,
212+
"Order": <int>,
213+
"RelTol": <float>,
214+
"AbsTol": <float>
212215
}
213216
```
214217

@@ -218,14 +221,12 @@ with
218221
the second-order system of differential equations. The available options are:
219222

220223
- `"GeneralizedAlpha"` : The second-order implicit generalized-``\alpha`` method with
221-
``\rho_\inf = 1.0``. This scheme is unconditionally stable.
222-
- `"NewmarkBeta"` : The second-order implicit Newmark-``\beta`` method with
223-
``\beta = 1/4`` and ``\gamma = 1/2``. This scheme is unconditionally stable.
224-
- `"CentralDifference"` : The second-order explicit central difference method, obtained
225-
by setting ``\beta = 0`` and ``\gamma = 1/2`` in the Newmark-``\beta`` method. In this
226-
case, the maximum eigenvalue of the system operator is estimated at the start of the
227-
simulation and used to restrict the simulation time step to below the maximum stability
228-
time step.
224+
``\rho_{\inf} = 1.0``. This scheme is unconditionally stable.
225+
- `"ARKODE"` : SUNDIALS ARKode implicit Runge-Kutta scheme applied to the first-order
226+
ODE system for the electric field with adaptive time-stepping. This option is only available when *Palace* has been [built with SUNDIALS support](../install.md#Configuration-options).
227+
- `"CVODE"` : SUNDIALS CVODE implicit multistep method scheme applied to the first-order
228+
ODE system for the electric field with adaptive time-stepping. This option is only available when *Palace* has been [built with SUNDIALS support](../install.md#Configuration-options).
229+
- `"RungeKutta"` : Two stage, singly diagonal implicit Runge-Kutta (SDIRK) method. Second order and L-stable.
229230
- `"Default"` : Use the default `"GeneralizedAlpha"` time integration scheme.
230231

231232
`"Excitation" [None]` : Controls the time dependence of the source excitation. The
@@ -260,6 +261,16 @@ disk for [visualization with ParaView](../guide/postprocessing.md#Visualization)
260261
saved in the `paraview/` directory under the directory specified by
261262
[`config["Problem"]["Output"]`](problem.md#config%5B%22Problem%22%5D).
262263

264+
`"Order" [2]` : Order of the adaptive Runge-Kutta integrators or maximum order of the
265+
multistep method, must be within `[2,5]`. Should only be specified if `"Type"` is `"ARKODE"`
266+
or `"CVODE"`.
267+
268+
`"RelTol" [1e-4]` : Relative tolerance used in adaptive time-stepping schemes. Should only
269+
be specified if `"Type"` is `"ARKODE"` or `"CVODE"`.
270+
271+
`"AbsTol" [1e-9]` : Absolute tolerance used in adaptive time-stepping schemes. Should only
272+
be specified if `"Type"` is `"ARKODE"` or `"CVODE"`.
273+
263274
## `solver["Electrostatic"]`
264275

265276
```json

docs/src/install.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ Additional build options are (with default values in brackets):
133133
- `PALACE_WITH_LIBXSMM [ON]` : Build with LIBXSMM backend for libCEED
134134
- `PALACE_WITH_MAGMA [ON]` : Build with MAGMA backend for libCEED
135135
- `PALACE_WITH_GSLIB [ON]` : Build with GSLIB library for high-order field interpolation
136+
- `PALACE_WITH_SUNDIALS [ON]` : Build with SUNDIALS ODE solver library
136137

137138
The build step is invoked by running (for example with 4 `make` threads)
138139

@@ -207,6 +208,7 @@ source code for these dependencies is downloaded during the build process:
207208
`PALACE_WITH_ARPACK=ON`)
208209
- [LIBXSMM](https://github.com/libxsmm/libxsmm) (optional, when `PALACE_WITH_LIBXSMM=ON`)
209210
- [MAGMA](https://icl.utk.edu/magma/) (optional, when `PALACE_WITH_MAGMA=ON`)
211+
- [SUNDIALS](https://github.com/LLNL/sundials) (optional, when `PALACE_WITH_SUNDIALS=ON`)
210212
- [nlohmann/json](https://github.com/nlohmann/json)
211213
- [fmt](https://fmt.dev/latest)
212214
- [Eigen](https://eigen.tuxfamily.org)

docs/src/reference.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,19 @@ boundary condition which is written for a lumped resistive port boundary, for ex
9494
= \bm{U}^{inc} \,,\; \bm{x}\in\Gamma_{Z} \,.
9595
```
9696

97-
The second-order electric field formulation is chosen to take advantage of unconditionally
98-
stable implicit time-integration schemes without the expense of a coupled block system
99-
solve for ``\bm{E}(\bm{x},t)`` and ``\bm{B}(\bm{x},t)``. It offers the additional benefit
97+
The second-order electric field differential equation is transformed into a first-order
98+
ODE system which is solved along with the equation for the magnetic flux density
99+
100+
```math
101+
\left(\begin{matrix} \varepsilon_r & 0 & 0 \\ 0 & I & 0 \\ 0 & 0 & I\end{matrix}\right)
102+
\left(\begin{matrix} \ddot{\bm{E}} \\ \dot{\bm{E}} \\ \dot{\bm{B}}\end{matrix} \right)
103+
= \left(\begin{matrix} -\sigma & -\nabla\times\mu_r^{-1}\nabla\times & 0\\ I & 0 & 0 \\ 0 & -\nabla\times & 0\end{matrix}\right)
104+
\left(\begin{matrix}\dot{\bm{E}}\\ \bm{E} \\ \bm{B} \end{matrix}\right) \,.
105+
```
106+
107+
The first-order ODE system formulation is chosen to take advantage of implicit adaptive
108+
time-stepping integration schemes. The ``3 \times 3`` system can be block-eliminated to
109+
avoid an expensive coupled block system solve. It offers the additional benefit
100110
of sharing many similarities in the spatial discretization as the frequency domain
101111
formulation outlined above.
102112

extern/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@ include(ExternalFmt)
7272
# Add Eigen
7373
message(STATUS "===================== Configuring Eigen dependency =====================")
7474
include(ExternalEigen)
75+
76+
# Add SUNDIALS
77+
if(PALACE_WITH_SUNDIALS)
78+
message(STATUS "===================== Configuring SUNDIALS dependency =====================")
79+
include(ExternalSUNDIALS)
80+
endif()

palace/drivers/transientsolver.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,8 @@ TransientSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
3030
std::function<double(double)> dJdt_coef = GetTimeExcitation(true);
3131
SpaceOperator space_op(iodata, mesh);
3232
TimeOperator time_op(iodata, space_op, dJdt_coef);
33+
3334
double delta_t = iodata.solver.transient.delta_t;
34-
if (time_op.isExplicit())
35-
{
36-
// Stability limited time step.
37-
const double dt_max = time_op.GetMaxTimeStep();
38-
const double dts_max = iodata.DimensionalizeValue(IoData::ValueType::TIME, dt_max);
39-
Mpi::Print(" Maximum stable time step: {:.6e} ns\n", dts_max);
40-
delta_t = std::min(delta_t, 0.95 * dt_max);
41-
}
4235
int n_step = GetNumSteps(0.0, iodata.solver.transient.max_t, delta_t);
4336
SaveMetadata(space_op.GetNDSpaces());
4437

@@ -138,6 +131,7 @@ TransientSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
138131
step++;
139132
}
140133
BlockTimer bt1(Timer::POSTPRO);
134+
time_op.PrintStats();
141135
SaveMetadata(time_op.GetLinearSolver());
142136
return {indicator, space_op.GlobalTrueVSize()};
143137
}

0 commit comments

Comments
 (0)