Skip to content

Commit

Permalink
Fix step sizes for cvode in sc-systems (#1049)
Browse files Browse the repository at this point in the history
* Fix step sizes for cvode in sc-systems

* Make result files unique

* Fix segmentation fault in Values.cpp

* Fix temp path

* Remove previous results for same OMS version

* More clean up and copy FMU next to LUA file

Co-authored-by: AnHeuermann <[email protected]>
  • Loading branch information
lochel and AnHeuermann authored Jul 8, 2021
1 parent 4b0e0be commit c2da8d2
Show file tree
Hide file tree
Showing 55 changed files with 621 additions and 558 deletions.
6 changes: 3 additions & 3 deletions src/OMSimulatorLib/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,9 @@ namespace oms

double absoluteTolerance = 1e-4;
double relativeTolerance = 1e-4;
double minimumStepSize = 1e-4;
double maximumStepSize = 1e-1;
double initialStepSize = 1e-4;
double minimumStepSize = 1e-12;
double maximumStepSize = 1e-3;
double initialStepSize = 1e-6;

std::unordered_map<unsigned int /*result file var ID*/, unsigned int /*allVariables ID*/> resultFileMapping;
std::unordered_map<ComRef, bool> exportConnectors;
Expand Down
42 changes: 24 additions & 18 deletions src/OMSimulatorLib/SystemSC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "Model.h"
#include "ssd/Tags.h"

#include <sstream>

int oms::cvode_rhs(realtype t, N_Vector y, N_Vector ydot, void* user_data)
{
Expand Down Expand Up @@ -134,16 +135,23 @@ oms_status_enu_t oms::SystemSC::setSolverMethod(std::string solver)

oms_status_enu_t oms::SystemSC::exportToSSD_SimulationInformation(pugi::xml_node& node) const
{
std::ostringstream ssAbsoluteTolerance, ssRelativeTolerance, ssMinimumStepSize, ssMaximumStepSize, ssInitialStepSize;
ssAbsoluteTolerance << absoluteTolerance;
ssRelativeTolerance << relativeTolerance;
ssMinimumStepSize << minimumStepSize;
ssMaximumStepSize << maximumStepSize;
ssInitialStepSize << initialStepSize;

/* ssd:SimulationInformation should be added as vendor specific annotations from Version 1.0 */
pugi::xml_node node_simulation_information = node.append_child(oms::ssp::Version1_0::simulation_information);

pugi::xml_node node_solver = node_simulation_information.append_child(oms::ssp::Version1_0::VariableStepSolver);
node_solver.append_attribute("description") = getSolverName().c_str();
node_solver.append_attribute("absoluteTolerance") = std::to_string(absoluteTolerance).c_str();
node_solver.append_attribute("relativeTolerance") = std::to_string(relativeTolerance).c_str();
node_solver.append_attribute("minimumStepSize") = std::to_string(minimumStepSize).c_str();
node_solver.append_attribute("maximumStepSize") = std::to_string(maximumStepSize).c_str();
node_solver.append_attribute("initialStepSize") = std::to_string(initialStepSize).c_str();
node_solver.append_attribute("absoluteTolerance") = ssAbsoluteTolerance.str().c_str();
node_solver.append_attribute("relativeTolerance") = ssRelativeTolerance.str().c_str();
node_solver.append_attribute("minimumStepSize") = ssMinimumStepSize.str().c_str();
node_solver.append_attribute("maximumStepSize") = ssMaximumStepSize.str().c_str();
node_solver.append_attribute("initialStepSize") = ssInitialStepSize.str().c_str();

return oms_status_ok;
}
Expand Down Expand Up @@ -299,7 +307,7 @@ oms_status_enu_t oms::SystemSC::initialize()
if (!solverData.cvode.abstol) logError("SUNDIALS_ERROR: N_VNew_Serial() failed - returned NULL pointer");
for (int j=0, k=0; j < fmus.size(); ++j)
for (size_t i=0; i < nStates[j]; ++i, ++k)
NV_Ith_S(solverData.cvode.abstol, k) = 0.01*relativeTolerance*states_nominal[j][i];
NV_Ith_S(solverData.cvode.abstol, k) = 0.01*absoluteTolerance*states_nominal[j][i];
//N_VPrint_Serial(solverData.cvode.abstol);

// Call CVodeCreate to create the solver memory and specify the
Expand Down Expand Up @@ -335,28 +343,26 @@ oms_status_enu_t oms::SystemSC::initialize()
flag = CVodeSetLinearSolver(solverData.cvode.mem, solverData.cvode.linSol, solverData.cvode.J);
if (flag < 0) logError("SUNDIALS_ERROR: CVDense() failed with flag = " + std::to_string(flag));

const fmi2_real_t stopTime = 1.0;
double max_h = (stopTime - time) / 10.0;
logInfo("maximum step size for '" + std::string(getFullCref()) + "': " + std::to_string(max_h));
flag = CVodeSetMaxStep(solverData.cvode.mem, max_h);
logInfo("maximum step size for '" + std::string(getFullCref()) + "': " + std::to_string(maximumStepSize));
flag = CVodeSetMaxStep(solverData.cvode.mem, maximumStepSize);
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxStep() failed with flag = " + std::to_string(flag));

// further settings from cpp runtime
flag = CVodeSetInitStep(solverData.cvode.mem, 1e-6); // INITIAL STEPSIZE
flag = CVodeSetInitStep(solverData.cvode.mem, initialStepSize); // INITIAL STEPSIZE
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetInitStep() failed with flag = " + std::to_string(flag));
flag = CVodeSetMaxOrd(solverData.cvode.mem, 5); // MAXIMUM ORDER
flag = CVodeSetMaxOrd(solverData.cvode.mem, 5); // MAXIMUM ORDER
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxOrd() failed with flag = " + std::to_string(flag));
flag = CVodeSetMaxConvFails(solverData.cvode.mem, 100); // MAXIMUM NUMBER OF NONLINEAR CONVERGENCE FAILURES
flag = CVodeSetMaxConvFails(solverData.cvode.mem, 100); // MAXIMUM NUMBER OF NONLINEAR CONVERGENCE FAILURES
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxConvFails() failed with flag = " + std::to_string(flag));
flag = CVodeSetStabLimDet(solverData.cvode.mem, true); // STABILITY DETECTION
flag = CVodeSetStabLimDet(solverData.cvode.mem, true); // STABILITY DETECTION
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetStabLimDet() failed with flag = " + std::to_string(flag));
flag = CVodeSetMinStep(solverData.cvode.mem, 1e-12); // MINIMUM STEPSIZE
flag = CVodeSetMinStep(solverData.cvode.mem, minimumStepSize); // MINIMUM STEPSIZE
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMinStep() failed with flag = " + std::to_string(flag));
flag = CVodeSetMaxNonlinIters(solverData.cvode.mem, 5); // MAXIMUM NUMBER OF ITERATIONS
flag = CVodeSetMaxNonlinIters(solverData.cvode.mem, 5); // MAXIMUM NUMBER OF ITERATIONS
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxNonlinIters() failed with flag = " + std::to_string(flag));
flag = CVodeSetMaxErrTestFails(solverData.cvode.mem, 100); // MAXIMUM NUMBER OF ERROR TEST FAILURES
flag = CVodeSetMaxErrTestFails(solverData.cvode.mem, 100); // MAXIMUM NUMBER OF ERROR TEST FAILURES
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxErrTestFails() failed with flag = " + std::to_string(flag));
flag = CVodeSetMaxNumSteps(solverData.cvode.mem, 1000); // MAXIMUM NUMBER OF STEPS
flag = CVodeSetMaxNumSteps(solverData.cvode.mem, 1000); // MAXIMUM NUMBER OF STEPS
if (flag < 0) logError("SUNDIALS_ERROR: CVodeSetMaxNumSteps() failed with flag = " + std::to_string(flag));
}

Expand Down
96 changes: 72 additions & 24 deletions src/OMSimulatorLib/Values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,36 +871,60 @@ void oms::Values::importParameterMapping(const pugi::xml_node& parameterMapping)

oms_status_enu_t oms::Values::rename(const oms::ComRef& oldCref, const oms::ComRef& newCref)
{
for (const auto &r : realStartValues)
for (auto it=realStartValues.cbegin(); it != realStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(r.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
realStartValues[newCref + tail] = r.second; // update the newCref
realStartValues.erase(r.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
realStartValues[newCref + tail] = it->second; // update the newCref
it = realStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}

for (const auto &i : integerStartValues)
for (auto it=integerStartValues.cbegin(); it != integerStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(i.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
integerStartValues[newCref + tail] = i.second; // update the newCref
integerStartValues.erase(i.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
integerStartValues[newCref + tail] = it->second; // update the newCref
it = integerStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}

for (const auto &b : booleanStartValues)
for (auto it=booleanStartValues.cbegin(); it != booleanStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(b.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
booleanStartValues[newCref + tail] = b.second; // update the newCref
booleanStartValues.erase(b.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
booleanStartValues[newCref + tail] = it->second; // update the newCref
it = booleanStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}

Expand All @@ -913,36 +937,60 @@ oms_status_enu_t oms::Values::renameInResources(const oms::ComRef& oldCref, cons
{
for (auto &res : it.allresources)
{
for (const auto &r : res.second.realStartValues)
for (auto it=res.second.realStartValues.cbegin(); it != res.second.realStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(r.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
res.second.realStartValues[newCref + tail] = r.second; // update the newCref
res.second.realStartValues.erase(r.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
res.second.realStartValues[newCref + tail] = it->second; // update the newCref
it = res.second.realStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}

for (const auto &i : res.second.integerStartValues)
for (auto it=res.second.integerStartValues.cbegin(); it != res.second.integerStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(i.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
res.second.integerStartValues[newCref + tail] = i.second; // update the newCref
res.second.integerStartValues.erase(i.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
res.second.integerStartValues[newCref + tail] = it->second; // update the newCref
it = res.second.integerStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}

for (const auto &b : booleanStartValues)
for (auto it=res.second.booleanStartValues.cbegin(); it != res.second.booleanStartValues.cend() /* not hoisted */; /* no increment */)
{
ComRef tail(b.first);
// renaming the keys
ComRef tail(it->first);
ComRef front = tail.pop_front();
if (oldCref == front)
{
res.second.booleanStartValues[newCref + tail] = b.second; // update the newCref
res.second.booleanStartValues.erase(b.first); // delete the old cref
//logInfo("old: " + std::string(it->first));
//logInfo("new: " + std::string(newCref + tail));
//logInfo("value: " + std::to_string(it->second));
res.second.booleanStartValues[newCref + tail] = it->second; // update the newCref
it = res.second.booleanStartValues.erase(it); // delete the old cref
}
else
{
++it;
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions testsuite/OMSimulator/DualMassOscillator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ oms_addConnection("DualMassOscillator.root.system1.a1", "DualMassOscillator.root
-- simulation settings
oms_setResultFile("DualMassOscillator", "DualMassOscillator.mat", 100)
oms_setStopTime("DualMassOscillator", 10.0)
oms_setFixedStepSize("DualMassOscillator.root", 1e-3)
oms_setVariableStepSize("DualMassOscillator.root", 1e-12, 1e-12, 1e-3)

oms_instantiate("DualMassOscillator")
oms_setReal("DualMassOscillator.root.system1.x1_start", 0.0)
Expand All @@ -45,15 +45,15 @@ oms_terminate("DualMassOscillator")
oms_delete("DualMassOscillator")

-- Result:
-- info: maximum step size for 'DualMassOscillator.root': 0.100000
-- info: maximum step size for 'DualMassOscillator.root': 0.001000
-- info: Result file: DualMassOscillator.mat (bufferSize=100)
-- info: Initialization
-- info: system1.x1: 0.0
-- info: system2.x2: 0.5
-- info: Simulation
-- info: system1.x1: 0.050988622308801
-- info: system2.x2: 0.03162781956834
-- info: system1.x1: 0.051037644866066
-- info: system2.x2: 0.031639500249976
-- info: Final Statistics for 'DualMassOscillator.root':
-- NumSteps = 262 NumRhsEvals = 293 NumLinSolvSetups = 25
-- NumNonlinSolvIters = 292 NumNonlinSolvConvFails = 0 NumErrTestFails = 2
-- NumSteps = 10007 NumRhsEvals = 10008 NumLinSolvSetups = 507
-- NumNonlinSolvIters = 10007 NumNonlinSolvConvFails = 0 NumErrTestFails = 0
-- endResult
56 changes: 27 additions & 29 deletions testsuite/OMSimulator/Enumeration.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,47 @@
oms_setCommandLineOption("--suppressPath=true")
oms_setTempDirectory("./Enumeration_lua/")

oms_newModel("test")
oms_addSystem("test.root", oms_system_sc)
oms_addSubModel("test.root.A", "../resources/Int1.fmu")
oms_addSubModel("test.root.B", "../resources/Enum1.fmu")
oms_newModel("Enumeration")
oms_addSystem("Enumeration.root", oms_system_sc)
oms_addSubModel("Enumeration.root.A", "../resources/Int1.fmu")
oms_addSubModel("Enumeration.root.B", "../resources/Enum1.fmu")

-- integer to enumeration
oms_addConnection("test.root.A.y", "test.root.B.u")
oms_addConnection("Enumeration.root.A.y", "Enumeration.root.B.u")

oms_setResultFile("test", "test_res.mat")
-- oms_exportDependencyGraphs("Enumeration.root", "Enumeration.root_init.dot", "Enumeration.root_sim.dot", "Enumeration.root_continuous.dot")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" Enumeration.root_init.dot | dot -Tpdf -o Enumeration.root_init.pdf")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" Enumeration.root_sim.dot | dot -Tpdf -o Enumeration.root_sim.pdf")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" Enumeration.root_continuous.dot | dot -Tpdf -o Enumeration.root_continuous.pdf")

-- oms_exportDependencyGraphs("test.root", "test.root_init.dot", "test.root_sim.dot", "test.root_continuous.dot")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" test.root_init.dot | dot -Tpdf -o test.root_init.pdf")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" test.root_sim.dot | dot -Tpdf -o test.root_sim.pdf")
-- os.execute("gvpr -c \"N[$.degree==0]{delete(root, $)}\" test.root_continuous.dot | dot -Tpdf -o test.root_continuous.pdf")

oms_instantiate("test")
oms_instantiate("Enumeration")
print("info: Instantiation")
print("info: test.root.A.y : " .. oms_getInteger("test.root.A.y"))
print("info: test.root.B.u : " .. oms_getInteger("test.root.B.u"))
print("info: Enumeration.root.A.y : " .. oms_getInteger("Enumeration.root.A.y"))
print("info: Enumeration.root.B.u : " .. oms_getInteger("Enumeration.root.B.u"))

oms_initialize("test")
oms_initialize("Enumeration")
print("info: Initialization")
print("info: test.root.A.y : " .. oms_getInteger("test.root.A.y"))
print("info: test.root.B.u : " .. oms_getInteger("test.root.B.u"))
print("info: Enumeration.root.A.y : " .. oms_getInteger("Enumeration.root.A.y"))
print("info: Enumeration.root.B.u : " .. oms_getInteger("Enumeration.root.B.u"))

oms_simulate("test")
oms_simulate("Enumeration")
print("info: Simulation")
print("info: test.root.A.y : " .. oms_getInteger("test.root.A.y"))
print("info: test.root.B.u : " .. oms_getInteger("test.root.B.u"))
print("info: Enumeration.root.A.y : " .. oms_getInteger("Enumeration.root.A.y"))
print("info: Enumeration.root.B.u : " .. oms_getInteger("Enumeration.root.B.u"))

oms_terminate("test")
oms_delete("test")
oms_terminate("Enumeration")
oms_delete("Enumeration")

-- Result:
-- info: model doesn't contain any continuous state
-- info: Instantiation
-- info: test.root.A.y : 2
-- info: test.root.B.u : 0
-- info: Result file: test_res.mat (bufferSize=1)
-- info: Enumeration.root.A.y : 2
-- info: Enumeration.root.B.u : 0
-- info: Result file: Enumeration_res.mat (bufferSize=10)
-- info: Initialization
-- info: test.root.A.y : 2
-- info: test.root.B.u : 2
-- info: Enumeration.root.A.y : 2
-- info: Enumeration.root.B.u : 2
-- info: Simulation
-- info: test.root.A.y : 2
-- info: test.root.B.u : 2
-- info: Enumeration.root.A.y : 2
-- info: Enumeration.root.B.u : 2
-- endResult
Loading

0 comments on commit c2da8d2

Please sign in to comment.