Serialization/De-serialization of CVODE and associated linear solvers
This feature also termed "hot-restart", because it allows repeating a time integration interval without loosing integration history. Essentially, the state of the CVODE integrator and its linear solvers is stored and can be restored at a later point.
This feature is essential for numerical solvers that include CVODE as integrator and want to implement roll-back functionality defined by the Functional Mockup Interface standard version 2.
Following assumptions/restrictions:
- serialization is done into continuous memory array
- deserialization is done from the same memory array, but the target CVODE and linear solver memory data structure must be correctly resized beforehand
- everything is restored, including integrator statistics (i.e. the memory occupied by the CVODE data structure will have exactly the same content, though the actual memory layout of data structures allocated on the heap may have changed.
Patched version
You can download the patched version of SUNDIALS 2.7.0 library: sundials_2.7.0_patched.7z
This version of SUNDIALS contains the serialization feature (described below), and also the runtime metrics code portion, described in Manual Instrumentation - Runtime metrics for CVODE.
Usage
You need to include the file
#include <cvode/cvode_serialization.h>
Get the serialization size
First, obtain the size of the memory block to store the serialized data:
unsigned int cvodeMemSize = CVodeSerializationSize(cvode_mem);
Mind, this will only give you the size needed to store the cvode memory record itself, not the linear solvers. So, usually you will need to store the memory size of the linear solvers and own preconditions as well:
// get size of iterative solver unsigned int spilsMemSize = CVSpilsSerializationSize(cvode_mem);
Next, reserve memory (usually of size cvodeMemSize + spilsMemSize).
Serialize CVODE data
Then, serialize the memory:
void * dataPtr = ...; // shall point to sufficiently large memory array CVodeSerialize(cvode_mem, &dataPtr); // serialize cvode_mem, afterwards dataPtr points to first byte after the cvode_mem block CVSpilsSerialize(cvode_mem, &dataPtr); // serialize linear memory array, afterwards dataPtr points to first byte after the stored memory block // you may add your custom data structures (jacobians, preconditioners, ...) to the memory pointer to by dataPtr
Deserialize the CVODE memory
Mind: the cvode memory record and the linear solver memory record must be correctly resized. When serialization and deserialization is used in the same program without reinit, this is usually guaranteed. Otherwise (i.e. when starting the solver executable anew), make sure that all relevant sizes are the same as when used during the serialization.
void * dataPtr = ...; // points to the memory array containing the serialized data CVodeDeserialize(cvode_mem, &dataPtr); // deserialize cvode_mem, moved dataPtr forward in memory array CVSpilsDeserialize(cvode_mem, &dataPtr); // deserialize linear memory array, afterwards dataPtr points to first byte after the stored memory block // you may now retrieve/restore your custom data structures (jacobians, preconditioners, ...) from the memory pointed to by dataPtr
If you have questions about the implementation, or if a port to newer SUNDIALS version is needed, please post a request in the SUNDIALS mailing list.