See publication (in german): Nicolai, A.: Co-Simulations-Masteralgorithmen - Analyse und Details der Implementierung am Beispiel des Masterprogramms MASTERSIM, http://nbn-resolving.de/urn:nbn:de:bsz:14-qucosa2-319735
Basically, consistent initial conditions can be obtained by repeatedly setting inputs and retrieving outputs of slaves without calling doStep()
in between. Hence, the states of the slaves do not have to be stored and retrieved, so initial condition iteration is also possible with FMI v1.
The master algorithm implementations can be recycled, when the calls to the following functions
doStep()
currentState()
(only FMI2)setState()
(only FMI2)are disabled by a flag.
Unconnected inputs need to be set to their start-values only once. Also, parameters need to be set by the master only once before the initial condition iteration.
For all iterative algorithms, convergence is found when:
Weighted root mean square norm (WRMS-norm) is computed as follows:
1 2 3 4 5 6 7 8 9 10 | double norm = 0; for (unsigned i=0; i<m_realytNextIter.size(); ++i) { double diff = m_realytNextIter[i] - m_realytNext[i]; double absValue = std::fabs(m_realytNextIter[i]); double weight = absValue*m_project.m_relTol + m_project.m_absTol; diff /= weight; norm += diff*diff; } norm = std::sqrt(norm); |
There is a publication (in german) that shows how the different choices of the master algorithms will affect result and evaluation counts:
Nicolai, A.; 2018, Co-Simulations-Masteralgorithmen - Analyse und Details der Implementierung am Beispiel des Masterprogramms MASTERSIM, Qucosa, doi-link (added soon, once available)
The paper can be downloaded from the MASTERSIM Webpage -> documentation section.
See [wiki:MasterSimProjectFileFormat] for options to configure the following algorithmic combinations.
Limitations on error and stability. Optionally supports parallelization (see performance tweaks discussion).
Limitations on error and stability. A bit better than Gauss-Jacobi.
Fixing the time step allows performance comparison with other algorithms.
Stable due to time step reduction, error control possible.
Stable due to time step reduction, error control possible. Convergence rate and success improved over Gauss-Seidel.
Depending on the selected algorithmic options, FMU must have certain capabilities:
All algorithms start with the following conditions:
When iteration is enabled and step adjustment is enabled, the FMU slave states are expected to be stored already, otherwise they will be stored at the begin of an iterating algorithm.
Note: MasterSim only implements the non-iterative Gauss-Jacobi algorithm because and two Gauss-Jacobi-Iterations correspond two non-iterative steps with half the step size - and the latter version will be even more accurate and stable. Therefore Gauss-Jacobi is implemented always without iteration, error checking and time step adjustment.
loop all cycles: loop all slaves in cycle: set inputs for slave using variables from time level t advance slave in time (doStep() and caching of outputs) sync cached outputs with variables vector for time level t+1 copy variables from time level t+1 to variables vector of time level t
Whether iterative or non-iterative version is used, is determined by iteration limit (==1, no iteration).
Solves is the fixed-point iteration
x* = S(x)
where S(x)
is the result of the evaluation of all slaves and mapping of outputs to inputs.
copy variables from time level t to variables vector of time level t+1 loop all cycles: loop iteration < maxIterations: if iterating: copy variables from time level t+1 to backup vector (for convergence check) if iteration > 1: restoreSlaveStates() loop all slaves in cycle: set inputs for slave using variables from time level t+1 (partially updated from previous slaves) advance slave in time (doStep() and caching of outputs) sync cached outputs with variables vector for time level t+1 if iterating and numSlaves > 1: doConvergenceTest() if success: break copy variables from time level t+1 to variables vector of time level t
Specific features of Gauss-Seidel implementation:
The Newton algorithm is always iterative. The algorithm employs a modified Newton method, where the Jacobian is updated only once at the begin of each step.
The root finding problem stems from the re-arranged fixed-point iteration:
0 = x - S(x) = G(x)
with the Jacobian
dG/dx = I - dS/dx
in the algorithm, each cycle is treated individually. Cycles with a single slave are not iterated. Cycles with no coupling variables (that means, not really a cycle) are not treated as Newton.
Variable communication steps are implemented only for FMUs v2 with rollback capabilities.
Principle algorithm:
loop until t > tEnd: loop until converged and error test has passed: take step if not converged: reduce step and try again do error test if error too large: reduce step and try again estimate step size for next step
The error test is done with the step-doubling technique. First a step is computed (it has converged in case of iterative algorithm). The same step is then calculated again but with two steps of halved size, yielding a solution of higher order.
The difference between method orders is used to estimate the local truncation error. This is done in analogy to Backward Euler which has method order 1. Suppose you have solution yh as the solution with the original step and yh2 as solution with halved steps, the error is estimated by:
error = 2 || yh - yh2 ||
Since we deal with vectors, a suitable norm (WRMS norm) is used to compute the scalars yh and yh2.
The error test is optional and done right after a solution has converged. In this case the new solution (for time point t + stepsize) is stored in temporary vectors xxxNext.
The error test algorithm copies this solution to vectors xxxFirst. It then resets the slaves to time point t and computes two steps of size stepsize/2. If any of the steps fails to converge during this attempt, the step size is not adjusted but the error test is marked as failed (when the long step converges, the smaller ones must converge as well, unless something significant has happened in the middle of the long step).
When taking two steps of size h2 = h/2 rounding errors can lead to states ending up at time 2*h2 != h
. Since at end of error test slaves are positioned at time t + 2*h2
we recompute the actual long step size h = 2*h2
and store that as long step size.
For the error test we have to take 3 communication steps instead of 1 for a single interval. This extra work can also be used to generate a better estimate for the solution by combining the solution of the single step with the dual step solution (of higher order). With the Richardson extrapolation both solution are combined to create a better estimate for the result.