Skip to content

Commit

Permalink
Improve error messages for missing initial unknowns (#1055)
Browse files Browse the repository at this point in the history
  • Loading branch information
lochel committed Jul 10, 2021
1 parent f015277 commit 9edae7e
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 44 deletions.
80 changes: 57 additions & 23 deletions src/OMSimulatorLib/ComponentFMUCS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <fmilib.h>
#include <JM/jm_portability.h>
#include <RegEx.h>
#include <unordered_set>

oms::ComponentFMUCS::ComponentFMUCS(const ComRef& cref, System* parentSystem, const std::string& fmuPath)
: oms::Component(cref, oms_component_fmu, parentSystem, fmuPath), fmuInfo(fmuPath)
Expand Down Expand Up @@ -146,43 +147,55 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms::
for (size_t i = 0; i < varListSize; ++i)
{
fmi2_import_variable_t* var = fmi2_import_get_variable(varList, i);
oms::Variable v(var, i + 1);
oms::Variable v(var);
if (v.getIndex() != i)
{
logError("Index mismatch " + std::to_string(v.getIndex()) + " != " + std::to_string(i) + ".\nPlease report the problem to the dev team: https://github.com/OpenModelica/OMSimulator/issues/new?assignees=&labels=&template=bug_report.md");
fmi2_import_free_variable_list(varList);
delete component;
return NULL;
}
component->allVariables.push_back(v);
if (v.isDer())
component->derivatives.push_back(v.getIndex());
component->exportVariables.push_back(true);
}
fmi2_import_free_variable_list(varList);

// mark states
varList = fmi2_import_get_derivatives_list(component->fmu);
varListSize = fmi2_import_get_variable_list_size(varList);
logDebug(std::to_string(varListSize) + " states");
for (size_t i = 0; i < varListSize; ++i)
if (varListSize != component->derivatives.size())
{
fmi2_import_variable_t* var = fmi2_import_get_variable(varList, i);
fmi2_import_real_variable_t* varReal = fmi2_import_get_variable_as_real(var);
fmi2_import_variable_t* varState = (fmi2_import_variable_t*)fmi2_import_get_real_variable_derivative_of(varReal);
if (varState)
std::unordered_set <unsigned int> setA_fmilib;
for (size_t i=0; i < varListSize; ++i)
{
// IMPORTANT: vr is not unique!!! Do lookup with proper index or name
size_t originalIndex = fmi2_import_get_variable_original_order(varState);
if (originalIndex < 0 || originalIndex >= component->allVariables.size())
{
logError("Couldn't find " + std::string(fmi2_import_get_variable_name(varState)));
fmi2_import_free_variable_list(varList);
delete component;
return NULL;
}
component->allVariables[originalIndex].markAsState();
fmi2_import_variable_t* var = fmi2_import_get_variable(varList, i);
size_t originalIndex = fmi2_import_get_variable_original_order(var);
setA_fmilib.insert(originalIndex);
}
else

std::string missing_der = "";
for (const auto& i : component->derivatives)
{
logError("Couldn't map " + std::string(fmi2_import_get_variable_name(var)) + " to the corresponding state variable");
fmi2_import_free_variable_list(varList);
delete component;
return NULL;
if (setA_fmilib.find(i) == setA_fmilib.end())
{
if (!missing_der.empty())
missing_der += ", ";
missing_der += std::to_string(i+1) + ": " + std::string(component->allVariables[i].getCref());
}
}

logWarning("[" + std::string(component->getCref()) + ": " + component->getPath() + "] The FMU lists " + std::to_string(varListSize) + " state derivatives but actually exposes " + std::to_string(component->derivatives.size()) + " state derivatives.\nThe following derivatives are missing: " + missing_der);
}
fmi2_import_free_variable_list(varList);
logDebug(std::to_string(varListSize) + " states");
for (const auto& i : component->derivatives)
{
// IMPORTANT: vr is not unique!!! Do lookup with proper index or name
size_t state_index = component->allVariables[i].getStateIndex();
component->allVariables[state_index].markAsState(i);
}

// create some special variable maps
for (auto const& v : component->allVariables)
Expand Down Expand Up @@ -368,7 +381,28 @@ oms_status_enu_t oms::ComponentFMUCS::initializeDependencyGraph_initialUnknowns(
if (N != N_fmilib)
{
if (!Flags::IgnoreInitialUnknowns())
logWarning("[" + std::string(getCref()) + ": " + getPath() + "] The FMU lists " + std::to_string(N_fmilib) + " initial unknowns but actually contains " + std::to_string(N) + " initial unknowns as per the variable definitions.");
{
std::unordered_set <unsigned int> setA_fmilib;
for (size_t i=0; i < N_fmilib; ++i)
{
fmi2_xml_variable_t* var_fmilib = fmi2_import_get_variable(initialUnknowns, i);
size_t originalIndex = fmi2_import_get_variable_original_order(var_fmilib);
setA_fmilib.insert(originalIndex);
}

std::string missing_unknowns = "";
for (auto &v : allVariables)
{
if (v.isInitialUnknown() && setA_fmilib.find(v.getIndex()) == setA_fmilib.end())
{
if (!missing_unknowns.empty())
missing_unknowns += ", ";
missing_unknowns += std::to_string(v.getIndex()+1) + ": " + std::string(v.getCref());
}
}

logWarning("[" + std::string(getCref()) + ": " + getPath() + "] The FMU lists " + std::to_string(N_fmilib) + " initial unknowns but actually exposes " + std::to_string(N) + " initial unknowns.\nThe following unknowns are missing: " + missing_unknowns);
}
badInitialUnknowns = true;
}

Expand Down
1 change: 1 addition & 0 deletions src/OMSimulatorLib/ComponentFMUCS.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ namespace oms
std::vector<Variable> parameters;
std::vector<Variable> calculatedParameters;
std::vector<bool> exportVariables;
std::vector<unsigned int> derivatives;

Values values; ///< start values defined before instantiating the FMU and external inputs defined after initialization

Expand Down
4 changes: 2 additions & 2 deletions src/OMSimulatorLib/ComponentFMUME.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::
for (size_t i = 0; i < varListSize; ++i)
{
fmi2_import_variable_t* var = fmi2_import_get_variable(varList, i);
oms::Variable v(var, i + 1);
oms::Variable v(var);
component->allVariables.push_back(v);
component->exportVariables.push_back(true);
}
Expand All @@ -174,7 +174,7 @@ oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::
delete component;
return NULL;
}
component->allVariables[originalIndex].markAsState();
component->allVariables[originalIndex].markAsState(fmi2_import_get_variable_original_order(var));
}
else
{
Expand Down
8 changes: 8 additions & 0 deletions src/OMSimulatorLib/DirectedGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,11 @@ void oms::DirectedGraph::calculateSortedConnections()

sortedConnectionsAreValid = true;
}

void oms::DirectedGraph::dumpNodes() const
{
std::string msg = "";
for (int i = 0; i < nodes.size(); ++i)
msg += std::to_string(i+1) + ": " + std::string(nodes[i].getName()) + "\n";
logInfo(msg);
}
2 changes: 2 additions & 0 deletions src/OMSimulatorLib/DirectedGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ namespace oms
const std::vector<Connector>& getNodes() const {return nodes;}
const oms_ssc_t& getEdges() const {return edges;}

void dumpNodes() const;

private:
std::deque< std::vector<int> > getSCCs();
void calculateSortedConnections();
Expand Down
7 changes: 5 additions & 2 deletions src/OMSimulatorLib/Variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
#include <JM/jm_portability.h>


oms::Variable::Variable(fmi2_import_variable_t* var, unsigned int index)
: is_state(false), is_der(false), cref(fmi2_import_get_variable_name(var)), index(index)
oms::Variable::Variable(fmi2_import_variable_t* var)
: der_index(0), state_index(0), is_state(false), is_der(false), cref(fmi2_import_get_variable_name(var)), index(fmi2_import_get_variable_original_order(var))
{
// extract the attributes
description = fmi2_import_get_variable_description(var) ? fmi2_import_get_variable_description(var) : "";
Expand Down Expand Up @@ -76,7 +76,10 @@ oms::Variable::Variable(fmi2_import_variable_t* var, unsigned int index)
fmi2_import_real_variable_t* varReal = fmi2_import_get_variable_as_real(var);
fmi2_import_variable_t* varState = (fmi2_import_variable_t*)fmi2_import_get_real_variable_derivative_of(varReal);
if (varState)
{
is_der = true;
state_index = fmi2_import_get_variable_original_order(varState);
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/OMSimulatorLib/Variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ namespace oms
class Variable
{
public:
Variable(fmi2_import_variable_t* var, unsigned int index);
Variable(fmi2_import_variable_t* var);
~Variable();

void markAsState() { is_state = true; }
void markAsState(size_t der_index) { is_state = true; this->der_index = der_index; }
unsigned int getStateIndex() const { return state_index; }

// causality attribute
bool isParameter() const { return fmi2_causality_enu_parameter == causality; }
Expand Down Expand Up @@ -98,7 +99,9 @@ namespace oms
bool is_state;
bool is_der;
oms_signal_type_enu_t type;
unsigned int index; ///< index origin = 1
unsigned int index; ///< index origin = 0
size_t state_index; ///< index origin = 0
size_t der_index; ///< index origin = 0

friend bool operator==(const oms::Variable& v1, const oms::Variable& v2);
friend bool operator!=(const oms::Variable& v1, const oms::Variable& v2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,13 @@ for _,var in ipairs(vars) do
end

-- Result:
-- warning: [cockpit: resources/0003_cockpit.fmu] The FMU lists 16 state derivatives but actually exposes 18 state derivatives.
-- The following derivatives are missing: 33: concealed15, 37: concealed19
-- warning: [cockpit: resources/0003_cockpit.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
-- warning: [consumer_A: resources/0004_consumer_A.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
-- warning: [consumer_B: resources/0005_consumer_B.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
-- warning: [eCS_Generic_Export: resources/0006_eCS_Generic_Export.fmu] The FMU lists 738 state derivatives but actually exposes 811 state derivatives.
-- The following derivatives are missing: 135: concealed19, 147: concealed31, 169: concealed53, 179: concealed63, 189: concealed73, 225: concealed109, 241: concealed125, 253: concealed137, 275: concealed159, 329: concealed213, 377: concealed261, 385: concealed269, 395: concealed279, 411: concealed295, 431: concealed315, 441: concealed325, 451: concealed335, 457: concealed341, 473: concealed357, 483: concealed367, 491: concealed375, 503: concealed387, 515: concealed399, 525: concealed409, 579: concealed463, 619: concealed503, 667: concealed551, 675: concealed559, 685: concealed569, 701: concealed585, 721: concealed605, 757: concealed641, 767: concealed651, 809: concealed693, 851: concealed735, 861: concealed745, 893: concealed777, 923: concealed807, 931: concealed815, 959: concealed843, 979: concealed863, 1021: concealed905, 1061: concealed945, 1069: concealed953, 1079: concealed963, 1095: concealed979, 1109: concealed993, 1123: concealed1007, 1137: concealed1021, 1151: concealed1035, 1165: concealed1049, 1175: concealed1059, 1185: concealed1069, 1227: concealed1111, 1261: concealed1145, 1269: concealed1153, 1281: concealed1165, 1291: concealed1175, 1311: concealed1195, 1323: concealed1207, 1333: concealed1217, 1373: concealed1257, 1403: concealed1287, 1415: concealed1299, 1441: concealed1325, 1457: concealed1341, 1487: concealed1371, 1507: concealed1391, 1549: concealed1433, 1559: concealed1443, 1569: concealed1453, 1579: concealed1463, 1589: concealed1473
-- warning: [eCS_Generic_Export: resources/0006_eCS_Generic_Export.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
-- warning: [eCS_SW: resources/0007_eCS_SW.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
-- warning: [engine: resources/0008_engine.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
Expand All @@ -187,6 +191,6 @@ end
-- info: AircraftVehicleDemonstrator.root.engine.pB.p is equal
-- info: AircraftVehicleDemonstrator.root.eCS_Generic_Export.Meas_PACK_TEMP is equal
-- info: AircraftVehicleDemonstrator.root.eCS_Generic_Export.Meas_PACK_PRESS is equal
-- info: 7 warnings
-- info: 9 warnings
-- info: 0 errors
-- endResult
6 changes: 5 additions & 1 deletion testsuite/AircraftVehicleDemonstrator/embrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,17 @@

## Result:
## warning: [ECS_SW: resources/0002_ECS_SW.fmu] The dependencies of the initial unknowns defined in the FMU are ignored because the flag --ignoreInitialUnknowns is active. Instead, all the initial unknowns will depend on all inputs.
## warning: [ECS_HW: resources/0001_ECS_HW.fmu] The FMU lists 57 state derivatives but actually exposes 60 state derivatives.
## The following derivatives are missing: 486: nodePumpToHEX.vp, 520: nodeHEXToPipeA.vp, 901: nodeAirOutlet.vp
## warning: [Consumer: resources/0003_Consumer.fmu] The FMU lists 19 state derivatives but actually exposes 21 state derivatives.
## The following derivatives are missing: 206: nodePipeAToConsumer.vp, 240: nodeConsumerToPipeB.vp
## info: Result file: sim_results.mat (bufferSize=1)
## info: Initialize:
## info: embrace.root.ECS_HW.coolinPackAir.looptype: 2
## info: embrace.root.ECS_HW.eCS.MaxCoolPower.k : 5.0
## info: embrace.root.ECS_HW.pipeC.L : 1.0
## info: embrace.root.ECS_HW.pipeB.L : 0.976535328081166
## info: embrace.root.ECS_HW.pipeA.L : 0.976535328081166
## info: 1 warnings
## info: 3 warnings
## info: 0 errors
## endResult
6 changes: 4 additions & 2 deletions testsuite/simulation/import_export.lua
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ printStatus(status, 0)
-- status: [correct] ok
-- status: [correct] ok
-- status: [correct] ok
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
-- The following unknowns are missing: 2: y
-- info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
-- status: [correct] ok
-- status: [correct] ok
Expand Down Expand Up @@ -361,7 +362,8 @@ printStatus(status, 0)
--
-- status: [correct] ok
-- status: [correct] ok
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
-- The following unknowns are missing: 2: y
-- info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
-- status: [correct] ok
-- status: [correct] ok
Expand Down
6 changes: 4 additions & 2 deletions testsuite/simulation/import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ def printStatus(status, expected):
## status: [correct] ok
## status: [correct] ok
## status: [correct] ok
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
## The following unknowns are missing: 2: y
## info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
## status: [correct] ok
## status: [correct] ok
Expand Down Expand Up @@ -360,7 +361,8 @@ def printStatus(status, expected):
##
## status: [correct] ok
## status: [correct] ok
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
## The following unknowns are missing: 2: y
## info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
## status: [correct] ok
## status: [correct] ok
Expand Down
6 changes: 3 additions & 3 deletions testsuite/simulation/renameSnapshot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ print(snapshot)
-- relativeTolerance="0.0001"
-- minimumStepSize="1e-12"
-- maximumStepSize="0.001"
-- initialStepSize="1e-6" />
-- initialStepSize="1e-06" />
-- </oms:SimulationInformation>
-- </oms:Annotations>
-- </ssc:Annotation>
Expand Down Expand Up @@ -557,7 +557,7 @@ print(snapshot)
-- <oms:SimulationInformation>
-- <oms:FixedStepMaster
-- description="oms-ma"
-- stepSize="0.001"
-- stepSize="0.001000"
-- absoluteTolerance="0.000100"
-- relativeTolerance="0.000100" />
-- </oms:SimulationInformation>
Expand Down Expand Up @@ -700,7 +700,7 @@ print(snapshot)
-- relativeTolerance="0.0001"
-- minimumStepSize="1e-12"
-- maximumStepSize="0.001"
-- initialStepSize="1e-6" />
-- initialStepSize="1e-06" />
-- </oms:SimulationInformation>
-- </oms:Annotations>
-- </ssc:Annotation>
Expand Down
2 changes: 1 addition & 1 deletion testsuite/simulation/renameValues1.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ print("info: renameValues1.root.add_3.u1 : " .. oms_getReal("renameVa
-- relativeTolerance="0.0001"
-- minimumStepSize="1e-12"
-- maximumStepSize="0.001"
-- initialStepSize="1e-6" />
-- initialStepSize="1e-06" />
-- </oms:SimulationInformation>
-- </oms:Annotations>
-- </ssc:Annotation>
Expand Down
6 changes: 4 additions & 2 deletions testsuite/simulation/simulation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ printStatus(status, 0)
-- Result:
-- status: [correct] ok
-- status: [correct] ok
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
-- warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
-- The following unknowns are missing: 2: y
-- info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
-- status: [correct] ok
-- warning: [B: resources/0002_B.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
-- warning: [B: resources/0002_B.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
-- The following unknowns are missing: 2: y
-- info: [B: resources/0002_B.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
-- status: [correct] ok
-- status: [correct] ok
Expand Down
6 changes: 4 additions & 2 deletions testsuite/simulation/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ def printStatus(status, expected):
## Result:
## status: [correct] ok
## status: [correct] ok
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
## warning: [A: resources/0001_A.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
## The following unknowns are missing: 2: y
## info: [A: resources/0001_A.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
## status: [correct] ok
## warning: [B: resources/0002_B.fmu] The FMU lists 0 initial unknowns but actually contains 1 initial unknowns as per the variable definitions.
## warning: [B: resources/0002_B.fmu] The FMU lists 0 initial unknowns but actually exposes 1 initial unknowns.
## The following unknowns are missing: 2: y
## info: [B: resources/0002_B.fmu] The FMU contains bad initial unknowns. This might cause problems, e.g. wrong simulation results.
## status: [correct] ok
## status: [correct] ok
Expand Down

0 comments on commit 9edae7e

Please sign in to comment.