To solve a SPARK problem, you need to perform the following steps:
- Retrieve the pointer to the SPARK::TProblem instance that was previously loaded;
- Initialize the problem with the previously constructed SPARK::TRuntimeControls object;
- Load the previously contructed SPARK::TPreferenceSettings object;
- Simulate the problem from
InitialTime
to FinalTime
(as specified in the *.run file); and
- Terminate the simulation run of the problem.
The address of the SPARK::TProblem instance of a previously loaded problem (See Load a SPARK problem at runtime) is returned by the the API function SPARK::Problem::Get() by passing the unique name of the problem instance as const char*
.
If no problem instance by this name can be found in the instance repository, then the function returns a NULL pointer. This will happen:
- Warning:
- Never explicitly delete the SPARK::TProblem object returned by SPARK::Problem::Get() with the C++ operator delete because this might produce memory violation problems and memory leaks. The garbage collection is performed internally upon calling the API function SPARK::End(). This is the only way that you can avoid memory leaks by ensuring that all memory allocated from the heap at runtime for this simulation session will be properly freed.
You initialize the problem with a previously constructed SPARK::TRuntimeControls object (See Set up the runtime controls) by invoking the SPARK::TProblem::Initialize() method:
This method prepares the simulator for the problem under study:
- it allocates various handlers for the specified runtime controls,
- it loads the initial values for all variables, and
- it fires the atomic class constructors (if any) to allocate the memory needed by each inverse and object.
Before re-initializing the same SPARK::TProblem object with new runtime controls, i.e., a new SPARK::TRuntimeControls object, you first have to call the SPARK::TProblem::Terminate() method to release the memory allocated by the previous call to SPARK::TProblem::Initialize().
- Note:
- The SPARK::TRuntimeControls object is copied internally in the SPARK::TProblem object, so that it can be destroyed (or go out of scope) as soon as the SPARK::TProblem::Initialize() method returns.
The preference settings described by an instance of the class SPARK::TPreferenceSettings (See Set up the preference settings) are loaded in the problem with the SPARK::TProblem::LoadPreferenceSettings() method:
It should be noted that you can call the SPARK::TProblem::LoadPreferenceSettings() method without having to re-initialize the SPARK::TProblem object. This feature can be useful to recover from non-converging simulations by loading a new set of "more robust" solution settings through a call to SPARK::TProblem::LoadPreferenceSettings() in the catch statement.
- Warning:
- The SPARK::TPreferenceSettings object is only partially copied internally in the SPARK::TProblem object. In particular, the global settings stored in the SPARK::TPreferenceSettings object through an instance of the class SPARK::TGlobalSettings might be accessed during the course of the simulation. Therefore, it is required that the SPARK::TPreferenceSettings object exists in memory until the simulation is over.
Starting from InitialTime
, the solution is computed by advancing the global time until reaching FinalTime
as specified in the SPARK::TRuntimeControls object. At each time step, the values for the known variables are read from the input files, and the computed values are reported to the output files.
It is good practice to test the value returned by the SPARK::TProblem::Simulate() method against SPARK::TProblem::SimulatorState_OK to detect possible runtime errors.
In the following code snippet, we exit the simulator if the simulation encountered any problem.
if ( P->Simulate() != SPARK::TProblem::SimulatorState_OK ) {
SPARK::ExitWithError(
SPARK::ExitCode_ERROR_NUMERICAL,
__FILE__,
"Abort simulation.",
P
);
}
After a call to the SPARK::TProblem::Simulate() method, you should invoke the SPARK::TProblem::Terminate() method to:
- Call the atomic class destructors (if any) to free the memory allocated in the constructors;
- Write the simulation statistics to the global run log file (if such diagnostic is required);
- Free the control-specific memory allocated at runtime following the call to SPARK::TProblem::Initialize(); and
- Reset the internal counters and handlers to allow for another run with a new set of runtime controls (i.e., a new instance of the class SPARK::TRuntimeControls).