From 755e69e324dca571d9c3dcdca7bf15a40a5ca3d3 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 09:38:16 +0200 Subject: [PATCH 1/9] Record initial values --- fmusim-gui/MainWindow.cpp | 416 +++++++++++++++++++++++--------- fmusim-gui/SimulationThread.cpp | 3 + fmusim/FMI3CSSimulation.c | 16 +- fmusim/FMI3CSSimulation.h | 6 +- fmusim/FMIRecorder.c | 4 + fmusim/FMISimulation.c | 3 +- fmusim/FMISimulation.h | 1 + fmusim/fmusim.c | 23 +- 8 files changed, 348 insertions(+), 124 deletions(-) diff --git a/fmusim-gui/MainWindow.cpp b/fmusim-gui/MainWindow.cpp index f9e8860c..c5143968 100644 --- a/fmusim-gui/MainWindow.cpp +++ b/fmusim-gui/MainWindow.cpp @@ -635,14 +635,128 @@ void MainWindow::openFileInDefaultApplication(const QModelIndex &index) { QDesktopServices::openUrl(QUrl(path)); } +static QString getData(FMIRecorder* recorder, const FMIModelVariable* variable) { + + const FMIVariableType type = variable->type; + + bool found = false; + + size_t index; + + for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { + if (recorder->variableInfos[type]->variables[index] == variable) { + found = true; + break; + } + } + + if (!found) { + return ""; + } + + QString y; + + for (size_t j = 0; j < recorder->nRows; j++) { + + Row* row = recorder->rows[j]; + + if (j > 0) { + y += ", "; + } + + switch (type) { + case FMIFloat32Type: + case FMIDiscreteFloat32Type: + { + const float* values = (float*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIFloat64Type: + case FMIDiscreteFloat64Type: + { + const double* values = (double*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt8Type: + { + const int8_t* values = (int8_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt8Type: + { + const uint8_t* values = (uint8_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt16Type: + { + const int16_t* values = (int16_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt16Type: + { + const uint16_t* values = (uint16_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt32Type: + { + const int32_t* values = (int32_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt32Type: + { + const uint32_t* values = (uint32_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt64Type: + { + const int64_t* values = (int64_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt64Type: + { + const uint64_t* values = (uint64_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIBooleanType: + { + const bool* values = (bool*)row->values[type]; + y += QString::number(values[index]); + } + break; + default: + y += "0"; + break; + } + + } + + return y; +} + void MainWindow::updatePlot() { if (!simulationThread || !simulationThread->settings->recorder) { return; } + FMIRecorder* initialRecorder = simulationThread->settings->initialRecorder; FMIRecorder* recorder = simulationThread->settings->recorder; + // for (const FMIModelVariable* variable : plotVariables) { + // QString y = getData(recorder, variable); + // qDebug() << y; + // } + QString data; data += "var time = ["; @@ -660,123 +774,42 @@ void MainWindow::updatePlot() { data += "];\n"; - data += "var data = [\n"; - - size_t k = 0; + data += "var time2 = ["; - for (size_t i = 0; i < recorder->nVariables; i++) { + data += QString::number(recorder->rows[0]->time); - const FMIModelVariable* variable = recorder->variables[i]; + data += ", "; - const FMIVariableType type = variable->type; + data += QString::number(recorder->rows[recorder->nRows - 1]->time); - if (!plotVariables.contains(variable)) { - continue; - } - - QString y; - - for (size_t j = 0; j < recorder->nRows; j++) { - - Row* row = recorder->rows[j]; - - if (j > 0) { - y += ", "; - } + data += "];\n"; - size_t index; + data += "var data = [\n"; - for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { - if (recorder->variableInfos[type]->variables[index] == variable) { - break; - } - } + size_t k = 0; - switch (type) { - case FMIFloat32Type: - case FMIDiscreteFloat32Type: - { - const float* values = (float*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIFloat64Type: - case FMIDiscreteFloat64Type: - { - const double* values = (double*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt8Type: - { - const int8_t* values = (int8_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt8Type: - { - const uint8_t* values = (uint8_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt16Type: - { - const int16_t* values = (int16_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt16Type: - { - const uint16_t* values = (uint16_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt32Type: - { - const int32_t* values = (int32_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt32Type: - { - const uint32_t* values = (uint32_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt64Type: - { - const int64_t* values = (int64_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt64Type: - { - const uint64_t* values = (uint64_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIBooleanType: - { - const bool* values = (bool*)row->values[type]; - y += QString::number(values[index]); - } - break; - default: - y += "0"; - break; - } - } + for (const FMIModelVariable* variable : plotVariables) { if (k > 0) { data += ", "; } - - data += "{x: time, y: [" + y + "], type: 'scatter', name: '', line: {color: '#248BD2', width: 1.5"; + QString y = getData(recorder, variable); + + if (y.isEmpty()) { + y = getData(initialRecorder, variable); + y = y + ", " + y; + data += "{x: time2, y: [" + y + "], "; + } else { + // data += "{x: [0, 2], y: [4, 5], "; + data += "{x: time, y: [" + y + "], "; + } + + data += "type: 'scatter', name: '', line: {color: '#248BD2', width: 1.5"; if (variable->variability == FMIContinuous) { data += "}"; - } else if (type == FMIBooleanType) { + } else if (variable->type == FMIBooleanType) { data += ", shape: 'hv'}, fill: 'tozeroy'"; } else { data += ", shape: 'hv'}"; @@ -794,17 +827,148 @@ void MainWindow::updatePlot() { data += "];\n"; - QString axes; + // qDebug().noquote() << data; + + // data += "var data = [\n"; + + // size_t k = 0; + + // for (size_t i = 0; i < recorder->nVariables; i++) { + + // const FMIModelVariable* variable = recorder->variables[i]; + + // const FMIVariableType type = variable->type; + + // if (!plotVariables.contains(variable)) { + // continue; + // } + + // QString y; + + // size_t index; + + // for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { + // if (recorder->variableInfos[type]->variables[index] == variable) { + // break; + // } + // } + + // for (size_t j = 0; j < recorder->nRows; j++) { + + // Row* row = recorder->rows[j]; + + // if (j > 0) { + // y += ", "; + // } + + // switch (type) { + // case FMIFloat32Type: + // case FMIDiscreteFloat32Type: + // { + // const float* values = (float*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIFloat64Type: + // case FMIDiscreteFloat64Type: + // { + // const double* values = (double*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIInt8Type: + // { + // const int8_t* values = (int8_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIUInt8Type: + // { + // const uint8_t* values = (uint8_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIInt16Type: + // { + // const int16_t* values = (int16_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIUInt16Type: + // { + // const uint16_t* values = (uint16_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIInt32Type: + // { + // const int32_t* values = (int32_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIUInt32Type: + // { + // const uint32_t* values = (uint32_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIInt64Type: + // { + // const int64_t* values = (int64_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIUInt64Type: + // { + // const uint64_t* values = (uint64_t*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // case FMIBooleanType: + // { + // const bool* values = (bool*)row->values[type]; + // y += QString::number(values[index]); + // } + // break; + // default: + // y += "0"; + // break; + // } + // } + + // if (k > 0) { + // data += ", "; + // } + + // data += "{x: time, y: [" + y + "], type: 'scatter', name: '', line: {color: '#248BD2', width: 1.5"; - k = 0; - for (size_t i = 0; i < recorder->nVariables; i++) { + // if (variable->variability == FMIContinuous) { + // data += "}"; + // } else if (type == FMIBooleanType) { + // data += ", shape: 'hv'}, fill: 'tozeroy'"; + // } else { + // data += ", shape: 'hv'}"; + // } - const FMIModelVariable* variable = recorder->variables[i]; + // if (k > 0) { + // const QString plotIndex = QString::number(k + 1); + // data += ", xaxis: 'x" + plotIndex + "', yaxis: 'y" + plotIndex + "'"; + // } - if (!plotVariables.contains(variable)) { - continue; - } + // data += "}\n"; + + // k++; + // } + + // data += "];\n"; + + + QString axes; + + k = 0; + + for (const FMIModelVariable* variable : plotVariables) { const QString name = QString::fromUtf8(variable->name); @@ -826,6 +990,38 @@ void MainWindow::updatePlot() { k++; } + // QString axes; + + // k = 0; + + // for (size_t i = 0; i < recorder->nVariables; i++) { + + // const FMIModelVariable* variable = recorder->variables[i]; + + // if (!plotVariables.contains(variable)) { + // continue; + // } + + // const QString name = QString::fromUtf8(variable->name); + + // const QString colors = colorScheme == Qt::ColorScheme::Dark ? "color: '#fff', zerolinecolor: '#666'" : "color: '#000', zerolinecolor: '#000'"; + + // const double segment = 1.0 / plotVariables.size(); + // const double margin = 0.02; + + // const QString domain = "[" + QString::number(k * segment + (k == 0 ? 0.0 : margin)) + ", " + QString::number((k + 1) * segment - (k == recorder->nVariables ? 0.0 : margin)) + "]"; + + // if (k == 0) { + // axes += "xaxis: {" + colors + "},"; + // axes += "yaxis: {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; + // } else { + // axes += "xaxis" + QString::number(k + 1) + ": {" + colors + ", matches: 'x'},"; + // axes += "yaxis" + QString::number(k + 1) + ": {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; + // } + + // k++; + // } + QString plotColors = colorScheme == Qt::ColorScheme::Dark ? "plot_bgcolor: '#1e1e1e', paper_bgcolor: '#1e1e1e'," : ""; QString javaScript = @@ -844,6 +1040,8 @@ void MainWindow::updatePlot() { "};" "Plotly.newPlot('gd', data, layout, config);"; + qDebug().noquote() << javaScript; + ui->plotWebEngineView->page()->runJavaScript(javaScript); } diff --git a/fmusim-gui/SimulationThread.cpp b/fmusim-gui/SimulationThread.cpp index d71dda7c..4f816455 100644 --- a/fmusim-gui/SimulationThread.cpp +++ b/fmusim-gui/SimulationThread.cpp @@ -103,10 +103,13 @@ void SimulationThread::run() { } } + FMIRecorder* initialRecorder = FMICreateRecorder(S, modelDescription->nModelVariables, (const FMIModelVariable**)modelDescription->modelVariables); + FMIRecorder* recorder = FMICreateRecorder(S, recordedVariables.size(), (const FMIModelVariable**)recordedVariables.data()); settings->S = S; settings->modelDescription = modelDescription; + settings->initialRecorder = initialRecorder; settings->recorder = recorder; settings->input = input; diff --git a/fmusim/FMI3CSSimulation.c b/fmusim/FMI3CSSimulation.c index 234d561e..8d93ca58 100644 --- a/fmusim/FMI3CSSimulation.c +++ b/fmusim/FMI3CSSimulation.c @@ -30,15 +30,21 @@ static void recordIntermediateValues( *earlyReturnRequested = fmi3False; } -FMIStatus FMI3CSSimulate(FMIInstance* S, - const FMIModelDescription * modelDescription, +FMIStatus FMI3CSSimulate(//FMIInstance* S, const char* resourcePath, - FMIRecorder* recorder, - const FMIStaticInput * input, + //FMIRecorder* initialRecorder, + //FMIRecorder* recorder, + //const FMIStaticInput * input, const FMISimulationSettings * settings) { FMIStatus status = FMIOK; + FMIInstance* S = settings->S; + const FMIModelDescription* modelDescription = settings->modelDescription; + FMIRecorder* initialRecorder = settings->initialRecorder; + FMIRecorder* recorder = settings->recorder; + FMIStaticInput* input = settings->input; + fmi3Boolean inputEvent = fmi3False; fmi3Boolean eventEncountered = fmi3False; fmi3Boolean terminateSimulation = fmi3False; @@ -118,8 +124,10 @@ FMIStatus FMI3CSSimulate(FMIInstance* S, } } + CALL(FMIRecorderUpdateSizes(initialRecorder)); CALL(FMIRecorderUpdateSizes(recorder)); + CALL(FMISample(S, time, initialRecorder)); CALL(FMISample(S, time, recorder)); size_t nSteps = 0; diff --git a/fmusim/FMI3CSSimulation.h b/fmusim/FMI3CSSimulation.h index ea761c35..e1e587ad 100644 --- a/fmusim/FMI3CSSimulation.h +++ b/fmusim/FMI3CSSimulation.h @@ -4,9 +4,7 @@ FMIStatus FMI3CSSimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, + //FMIInstance* S, + //const FMIModelDescription* modelDescription, const char* resourcePath, - FMIRecorder* recorder, - const FMIStaticInput* input, const FMISimulationSettings* settings); diff --git a/fmusim/FMIRecorder.c b/fmusim/FMIRecorder.c index d0fef9ed..98af2ad1 100644 --- a/fmusim/FMIRecorder.c +++ b/fmusim/FMIRecorder.c @@ -117,6 +117,10 @@ FMIStatus FMIRecorderUpdateSizes(FMIRecorder* recorder) { FMIStatus status = FMIOK; + if (!recorder) { + goto TERMINATE; + } + for (size_t i = 0; i < N_VARIABLE_TYPES; i++) { VariableInfo* info = recorder->variableInfos[i]; diff --git a/fmusim/FMISimulation.c b/fmusim/FMISimulation.c index 754b14b7..ef456f7d 100644 --- a/fmusim/FMISimulation.c +++ b/fmusim/FMISimulation.c @@ -88,6 +88,7 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { FMIInstance* S = settings->S; const FMIModelDescription* modelDescription = settings->modelDescription; const char* unzipdir = settings->unzipdir; + FMIRecorder* initialRecorder = settings->initialRecorder; FMIRecorder* recorder = settings->recorder; FMIStaticInput* input = settings->input; @@ -123,7 +124,7 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { } else { if (settings->interfaceType == FMICoSimulation) { - CALL(FMI3CSSimulate(S, modelDescription, resourcePath, recorder, input, settings)); + CALL(FMI3CSSimulate(/*S, modelDescription,*/ resourcePath, settings)); } else { CALL(FMI3MESimulate(S, modelDescription, resourcePath, recorder, input, settings)); } diff --git a/fmusim/FMISimulation.h b/fmusim/FMISimulation.h index 47d856e9..99181f4a 100644 --- a/fmusim/FMISimulation.h +++ b/fmusim/FMISimulation.h @@ -15,6 +15,7 @@ typedef struct FMISimulationSettings { FMIInstance* S; const FMIModelDescription* modelDescription; const char* unzipdir; + FMIRecorder* initialRecorder; FMIRecorder* recorder; FMIStaticInput* input; FMIInterfaceType interfaceType; diff --git a/fmusim/fmusim.c b/fmusim/fmusim.c index c76b9e3a..18b9aa76 100644 --- a/fmusim/fmusim.c +++ b/fmusim/fmusim.c @@ -153,6 +153,7 @@ int main(int argc, const char* argv[]) { FMIModelDescription* modelDescription = NULL; FMIInstance* S = NULL; FMIStaticInput* input = NULL; + FMIRecorder* initialRecorder = NULL; FMIRecorder* recorder = NULL; const char* unzipdir = NULL; FMIStatus status = FMIFatal; @@ -352,10 +353,18 @@ int main(int argc, const char* argv[]) { CALL(FMILoadPlatformBinary(S, platformBinaryPath)); + initialRecorder = FMICreateRecorder(S, modelDescription->nModelVariables, modelDescription->modelVariables); + + if (!initialRecorder) { + printf("Failed to create initial variable recorder.\n"); + status = FMIError; + goto TERMINATE; + } + size_t nOutputVariables = 0; void* outputVariablesMemory = NULL; - + CALL(FMICalloc(&outputVariablesMemory, modelDescription->nModelVariables, sizeof(FMIModelVariable*))); FMIModelVariable** outputVariables = outputVariablesMemory; @@ -383,7 +392,7 @@ int main(int argc, const char* argv[]) { recorder = FMICreateRecorder(S, nOutputVariables, (const FMIModelVariable**)outputVariables); if (!recorder) { - printf("Failed to open result file %s for writing.\n", outputFile); + printf("Failed to create output variable recorder.\n"); status = FMIError; goto TERMINATE; } @@ -458,11 +467,12 @@ int main(int argc, const char* argv[]) { goto TERMINATE; } - settings.S = S; + settings.S = S; settings.modelDescription = modelDescription; - settings.unzipdir = unzipdir; - settings.recorder = recorder; - settings.input = input; + settings.unzipdir = unzipdir; + settings.initialRecorder = initialRecorder; + settings.recorder = recorder; + settings.input = input; status = FMISimulate(&settings); @@ -484,6 +494,7 @@ int main(int argc, const char* argv[]) { TERMINATE: FMIFreeInput(input); + FMIFreeRecorder(initialRecorder); FMIFreeRecorder(recorder); FMIFreeModelDescription(modelDescription); FMIFreeInstance(S); From 6f858f4dc6c9a04bf71f4e3317a70bdfc5c15a91 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 10:39:09 +0200 Subject: [PATCH 2/9] Add PlotUtil.cpp --- fmusim-gui/CMakeLists.txt | 1 + fmusim-gui/MainWindow.cpp | 406 +------------------------------------- fmusim-gui/PlotUtil.cpp | 233 ++++++++++++++++++++++ fmusim-gui/PlotUtil.h | 20 ++ 4 files changed, 261 insertions(+), 399 deletions(-) create mode 100644 fmusim-gui/PlotUtil.cpp create mode 100644 fmusim-gui/PlotUtil.h diff --git a/fmusim-gui/CMakeLists.txt b/fmusim-gui/CMakeLists.txt index ed9800c3..93af0009 100644 --- a/fmusim-gui/CMakeLists.txt +++ b/fmusim-gui/CMakeLists.txt @@ -99,6 +99,7 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ModelVariablesTreeModel.h ModelVariablesTreeModel.cpp AbstractModelVariablesModel.h AbstractModelVariablesModel.cpp + PlotUtil.h PlotUtil.cpp ) target_include_directories(fmusim-gui PRIVATE diff --git a/fmusim-gui/MainWindow.cpp b/fmusim-gui/MainWindow.cpp index c5143968..ec355023 100644 --- a/fmusim-gui/MainWindow.cpp +++ b/fmusim-gui/MainWindow.cpp @@ -17,6 +17,7 @@ #include "SimulationThread.h" #include "BuildPlatformBinaryThread.h" #include "BuildPlatformBinaryDialog.h" +#include "PlotUtil.h" extern "C" { #include "FMIZip.h" @@ -635,412 +636,19 @@ void MainWindow::openFileInDefaultApplication(const QModelIndex &index) { QDesktopServices::openUrl(QUrl(path)); } -static QString getData(FMIRecorder* recorder, const FMIModelVariable* variable) { - - const FMIVariableType type = variable->type; - - bool found = false; - - size_t index; - - for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { - if (recorder->variableInfos[type]->variables[index] == variable) { - found = true; - break; - } - } - - if (!found) { - return ""; - } - - QString y; - - for (size_t j = 0; j < recorder->nRows; j++) { - - Row* row = recorder->rows[j]; - - if (j > 0) { - y += ", "; - } - - switch (type) { - case FMIFloat32Type: - case FMIDiscreteFloat32Type: - { - const float* values = (float*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIFloat64Type: - case FMIDiscreteFloat64Type: - { - const double* values = (double*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt8Type: - { - const int8_t* values = (int8_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt8Type: - { - const uint8_t* values = (uint8_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt16Type: - { - const int16_t* values = (int16_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt16Type: - { - const uint16_t* values = (uint16_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt32Type: - { - const int32_t* values = (int32_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt32Type: - { - const uint32_t* values = (uint32_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIInt64Type: - { - const int64_t* values = (int64_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIUInt64Type: - { - const uint64_t* values = (uint64_t*)row->values[type]; - y += QString::number(values[index]); - } - break; - case FMIBooleanType: - { - const bool* values = (bool*)row->values[type]; - y += QString::number(values[index]); - } - break; - default: - y += "0"; - break; - } - - } - - return y; -} - void MainWindow::updatePlot() { if (!simulationThread || !simulationThread->settings->recorder) { return; } - FMIRecorder* initialRecorder = simulationThread->settings->initialRecorder; - FMIRecorder* recorder = simulationThread->settings->recorder; - - // for (const FMIModelVariable* variable : plotVariables) { - // QString y = getData(recorder, variable); - // qDebug() << y; - // } - - QString data; - - data += "var time = ["; - - for (size_t i = 0; i < recorder->nRows; i++) { - - Row* row = recorder->rows[i]; - - if (i > 0) { - data += ", "; - } - - data += QString::number(row->time); - } - - data += "];\n"; - - data += "var time2 = ["; - - data += QString::number(recorder->rows[0]->time); - - data += ", "; - - data += QString::number(recorder->rows[recorder->nRows - 1]->time); - - data += "];\n"; - - data += "var data = [\n"; - - size_t k = 0; - - for (const FMIModelVariable* variable : plotVariables) { - - if (k > 0) { - data += ", "; - } - - QString y = getData(recorder, variable); - - if (y.isEmpty()) { - y = getData(initialRecorder, variable); - y = y + ", " + y; - data += "{x: time2, y: [" + y + "], "; - } else { - // data += "{x: [0, 2], y: [4, 5], "; - data += "{x: time, y: [" + y + "], "; - } - - data += "type: 'scatter', name: '', line: {color: '#248BD2', width: 1.5"; - - if (variable->variability == FMIContinuous) { - data += "}"; - } else if (variable->type == FMIBooleanType) { - data += ", shape: 'hv'}, fill: 'tozeroy'"; - } else { - data += ", shape: 'hv'}"; - } - - if (k > 0) { - const QString plotIndex = QString::number(k + 1); - data += ", xaxis: 'x" + plotIndex + "', yaxis: 'y" + plotIndex + "'"; - } - - data += "}\n"; - - k++; - } - - data += "];\n"; - - // qDebug().noquote() << data; - - // data += "var data = [\n"; - - // size_t k = 0; - - // for (size_t i = 0; i < recorder->nVariables; i++) { - - // const FMIModelVariable* variable = recorder->variables[i]; - - // const FMIVariableType type = variable->type; - - // if (!plotVariables.contains(variable)) { - // continue; - // } - - // QString y; - - // size_t index; - - // for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { - // if (recorder->variableInfos[type]->variables[index] == variable) { - // break; - // } - // } - - // for (size_t j = 0; j < recorder->nRows; j++) { - - // Row* row = recorder->rows[j]; - - // if (j > 0) { - // y += ", "; - // } - - // switch (type) { - // case FMIFloat32Type: - // case FMIDiscreteFloat32Type: - // { - // const float* values = (float*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIFloat64Type: - // case FMIDiscreteFloat64Type: - // { - // const double* values = (double*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIInt8Type: - // { - // const int8_t* values = (int8_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIUInt8Type: - // { - // const uint8_t* values = (uint8_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIInt16Type: - // { - // const int16_t* values = (int16_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIUInt16Type: - // { - // const uint16_t* values = (uint16_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIInt32Type: - // { - // const int32_t* values = (int32_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIUInt32Type: - // { - // const uint32_t* values = (uint32_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIInt64Type: - // { - // const int64_t* values = (int64_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIUInt64Type: - // { - // const uint64_t* values = (uint64_t*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // case FMIBooleanType: - // { - // const bool* values = (bool*)row->values[type]; - // y += QString::number(values[index]); - // } - // break; - // default: - // y += "0"; - // break; - // } - // } - - // if (k > 0) { - // data += ", "; - // } - - // data += "{x: time, y: [" + y + "], type: 'scatter', name: '', line: {color: '#248BD2', width: 1.5"; - - - // if (variable->variability == FMIContinuous) { - // data += "}"; - // } else if (type == FMIBooleanType) { - // data += ", shape: 'hv'}, fill: 'tozeroy'"; - // } else { - // data += ", shape: 'hv'}"; - // } - - // if (k > 0) { - // const QString plotIndex = QString::number(k + 1); - // data += ", xaxis: 'x" + plotIndex + "', yaxis: 'y" + plotIndex + "'"; - // } - - // data += "}\n"; - - // k++; - // } - - // data += "];\n"; - - - QString axes; - - k = 0; - - for (const FMIModelVariable* variable : plotVariables) { - - const QString name = QString::fromUtf8(variable->name); - - const QString colors = colorScheme == Qt::ColorScheme::Dark ? "color: '#fff', zerolinecolor: '#666'" : "color: '#000', zerolinecolor: '#000'"; - - const double segment = 1.0 / plotVariables.size(); - const double margin = 0.02; - - const QString domain = "[" + QString::number(k * segment + (k == 0 ? 0.0 : margin)) + ", " + QString::number((k + 1) * segment - (k == recorder->nVariables ? 0.0 : margin)) + "]"; - - if (k == 0) { - axes += "xaxis: {" + colors + "},"; - axes += "yaxis: {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; - } else { - axes += "xaxis" + QString::number(k + 1) + ": {" + colors + ", matches: 'x'},"; - axes += "yaxis" + QString::number(k + 1) + ": {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; - } - - k++; - } - - // QString axes; - - // k = 0; - - // for (size_t i = 0; i < recorder->nVariables; i++) { - - // const FMIModelVariable* variable = recorder->variables[i]; - - // if (!plotVariables.contains(variable)) { - // continue; - // } - - // const QString name = QString::fromUtf8(variable->name); - - // const QString colors = colorScheme == Qt::ColorScheme::Dark ? "color: '#fff', zerolinecolor: '#666'" : "color: '#000', zerolinecolor: '#000'"; - - // const double segment = 1.0 / plotVariables.size(); - // const double margin = 0.02; - - // const QString domain = "[" + QString::number(k * segment + (k == 0 ? 0.0 : margin)) + ", " + QString::number((k + 1) * segment - (k == recorder->nVariables ? 0.0 : margin)) + "]"; - - // if (k == 0) { - // axes += "xaxis: {" + colors + "},"; - // axes += "yaxis: {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; - // } else { - // axes += "xaxis" + QString::number(k + 1) + ": {" + colors + ", matches: 'x'},"; - // axes += "yaxis" + QString::number(k + 1) + ": {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; - // } - - // k++; - // } - - QString plotColors = colorScheme == Qt::ColorScheme::Dark ? "plot_bgcolor: '#1e1e1e', paper_bgcolor: '#1e1e1e'," : ""; - - QString javaScript = - data + - " var layout = {" - " showlegend: false," - " autosize: true," - " font: {family: 'Segoe UI', size: 12}," - + plotColors + - " grid: {rows: " + QString::number(plotVariables.size()) + ", columns: 1, pattern: 'independent'}," - + axes + - " margin: { l: 60, r: 20, b: 20, t: 20, pad: 0 }" - "};" - "var config = {" - " 'responsive': true" - "};" - "Plotly.newPlot('gd', data, layout, config);"; + const QString javaScript = PlotUtil::createPlot( + simulationThread->settings->initialRecorder, + simulationThread->settings->recorder, + plotVariables, + colorScheme); - qDebug().noquote() << javaScript; + // qDebug().noquote() << javaScript; ui->plotWebEngineView->page()->runJavaScript(javaScript); } diff --git a/fmusim-gui/PlotUtil.cpp b/fmusim-gui/PlotUtil.cpp new file mode 100644 index 00000000..6832d6ee --- /dev/null +++ b/fmusim-gui/PlotUtil.cpp @@ -0,0 +1,233 @@ +#include +#include "FMIRecorder.h" +#include "PlotUtil.h" + + +PlotUtil::PlotUtil() {} + +static QString getData(const FMIRecorder* recorder, const FMIModelVariable* variable) { + + const FMIVariableType type = variable->type; + + bool found = false; + + size_t index; + + for (index = 0; index < recorder->variableInfos[type]->nVariables; index++) { + if (recorder->variableInfos[type]->variables[index] == variable) { + found = true; + break; + } + } + + if (!found) { + return ""; + } + + QString y; + + for (size_t j = 0; j < recorder->nRows; j++) { + + Row* row = recorder->rows[j]; + + if (j > 0) { + y += ", "; + } + + switch (type) { + case FMIFloat32Type: + case FMIDiscreteFloat32Type: + { + const float* values = (float*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIFloat64Type: + case FMIDiscreteFloat64Type: + { + const double* values = (double*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt8Type: + { + const int8_t* values = (int8_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt8Type: + { + const uint8_t* values = (uint8_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt16Type: + { + const int16_t* values = (int16_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt16Type: + { + const uint16_t* values = (uint16_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt32Type: + { + const int32_t* values = (int32_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt32Type: + { + const uint32_t* values = (uint32_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIInt64Type: + { + const int64_t* values = (int64_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIUInt64Type: + { + const uint64_t* values = (uint64_t*)row->values[type]; + y += QString::number(values[index]); + } + break; + case FMIBooleanType: + { + const bool* values = (bool*)row->values[type]; + y += QString::number(values[index]); + } + break; + default: + y += "0"; + break; + } + + } + + return y; +} + + +QString PlotUtil::createPlot(const FMIRecorder* initialRecorder, const FMIRecorder* recorder, const QList plotVariables, Qt::ColorScheme colorScheme) { + + QString data; + + data += "var time = ["; + + for (size_t i = 0; i < recorder->nRows; i++) { + + Row* row = recorder->rows[i]; + + if (i > 0) { + data += ", "; + } + + data += QString::number(row->time); + } + + data += "];\n"; + + data += "var time2 = ["; + + data += QString::number(recorder->rows[0]->time); + + data += ", "; + + data += QString::number(recorder->rows[recorder->nRows - 1]->time); + + data += "];\n"; + + data += "var data = [\n"; + + size_t k = 0; + + for (const FMIModelVariable* variable : plotVariables) { + + if (k > 0) { + data += ", "; + } + + QString y = getData(recorder, variable); + + if (y.isEmpty()) { + y = getData(initialRecorder, variable); + y = y + ", " + y; + data += "{x: time2, y: [" + y + "], "; + } else { + data += "{x: time, y: [" + y + "], "; + } + + data += "type: 'scatter', type: 'line', mode: 'lines', name: '', line: {color: '#248BD2', width: 1.5"; + + if (variable->variability == FMIContinuous) { + data += "}"; + } else if (variable->type == FMIBooleanType) { + data += ", shape: 'hv'}, fill: 'tozeroy'"; + } else { + data += ", shape: 'hv'}"; + } + + if (k > 0) { + const QString plotIndex = QString::number(k + 1); + data += ", xaxis: 'x" + plotIndex + "', yaxis: 'y" + plotIndex + "'"; + } + + data += "}\n"; + + k++; + } + + data += "];\n"; + + QString axes; + + k = 0; + + for (const FMIModelVariable* variable : plotVariables) { + + const QString name = QString::fromUtf8(variable->name); + + const QString colors = colorScheme == Qt::ColorScheme::Dark ? "color: '#fff', zerolinecolor: '#666'" : "color: '#000', zerolinecolor: '#000'"; + + const double segment = 1.0 / plotVariables.size(); + const double margin = 0.02; + + const QString domain = "[" + QString::number(k * segment + (k == 0 ? 0.0 : margin)) + ", " + QString::number((k + 1) * segment - (k == recorder->nVariables ? 0.0 : margin)) + "]"; + + if (k == 0) { + axes += "xaxis: {" + colors + "},"; + axes += "yaxis: {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; + } else { + axes += "xaxis" + QString::number(k + 1) + ": {" + colors + ", matches: 'x'},"; + axes += "yaxis" + QString::number(k + 1) + ": {title: '" + name + "', titlefont: {size: 13}, " + colors + ", domain: " + domain + "},"; + } + + k++; + } + + QString plotColors = colorScheme == Qt::ColorScheme::Dark ? "plot_bgcolor: '#1e1e1e', paper_bgcolor: '#1e1e1e'," : ""; + + QString javaScript = + data + + " var layout = {" + " showlegend: false," + " autosize: true," + " font: {family: 'Segoe UI', size: 12}," + + plotColors + + " grid: {rows: " + QString::number(plotVariables.size()) + ", columns: 1, pattern: 'independent'}," + + axes + + " margin: { l: 60, r: 20, b: 20, t: 20, pad: 0 }" + "};" + "var config = {" + " 'responsive': true" + "};" + "Plotly.newPlot('gd', data, layout, config);"; + + return javaScript; +} diff --git a/fmusim-gui/PlotUtil.h b/fmusim-gui/PlotUtil.h new file mode 100644 index 00000000..9d7daebd --- /dev/null +++ b/fmusim-gui/PlotUtil.h @@ -0,0 +1,20 @@ +#ifndef PLOTUTIL_H +#define PLOTUTIL_H + +#include + +extern "C" { +typedef struct FMIRecorder FMIRecorder; +typedef struct FMIModelVariable FMIModelVariable; +} + +class PlotUtil +{ +private: + PlotUtil(); + +public: + static QString createPlot(const FMIRecorder* initialRecorder, const FMIRecorder* recorder, const QList plotVariables, Qt::ColorScheme colorScheme); +}; + +#endif // PLOTUTIL_H From d31ffe22a5af411fd110f3985530694c133706b1 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 11:44:22 +0200 Subject: [PATCH 3/9] Record initial values --- fmusim/FMI1CSSimulation.c | 48 ++++++++++----------- fmusim/FMI1CSSimulation.h | 8 +--- fmusim/FMI1MESimulation.c | 59 +++++++++++++------------- fmusim/FMI1MESimulation.h | 7 +-- fmusim/FMI2CSSimulation.c | 49 ++++++++++----------- fmusim/FMI2CSSimulation.h | 8 +--- fmusim/FMI2MESimulation.c | 75 ++++++++++++++++----------------- fmusim/FMI2MESimulation.h | 8 +--- fmusim/FMI3CSSimulation.c | 89 ++++++++++++++++++--------------------- fmusim/FMI3MESimulation.c | 76 ++++++++++++++++----------------- fmusim/FMI3MESimulation.h | 8 +--- fmusim/FMISimulation.c | 16 +++---- 12 files changed, 199 insertions(+), 252 deletions(-) diff --git a/fmusim/FMI1CSSimulation.c b/fmusim/FMI1CSSimulation.c index 9e336c0c..fe808046 100644 --- a/fmusim/FMI1CSSimulation.c +++ b/fmusim/FMI1CSSimulation.c @@ -4,47 +4,45 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI1CSSimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* fmuLocation, - FMIRecorder* recorder, - const FMIStaticInput * input, - const FMISimulationSettings * settings) { +FMIStatus FMI1CSSimulate(const char* fmuLocation, const FMISimulationSettings * s) { FMIStatus status = FMIOK; + FMIInstance* S = s->S; + CALL(FMI1InstantiateSlave(S, - modelDescription->coSimulation->modelIdentifier, // modelIdentifier - modelDescription->instantiationToken, // fmuGUID - fmuLocation, // fmuLocation - "application/x-fmusim", // mimeType - 0.0, // timeout - settings->visible, // visible - fmi1False, // interactive - settings->loggingOn // loggingOn + s->modelDescription->coSimulation->modelIdentifier, // modelIdentifier + s->modelDescription->instantiationToken, // fmuGUID + fmuLocation, // fmuLocation + "application/x-fmusim", // mimeType + 0.0, // timeout + s->visible, // visible + fmi1False, // interactive + s->loggingOn // loggingOn )); // set start values - CALL(FMIApplyStartValues(S, settings)); - CALL(FMIApplyInput(S, input, settings->startTime, true, true, false)); + CALL(FMIApplyStartValues(S, s)); + CALL(FMIApplyInput(S, s->input, s->startTime, true, true, false)); // initialize - CALL(FMI1InitializeSlave(S, settings->startTime, fmi1False, 0)); + CALL(FMI1InitializeSlave(S, s->startTime, fmi1False, 0)); + + CALL(FMISample(S, s->startTime, s->initialRecorder)); for (unsigned long step = 0;; step++) { - const fmi1Real time = settings->startTime + step * settings->outputInterval; + const fmi1Real time = s->startTime + step * s->outputInterval; - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); - CALL(FMIApplyInput(S, input, time, true, true, false)); + CALL(FMIApplyInput(S, s->input, time, true, true, false)); - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - const FMIStatus doStepStatus = FMI1DoStep(S, time, settings->outputInterval, fmi1True); + const FMIStatus doStepStatus = FMI1DoStep(S, time, s->outputInterval, fmi1True); if (doStepStatus == fmi1Discard) { @@ -58,7 +56,7 @@ FMIStatus FMI1CSSimulate( CALL(FMI1GetRealStatus(S, fmi1LastSuccessfulTime, &lastSuccessfulTime)); - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); break; } @@ -67,7 +65,7 @@ FMIStatus FMI1CSSimulate( CALL(doStepStatus); } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } diff --git a/fmusim/FMI1CSSimulation.h b/fmusim/FMI1CSSimulation.h index 80a2ba74..8d273952 100644 --- a/fmusim/FMI1CSSimulation.h +++ b/fmusim/FMI1CSSimulation.h @@ -3,10 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI1CSSimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourceURI, - FMIRecorder* recorder, - const FMIStaticInput* input, - const FMISimulationSettings* settings); +FMIStatus FMI1CSSimulate(const char* fmuLocation, const FMISimulationSettings* s); diff --git a/fmusim/FMI1MESimulation.c b/fmusim/FMI1MESimulation.c index 7a09eced..89b4c474 100644 --- a/fmusim/FMI1MESimulation.c +++ b/fmusim/FMI1MESimulation.c @@ -8,16 +8,13 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI1MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - FMIRecorder* recorder, - const FMIStaticInput * input, - const FMISimulationSettings* settings) { +FMIStatus FMI1MESimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; - fmi1Real time = settings->startTime; + FMIInstance* S = s->S; + + fmi1Real time = s->startTime; bool stateEvent = false; fmi1Boolean inputEvent = fmi1False; @@ -43,22 +40,22 @@ FMIStatus FMI1MESimulate( }; CALL(FMI1InstantiateModel(S, - modelDescription->modelExchange->modelIdentifier, // modelIdentifier - modelDescription->instantiationToken, // GUID - settings->loggingOn // loggingOn + s->modelDescription->modelExchange->modelIdentifier, // modelIdentifier + s->modelDescription->instantiationToken, // GUID + s->loggingOn // loggingOn )); // set start values - CALL(FMIApplyStartValues(S, settings)); + CALL(FMIApplyStartValues(S, s)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous false // after event )); // initialize - CALL(FMI1Initialize(S, settings->tolerance > 0, settings->tolerance, &eventInfo)); + CALL(FMI1Initialize(S, s->tolerance > 0, s->tolerance, &eventInfo)); if (!eventInfo.upcomingTimeEvent) { eventInfo.nextEventTime = INFINITY; @@ -66,11 +63,11 @@ FMIStatus FMI1MESimulate( const FMISolverParameters solverFunctions = { .modelInstance = S, - .input = input, + .input = s->input, .startTime = time, - .tolerance = settings->tolerance, - .nx = modelDescription->nContinuousStates, - .nz = modelDescription->nEventIndicators, + .tolerance = s->tolerance, + .nx = s->modelDescription->nContinuousStates, + .nz = s->modelDescription->nEventIndicators, .setTime = (FMISolverSetTime)FMI1SetTime, .applyInput = (FMISolverApplyInput)FMIApplyInput, .getContinuousStates = (FMISolverGetContinuousStates)FMI1GetContinuousStates, @@ -81,26 +78,28 @@ FMIStatus FMI1MESimulate( .logError = (FMISolverLogError)FMILogError }; - solver = settings->solverCreate(&solverFunctions); + solver = s->solverCreate(&solverFunctions); if (!solver) { status = FMIError; goto TERMINATE; } + CALL(FMISample(S, time, s->initialRecorder)); + for (;;) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - nextRegularPoint = settings->startTime + (nSteps + 1) * settings->outputInterval; + nextRegularPoint = s->startTime + (nSteps + 1) * s->outputInterval; nextCommunicationPoint = nextRegularPoint; - nextInputEventTime = FMINextInputEvent(input, time); + nextInputEventTime = FMINextInputEvent(s->input, time); inputEvent = nextCommunicationPoint >= nextInputEventTime; @@ -110,11 +109,11 @@ FMIStatus FMI1MESimulate( nextCommunicationPoint = fmin(nextInputEventTime, eventInfo.nextEventTime); } - CALL(settings->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); + CALL(s->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); CALL(FMI1SetTime(S, time)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, false, // discrete true, // continous false // after event @@ -133,10 +132,10 @@ FMIStatus FMI1MESimulate( if (inputEvent || timeEvent || stateEvent || stepEvent) { // record the values before the event - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); if (inputEvent) { - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous true // after event @@ -150,7 +149,7 @@ FMIStatus FMI1MESimulate( CALL(FMI1EventUpdate(S, fmi1True, &eventInfo)); if (eventInfo.terminateSimulation) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); goto TERMINATE; } @@ -163,11 +162,11 @@ FMIStatus FMI1MESimulate( } if (resetSolver) { - settings->solverReset(solver, time); + s->solverReset(solver, time); } } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } @@ -188,7 +187,7 @@ FMIStatus FMI1MESimulate( } if (solver) { - settings->solverFree(solver); + s->solverFree(solver); } return status; diff --git a/fmusim/FMI1MESimulation.h b/fmusim/FMI1MESimulation.h index aeac1794..586d45ea 100644 --- a/fmusim/FMI1MESimulation.h +++ b/fmusim/FMI1MESimulation.h @@ -3,9 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI1MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - FMIRecorder* recorder, - const FMIStaticInput* input, - const FMISimulationSettings* settings); +FMIStatus FMI1MESimulate(const FMISimulationSettings* s); diff --git a/fmusim/FMI2CSSimulation.c b/fmusim/FMI2CSSimulation.c index 33fe2cbe..c3957896 100644 --- a/fmusim/FMI2CSSimulation.c +++ b/fmusim/FMI2CSSimulation.c @@ -5,51 +5,48 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) - -FMIStatus FMI2CSSimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourceURI, - FMIRecorder* recorder, - const FMIStaticInput * input, - const FMISimulationSettings * settings) { +FMIStatus FMI2CSSimulate(const char* resourceURI, const FMISimulationSettings* s) { FMIStatus status = FMIOK; + FMIInstance* S = s->S; + CALL(FMI2Instantiate(S, resourceURI, fmi2CoSimulation, - modelDescription->instantiationToken, - settings->visible, - settings->loggingOn + s->modelDescription->instantiationToken, + s->visible, + s->loggingOn )); - if (settings->initialFMUStateFile) { - CALL(FMIRestoreFMUStateFromFile(S, settings->initialFMUStateFile)); + if (s->initialFMUStateFile) { + CALL(FMIRestoreFMUStateFromFile(S, s->initialFMUStateFile)); } - CALL(FMIApplyStartValues(S, settings)); + CALL(FMIApplyStartValues(S, s)); - if (!settings->initialFMUStateFile) { - CALL(FMI2SetupExperiment(S, settings->tolerance > 0, settings->tolerance, settings->startTime, fmi2False, 0)); + if (!s->initialFMUStateFile) { + CALL(FMI2SetupExperiment(S, s->tolerance > 0, s->tolerance, s->startTime, fmi2False, 0)); CALL(FMI2EnterInitializationMode(S)); - CALL(FMIApplyInput(S, input, settings->startTime, true, true, false)); + CALL(FMIApplyInput(S, s->input, s->startTime, true, true, false)); CALL(FMI2ExitInitializationMode(S)); } + CALL(FMISample(S, s->startTime, s->initialRecorder)); + for (unsigned long step = 0;; step++) { - const fmi2Real time = settings->startTime + step * settings->outputInterval; + const fmi2Real time = s->startTime + step * s->outputInterval; - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); - CALL(FMIApplyInput(S, input, time, true, true, false)); + CALL(FMIApplyInput(S, s->input, time, true, true, false)); - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - const FMIStatus doStepStatus = FMI2DoStep(S, time, settings->outputInterval, fmi2True); + const FMIStatus doStepStatus = FMI2DoStep(S, time, s->outputInterval, fmi2True); if (doStepStatus == fmi2Discard) { @@ -62,7 +59,7 @@ FMIStatus FMI2CSSimulate( CALL(FMI2GetRealStatus(S, fmi2LastSuccessfulTime, &lastSuccessfulTime)); - CALL(FMISample(S, lastSuccessfulTime, recorder)); + CALL(FMISample(S, lastSuccessfulTime, s->recorder)); break; } @@ -71,13 +68,13 @@ FMIStatus FMI2CSSimulate( CALL(doStepStatus); } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } - if (settings->finalFMUStateFile) { - CALL(FMISaveFMUStateToFile(S, settings->finalFMUStateFile)); + if (s->finalFMUStateFile) { + CALL(FMISaveFMUStateToFile(S, s->finalFMUStateFile)); } TERMINATE: diff --git a/fmusim/FMI2CSSimulation.h b/fmusim/FMI2CSSimulation.h index 21d51697..cf346a2b 100644 --- a/fmusim/FMI2CSSimulation.h +++ b/fmusim/FMI2CSSimulation.h @@ -3,10 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI2CSSimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourceURI, - FMIRecorder* recorder, - const FMIStaticInput* input, - const FMISimulationSettings* settings); +FMIStatus FMI2CSSimulate(const char* resourceURI, const FMISimulationSettings* s); diff --git a/fmusim/FMI2MESimulation.c b/fmusim/FMI2MESimulation.c index bc7e94fe..dea4416a 100644 --- a/fmusim/FMI2MESimulation.c +++ b/fmusim/FMI2MESimulation.c @@ -8,18 +8,13 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) +FMIStatus FMI2MESimulate(const char* resourceURI, const FMISimulationSettings* s) { -FMIStatus FMI2MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourceURI, - FMIRecorder* recorder, - const FMIStaticInput * input, - const FMISimulationSettings* settings) { + FMIStatus status = FMIOK; - const bool needsCompletedIntegratorStep = modelDescription->modelExchange->needsCompletedIntegratorStep; + FMIInstance* S = s->S; - FMIStatus status = FMIOK; + const bool needsCompletedIntegratorStep = s->modelDescription->modelExchange->needsCompletedIntegratorStep; fmi2Real time; @@ -49,24 +44,24 @@ FMIStatus FMI2MESimulate( CALL(FMI2Instantiate(S, resourceURI, fmi2ModelExchange, - modelDescription->instantiationToken, - settings->visible, - settings->loggingOn + s->modelDescription->instantiationToken, + s->visible, + s->loggingOn )); - time = settings->startTime; + time = s->startTime; - if (settings->initialFMUStateFile) { - CALL(FMIRestoreFMUStateFromFile(S, settings->initialFMUStateFile)); + if (s->initialFMUStateFile) { + CALL(FMIRestoreFMUStateFromFile(S, s->initialFMUStateFile)); } - CALL(FMIApplyStartValues(S, settings)); + CALL(FMIApplyStartValues(S, s)); - if (!settings->initialFMUStateFile) { + if (!s->initialFMUStateFile) { - CALL(FMI2SetupExperiment(S, settings->tolerance > 0, settings->tolerance, time, fmi2False, 0)); + CALL(FMI2SetupExperiment(S, s->tolerance > 0, s->tolerance, time, fmi2False, 0)); CALL(FMI2EnterInitializationMode(S)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous false // after event @@ -92,11 +87,11 @@ FMIStatus FMI2MESimulate( const FMISolverParameters solverFunctions = { .modelInstance = S, - .input = input, + .input = s->input, .startTime = time, - .tolerance = settings->tolerance, - .nx = modelDescription->nContinuousStates, - .nz = modelDescription->nEventIndicators, + .tolerance = s->tolerance, + .nx = s->modelDescription->nContinuousStates, + .nz = s->modelDescription->nEventIndicators, .setTime = (FMISolverSetTime)FMI2SetTime, .applyInput = (FMISolverApplyInput)FMIApplyInput, .getContinuousStates = (FMISolverGetContinuousStates)FMI2GetContinuousStates, @@ -107,7 +102,7 @@ FMIStatus FMI2MESimulate( .logError = (FMISolverLogError)FMILogError }; - solver = settings->solverCreate(&solverFunctions); + solver = s->solverCreate(&solverFunctions); if (!solver) { status = FMIError; @@ -116,19 +111,21 @@ FMIStatus FMI2MESimulate( nSteps = 0; + CALL(FMISample(S, time, s->initialRecorder)); + for (;;) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - nextRegularPoint = settings->startTime + (nSteps + 1) * settings->outputInterval; + nextRegularPoint = s->startTime + (nSteps + 1) * s->outputInterval; nextCommunicationPoint = nextRegularPoint; - nextInputEventTime = FMINextInputEvent(input, time); + nextInputEventTime = FMINextInputEvent(s->input, time); inputEvent = nextCommunicationPoint >= nextInputEventTime; @@ -138,11 +135,11 @@ FMIStatus FMI2MESimulate( nextCommunicationPoint = fmin(nextInputEventTime, eventInfo.nextEventTime); } - CALL(settings->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); + CALL(s->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); CALL(FMI2SetTime(S, time)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, false, // discrete true, // continous false // after event @@ -164,12 +161,12 @@ FMIStatus FMI2MESimulate( if (inputEvent || timeEvent || stateEvent || stepEvent) { // record the values before the event - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); CALL(FMI2EnterEventMode(S)); if (inputEvent) { - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous true // after event @@ -183,7 +180,7 @@ FMIStatus FMI2MESimulate( CALL(FMI2NewDiscreteStates(S, &eventInfo)); if (eventInfo.terminateSimulation) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); goto TERMINATE; } @@ -199,17 +196,17 @@ FMIStatus FMI2MESimulate( CALL(FMI2EnterContinuousTimeMode(S)); if (resetSolver) { - settings->solverReset(solver, time); + s->solverReset(solver, time); } } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } - if (settings->finalFMUStateFile) { - CALL(FMISaveFMUStateToFile(S, settings->finalFMUStateFile)); + if (s->finalFMUStateFile) { + CALL(FMISaveFMUStateToFile(S, s->finalFMUStateFile)); } TERMINATE: @@ -228,8 +225,8 @@ FMIStatus FMI2MESimulate( } if (solver) { - settings->solverFree(solver); + s->solverFree(solver); } return status; -} \ No newline at end of file +} diff --git a/fmusim/FMI2MESimulation.h b/fmusim/FMI2MESimulation.h index 135e2f15..3f09fae1 100644 --- a/fmusim/FMI2MESimulation.h +++ b/fmusim/FMI2MESimulation.h @@ -3,10 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI2MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourceURI, - FMIRecorder* recorder, - const FMIStaticInput* input, - const FMISimulationSettings* settings); +FMIStatus FMI2MESimulate(const char* resourceURI, const FMISimulationSettings* s); diff --git a/fmusim/FMI3CSSimulation.c b/fmusim/FMI3CSSimulation.c index 8d93ca58..2a59a133 100644 --- a/fmusim/FMI3CSSimulation.c +++ b/fmusim/FMI3CSSimulation.c @@ -30,27 +30,18 @@ static void recordIntermediateValues( *earlyReturnRequested = fmi3False; } -FMIStatus FMI3CSSimulate(//FMIInstance* S, - const char* resourcePath, - //FMIRecorder* initialRecorder, - //FMIRecorder* recorder, - //const FMIStaticInput * input, - const FMISimulationSettings * settings) { +FMIStatus FMI3CSSimulate(const char* resourcePath, const FMISimulationSettings* s) { FMIStatus status = FMIOK; - FMIInstance* S = settings->S; - const FMIModelDescription* modelDescription = settings->modelDescription; - FMIRecorder* initialRecorder = settings->initialRecorder; - FMIRecorder* recorder = settings->recorder; - FMIStaticInput* input = settings->input; + FMIInstance* S = s->S; fmi3Boolean inputEvent = fmi3False; fmi3Boolean eventEncountered = fmi3False; fmi3Boolean terminateSimulation = fmi3False; fmi3Boolean earlyReturn = fmi3False; - fmi3Float64 lastSuccessfulTime = settings->startTime; - fmi3Float64 time = settings->startTime; + fmi3Float64 lastSuccessfulTime = s->startTime; + fmi3Float64 time = s->startTime; fmi3Float64 nextCommunicationPoint = 0.0; fmi3Float64 nextRegularPoint = 0.0; fmi3Float64 stepSize = 0.0; @@ -65,40 +56,40 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, size_t nRequiredIntermediateVariables = 0; fmi3IntermediateUpdateCallback intermediateUpdate = NULL; - if (settings->recordIntermediateValues) { - requiredIntermediateVariables = (fmi3ValueReference*)recorder->valueReferences; - nRequiredIntermediateVariables = recorder->nVariables; + if (s->recordIntermediateValues) { + requiredIntermediateVariables = (fmi3ValueReference*)s->recorder->valueReferences; + nRequiredIntermediateVariables = s->recorder->nVariables; intermediateUpdate = recordIntermediateValues; - S->userData = recorder; + S->userData = s->recorder; } CALL(FMI3InstantiateCoSimulation(S, - modelDescription->instantiationToken, + s->modelDescription->instantiationToken, resourcePath, - settings->visible, - settings->loggingOn, - settings->eventModeUsed, - settings->earlyReturnAllowed, + s->visible, + s->loggingOn, + s->eventModeUsed, + s->earlyReturnAllowed, requiredIntermediateVariables, nRequiredIntermediateVariables, intermediateUpdate )); - if (settings->initialFMUStateFile) { - CALL(FMIRestoreFMUStateFromFile(S, settings->initialFMUStateFile)); + if (s->initialFMUStateFile) { + CALL(FMIRestoreFMUStateFromFile(S, s->initialFMUStateFile)); } - CALL(FMIApplyStartValues(S, settings)); + CALL(FMIApplyStartValues(S, s)); - if (!settings->initialFMUStateFile) { + if (!s->initialFMUStateFile) { - CALL(FMI3EnterInitializationMode(S, settings->tolerance > 0, settings->tolerance, settings->startTime, fmi3False, 0)); + CALL(FMI3EnterInitializationMode(S, s->tolerance > 0, s->tolerance, s->startTime, fmi3False, 0)); - CALL(FMIApplyInput(S, input, settings->startTime, true, true, false)); + CALL(FMIApplyInput(S, s->input, s->startTime, true, true, false)); CALL(FMI3ExitInitializationMode(S)); - if (settings->eventModeUsed) { + if (s->eventModeUsed) { do { @@ -124,25 +115,25 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, } } - CALL(FMIRecorderUpdateSizes(initialRecorder)); - CALL(FMIRecorderUpdateSizes(recorder)); + CALL(FMIRecorderUpdateSizes(s->initialRecorder)); + CALL(FMIRecorderUpdateSizes(s->recorder)); - CALL(FMISample(S, time, initialRecorder)); - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->initialRecorder)); + CALL(FMISample(S, time, s->recorder)); size_t nSteps = 0; for (;;) { - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - nextRegularPoint = settings->startTime + (nSteps + 1) * settings->outputInterval; + nextRegularPoint = s->startTime + (nSteps + 1) * s->outputInterval; nextCommunicationPoint = nextRegularPoint; - nextInputEventTime = FMINextInputEvent(input, time); + nextInputEventTime = FMINextInputEvent(s->input, time); inputEvent = nextCommunicationPoint >= nextInputEventTime; @@ -152,10 +143,10 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, stepSize = nextCommunicationPoint - time; - CALL(FMIApplyInput(S, input, time, - !settings->eventModeUsed, // discrete - true, // continuous - !settings->eventModeUsed // afterEvent + CALL(FMIApplyInput(S, s->input, time, + !s->eventModeUsed, // discrete + true, // continuous + !s->eventModeUsed // afterEvent )); CALL(FMI3DoStep(S, @@ -168,7 +159,7 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, &lastSuccessfulTime // lastSuccessfulTime )); - if (earlyReturn && !settings->earlyReturnAllowed) { + if (earlyReturn && !s->earlyReturnAllowed) { FMILogError("The FMU returned early from fmi3DoStep() but early return is not allowed."); status = FMIError; goto TERMINATE; @@ -184,18 +175,18 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, nSteps++; } - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); if (terminateSimulation) { goto TERMINATE; } - if (settings->eventModeUsed && (inputEvent || eventEncountered)) { + if (s->eventModeUsed && (inputEvent || eventEncountered)) { CALL(FMI3EnterEventMode(S)); if (inputEvent) { - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous true // after event @@ -213,7 +204,7 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, &nextEventTime)); if (terminateSimulation) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); goto TERMINATE; } @@ -225,16 +216,16 @@ FMIStatus FMI3CSSimulate(//FMIInstance* S, CALL(FMI3EnterStepMode(S)); - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } - if (settings->finalFMUStateFile) { - CALL(FMISaveFMUStateToFile(S, settings->finalFMUStateFile)); + if (s->finalFMUStateFile) { + CALL(FMISaveFMUStateToFile(S, s->finalFMUStateFile)); } TERMINATE: diff --git a/fmusim/FMI3MESimulation.c b/fmusim/FMI3MESimulation.c index 8757d738..a2664fef 100644 --- a/fmusim/FMI3MESimulation.c +++ b/fmusim/FMI3MESimulation.c @@ -9,18 +9,14 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI3MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourcePath, - FMIRecorder* recorder, - const FMIStaticInput * input, - const FMISimulationSettings * settings) { - - const bool needsCompletedIntegratorStep = modelDescription->modelExchange->needsCompletedIntegratorStep; +FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings * s) { FMIStatus status = FMIOK; + const bool needsCompletedIntegratorStep = s->modelDescription->modelExchange->needsCompletedIntegratorStep; + + FMIInstance* S = s->S; + fmi3Float64 time; fmi3Boolean inputEvent = fmi3False; @@ -45,26 +41,26 @@ FMIStatus FMI3MESimulate( FMISolver* solver = NULL; CALL(FMI3InstantiateModelExchange(S, - modelDescription->instantiationToken, + s->modelDescription->instantiationToken, resourcePath, - settings->visible, - settings->loggingOn + s->visible, + s->loggingOn )); - time = settings->startTime; + time = s->startTime; - if (settings->initialFMUStateFile) { - CALL(FMIRestoreFMUStateFromFile(S, settings->initialFMUStateFile)); + if (s->initialFMUStateFile) { + CALL(FMIRestoreFMUStateFromFile(S, s->initialFMUStateFile)); } - CALL(FMIApplyStartValues(S, settings)); + CALL(FMIApplyStartValues(S, s)); - if (!settings->initialFMUStateFile) { + if (!s->initialFMUStateFile) { // initialize - CALL(FMI3EnterInitializationMode(S, settings->tolerance > 0, settings->tolerance, time, fmi3False, 0)); + CALL(FMI3EnterInitializationMode(S, s->tolerance > 0, s->tolerance, time, fmi3False, 0)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous false // after event @@ -96,13 +92,13 @@ FMIStatus FMI3MESimulate( CALL(FMI3EnterContinuousTimeMode(S)); } - CALL(FMIRecorderUpdateSizes(recorder)); + CALL(FMIRecorderUpdateSizes(s->recorder)); FMISolverParameters solverFunctions = { .modelInstance = S, - .input = input, + .input = s->input, .startTime = time, - .tolerance = settings->tolerance, + .tolerance = s->tolerance, .setTime = (FMISolverSetTime)FMI3SetTime, .applyInput = (FMISolverApplyInput)FMIApplyInput, .getContinuousStates = (FMISolverGetContinuousStates)FMI3GetContinuousStates, @@ -113,10 +109,10 @@ FMIStatus FMI3MESimulate( .logError = (FMISolverLogError)FMILogError }; - CALL(FMIGetNumberOfUnkownValues(S, modelDescription->nContinuousStates, modelDescription->derivatives, &solverFunctions.nx)); - CALL(FMIGetNumberOfUnkownValues(S, modelDescription->nEventIndicators, modelDescription->eventIndicators, &solverFunctions.nz)); + CALL(FMIGetNumberOfUnkownValues(S, s->modelDescription->nContinuousStates, s->modelDescription->derivatives, &solverFunctions.nx)); + CALL(FMIGetNumberOfUnkownValues(S, s->modelDescription->nEventIndicators, s->modelDescription->eventIndicators, &solverFunctions.nz)); - solver = settings->solverCreate(&solverFunctions); + solver = s->solverCreate(&solverFunctions); if (!solver) { status = FMIError; @@ -125,19 +121,21 @@ FMIStatus FMI3MESimulate( nSteps = 0; + CALL(FMISample(S, time, s->initialRecorder)); + for (;;) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); - if (time >= settings->stopTime) { + if (time >= s->stopTime) { break; } - nextRegularPoint = settings->startTime + (nSteps + 1) * settings->outputInterval; + nextRegularPoint = s->startTime + (nSteps + 1) * s->outputInterval; nextCommunicationPoint = nextRegularPoint; - nextInputEventTime = FMINextInputEvent(input, time); + nextInputEventTime = FMINextInputEvent(s->input, time); inputEvent = nextCommunicationPoint >= nextInputEventTime; @@ -147,11 +145,11 @@ FMIStatus FMI3MESimulate( nextCommunicationPoint = fmin(nextInputEventTime, nextEventTime); } - CALL(settings->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); + CALL(s->solverStep(solver, nextCommunicationPoint, &time, &stateEvent)); CALL(FMI3SetTime(S, time)); - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, false, // discrete true, // continous false // after event @@ -172,12 +170,12 @@ FMIStatus FMI3MESimulate( if (inputEvent || timeEvent || stateEvent || stepEvent) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); CALL(FMI3EnterEventMode(S)); if (inputEvent) { - CALL(FMIApplyInput(S, input, time, + CALL(FMIApplyInput(S, s->input, time, true, // discrete true, // continous true // after event @@ -197,7 +195,7 @@ FMIStatus FMI3MESimulate( &nextEventTime)); if (terminateSimulation) { - CALL(FMISample(S, time, recorder)); + CALL(FMISample(S, time, s->recorder)); goto TERMINATE; } @@ -212,17 +210,17 @@ FMIStatus FMI3MESimulate( CALL(FMI3EnterContinuousTimeMode(S)); if (resetSolver) { - settings->solverReset(solver, time); + s->solverReset(solver, time); } } - if (settings->stepFinished && !settings->stepFinished(settings, time)) { + if (s->stepFinished && !s->stepFinished(s, time)) { break; } } - if (settings->finalFMUStateFile) { - CALL(FMISaveFMUStateToFile(S, settings->finalFMUStateFile)); + if (s->finalFMUStateFile) { + CALL(FMISaveFMUStateToFile(S, s->finalFMUStateFile)); } TERMINATE: @@ -241,7 +239,7 @@ FMIStatus FMI3MESimulate( } if (solver) { - settings->solverFree(solver); + s->solverFree(solver); } return status; diff --git a/fmusim/FMI3MESimulation.h b/fmusim/FMI3MESimulation.h index c76b059e..8f6a4cde 100644 --- a/fmusim/FMI3MESimulation.h +++ b/fmusim/FMI3MESimulation.h @@ -3,10 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI3MESimulate( - FMIInstance* S, - const FMIModelDescription* modelDescription, - const char* resourcePath, - FMIRecorder* recorder, - const FMIStaticInput* input, - const FMISimulationSettings* settings); +FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings* s); diff --git a/fmusim/FMISimulation.c b/fmusim/FMISimulation.c index ef456f7d..bf69e6eb 100644 --- a/fmusim/FMISimulation.c +++ b/fmusim/FMISimulation.c @@ -85,12 +85,8 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { FMIStatus status = FMIOK; - FMIInstance* S = settings->S; const FMIModelDescription* modelDescription = settings->modelDescription; const char* unzipdir = settings->unzipdir; - FMIRecorder* initialRecorder = settings->initialRecorder; - FMIRecorder* recorder = settings->recorder; - FMIStaticInput* input = settings->input; char resourcePath[FMI_PATH_MAX] = ""; @@ -105,9 +101,9 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { if (settings->interfaceType == FMICoSimulation) { char fmuLocation[FMI_PATH_MAX] = ""; CALL(FMIPathToURI(unzipdir, fmuLocation, FMI_PATH_MAX)); - CALL(FMI1CSSimulate(S, modelDescription, fmuLocation, recorder, input, settings)); + CALL(FMI1CSSimulate(fmuLocation, settings)); } else { - CALL(FMI1MESimulate(S, modelDescription, recorder, input, settings)); + CALL(FMI1MESimulate(settings)); } } else if (modelDescription->fmiMajorVersion == FMIMajorVersion2) { @@ -116,17 +112,17 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { CALL(FMIPathToURI(resourcePath, resourceURI, FMI_PATH_MAX)); if (settings->interfaceType == FMICoSimulation) { - CALL(FMI2CSSimulate(S, modelDescription, resourceURI, recorder, input, settings)); + CALL(FMI2CSSimulate(resourceURI, settings)); } else { - CALL(FMI2MESimulate(S, modelDescription, resourceURI, recorder, input, settings)); + CALL(FMI2MESimulate(resourceURI, settings)); } } else { if (settings->interfaceType == FMICoSimulation) { - CALL(FMI3CSSimulate(/*S, modelDescription,*/ resourcePath, settings)); + CALL(FMI3CSSimulate(resourcePath, settings)); } else { - CALL(FMI3MESimulate(S, modelDescription, resourcePath, recorder, input, settings)); + CALL(FMI3MESimulate(resourcePath, settings)); } } From 886f26cbb7d9c9e5021f74e7a649517e30320ffa Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 14:52:07 +0200 Subject: [PATCH 4/9] Remove resource path from FMI*Simulate() --- fmusim-gui/MainWindow.cpp | 8 ++++ fmusim-gui/ModelVariablesTableModel.cpp | 8 +++- fmusim-gui/ModelVariablesTreeModel.cpp | 54 ++++++++++++++----------- fmusim/FMI1CSSimulation.c | 8 +++- fmusim/FMI1CSSimulation.h | 2 +- fmusim/FMI2CSSimulation.c | 14 ++++++- fmusim/FMI2CSSimulation.h | 2 +- fmusim/FMI2MESimulation.c | 12 +++++- fmusim/FMI2MESimulation.h | 2 +- fmusim/FMI3CSSimulation.c | 12 +++++- fmusim/FMI3CSSimulation.h | 6 +-- fmusim/FMI3MESimulation.c | 13 +++++- fmusim/FMI3MESimulation.h | 2 +- fmusim/FMISimulation.c | 50 ++++++++--------------- tests/test_fmusim.py | 1 - 15 files changed, 120 insertions(+), 74 deletions(-) diff --git a/fmusim-gui/MainWindow.cpp b/fmusim-gui/MainWindow.cpp index ec355023..bea27d9e 100644 --- a/fmusim-gui/MainWindow.cpp +++ b/fmusim-gui/MainWindow.cpp @@ -412,6 +412,7 @@ void MainWindow::loadFMU(const QString &filename) { ui->plotWebEngineView->load(QUrl("qrc:/plot.html")); // enable widgets + ui->dockWidget->show(); ui->showSideBarAction->setEnabled(true); ui->showSideBarAction->setChecked(true); @@ -642,6 +643,10 @@ void MainWindow::updatePlot() { return; } + std::sort(plotVariables.begin(), plotVariables.end(), [](const FMIModelVariable* a, const FMIModelVariable* b) { + return QString(a->name) > QString(b->name); + }); + const QString javaScript = PlotUtil::createPlot( simulationThread->settings->initialRecorder, simulationThread->settings->recorder, @@ -655,6 +660,9 @@ void MainWindow::updatePlot() { void MainWindow::unloadFMU() { + variablesListModel->setModelDescription(nullptr); + modelVariablesTreeModel->setModelDescription(nullptr); + if (modelDescription) { FMIFreeModelDescription(modelDescription); modelDescription = nullptr; diff --git a/fmusim-gui/ModelVariablesTableModel.cpp b/fmusim-gui/ModelVariablesTableModel.cpp index 49624745..9c2ae8cb 100644 --- a/fmusim-gui/ModelVariablesTableModel.cpp +++ b/fmusim-gui/ModelVariablesTableModel.cpp @@ -8,7 +8,13 @@ ModelVariablesTableModel::ModelVariablesTableModel(QObject *parent) } QModelIndex ModelVariablesTableModel::index(int row, int column, const QModelIndex &parent) const { - FMIModelVariable* variable = modelDescription->modelVariables[row]; + + FMIModelVariable* variable = nullptr; + + if (row >= 0 && row < modelDescription->nModelVariables) { + variable = modelDescription->modelVariables[row]; + } + return createIndex(row, column, variable); } diff --git a/fmusim-gui/ModelVariablesTreeModel.cpp b/fmusim-gui/ModelVariablesTreeModel.cpp index 5d4c39f4..dc0c2633 100644 --- a/fmusim-gui/ModelVariablesTreeModel.cpp +++ b/fmusim-gui/ModelVariablesTreeModel.cpp @@ -72,43 +72,49 @@ void ModelVariablesTreeModel::setModelDescription(const FMIModelDescription *mod beginResetModel(); - for (size_t i = 0; i < modelDescription->nModelVariables; i++) { + this->modelDescription = modelDescription; - const FMIModelVariable* variable = modelDescription->modelVariables[i]; + if (modelDescription) { - QString name = variable->name; - QString prefix; - QString suffix; + for (size_t i = 0; i < modelDescription->nModelVariables; i++) { - if (name.startsWith("der(") && name.endsWith(")")) { - prefix = "der("; - suffix = ")"; - name = name.sliced(4, name.length() - 5); - } + const FMIModelVariable* variable = modelDescription->modelVariables[i]; + + QString name = variable->name; + QString prefix; + QString suffix; + + if (name.startsWith("der(") && name.endsWith(")")) { + prefix = "der("; + suffix = ")"; + name = name.sliced(4, name.length() - 5); + } - const QStringList segments = QString(name).split('.'); + const QStringList segments = QString(name).split('.'); - TreeItem* parentItem = rootItem; + TreeItem* parentItem = rootItem; - for (const QString& segment : segments.sliced(0, segments.length() - 1)) { + for (const QString& segment : segments.sliced(0, segments.length() - 1)) { - TreeItem* p = parentItem->find(segment); + TreeItem* p = parentItem->find(segment); - if (!p) { - p = new TreeItem(); - p->name = segment; - parentItem->addChild(p); + if (!p) { + p = new TreeItem(); + p->name = segment; + parentItem->addChild(p); + } + + parentItem = p; } - parentItem = p; - } + TreeItem* treeItem = new TreeItem(); - TreeItem* treeItem = new TreeItem(); + treeItem->name = prefix + segments.last() + suffix; + treeItem->modelVariable = variable; - treeItem->name = prefix + segments.last() + suffix; - treeItem->modelVariable = variable; + parentItem->addChild(treeItem); + } - parentItem->addChild(treeItem); } endResetModel(); diff --git a/fmusim/FMI1CSSimulation.c b/fmusim/FMI1CSSimulation.c index fe808046..39157452 100644 --- a/fmusim/FMI1CSSimulation.c +++ b/fmusim/FMI1CSSimulation.c @@ -1,15 +1,21 @@ #include "FMI1.h" #include "FMI1CSSimulation.h" +#define FMI_PATH_MAX 4096 + #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI1CSSimulate(const char* fmuLocation, const FMISimulationSettings * s) { +FMIStatus FMI1CSSimulate(const FMISimulationSettings * s) { FMIStatus status = FMIOK; FMIInstance* S = s->S; + char fmuLocation[FMI_PATH_MAX] = ""; + + CALL(FMIPathToURI(s->unzipdir, fmuLocation, FMI_PATH_MAX)); + CALL(FMI1InstantiateSlave(S, s->modelDescription->coSimulation->modelIdentifier, // modelIdentifier s->modelDescription->instantiationToken, // fmuGUID diff --git a/fmusim/FMI1CSSimulation.h b/fmusim/FMI1CSSimulation.h index 8d273952..eabe94af 100644 --- a/fmusim/FMI1CSSimulation.h +++ b/fmusim/FMI1CSSimulation.h @@ -3,4 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI1CSSimulate(const char* fmuLocation, const FMISimulationSettings* s); +FMIStatus FMI1CSSimulate(const FMISimulationSettings* s); diff --git a/fmusim/FMI2CSSimulation.c b/fmusim/FMI2CSSimulation.c index c3957896..d76742ce 100644 --- a/fmusim/FMI2CSSimulation.c +++ b/fmusim/FMI2CSSimulation.c @@ -3,14 +3,26 @@ #include "FMI2CSSimulation.h" +#define FMI_PATH_MAX 4096 + #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI2CSSimulate(const char* resourceURI, const FMISimulationSettings* s) { +FMIStatus FMI2CSSimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; FMIInstance* S = s->S; + char resourceURI[FMI_PATH_MAX] = ""; + +#ifdef _WIN32 + snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); +#else + snprintf(fmuResourceLocation, FMI_PATH_MAX, "%s/resources/", s->unzipdir); +#endif + + CALL(FMIPathToURI(resourceURI, resourceURI, FMI_PATH_MAX)); + CALL(FMI2Instantiate(S, resourceURI, fmi2CoSimulation, diff --git a/fmusim/FMI2CSSimulation.h b/fmusim/FMI2CSSimulation.h index cf346a2b..e1db7ec2 100644 --- a/fmusim/FMI2CSSimulation.h +++ b/fmusim/FMI2CSSimulation.h @@ -3,4 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI2CSSimulate(const char* resourceURI, const FMISimulationSettings* s); +FMIStatus FMI2CSSimulate(const FMISimulationSettings* s); diff --git a/fmusim/FMI2MESimulation.c b/fmusim/FMI2MESimulation.c index dea4416a..7191344c 100644 --- a/fmusim/FMI2MESimulation.c +++ b/fmusim/FMI2MESimulation.c @@ -6,9 +6,11 @@ #include "FMI2MESimulation.h" +#define FMI_PATH_MAX 4096 + #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI2MESimulate(const char* resourceURI, const FMISimulationSettings* s) { +FMIStatus FMI2MESimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; @@ -16,6 +18,14 @@ FMIStatus FMI2MESimulate(const char* resourceURI, const FMISimulationSettings* s const bool needsCompletedIntegratorStep = s->modelDescription->modelExchange->needsCompletedIntegratorStep; + char resourceURI[FMI_PATH_MAX] = ""; + +#ifdef _WIN32 + snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); +#else + snprintf(fmuResourceLocation, FMI_PATH_MAX, "%s/resources/", s->unzipdir); +#endif + fmi2Real time; bool stateEvent = false; diff --git a/fmusim/FMI2MESimulation.h b/fmusim/FMI2MESimulation.h index 3f09fae1..eb36deac 100644 --- a/fmusim/FMI2MESimulation.h +++ b/fmusim/FMI2MESimulation.h @@ -3,4 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI2MESimulate(const char* resourceURI, const FMISimulationSettings* s); +FMIStatus FMI2MESimulate(const FMISimulationSettings* s); diff --git a/fmusim/FMI3CSSimulation.c b/fmusim/FMI3CSSimulation.c index 2a59a133..969d19ef 100644 --- a/fmusim/FMI3CSSimulation.c +++ b/fmusim/FMI3CSSimulation.c @@ -6,6 +6,8 @@ #include "FMI3CSSimulation.h" +#define FMI_PATH_MAX 4096 + #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) @@ -30,7 +32,7 @@ static void recordIntermediateValues( *earlyReturnRequested = fmi3False; } -FMIStatus FMI3CSSimulate(const char* resourcePath, const FMISimulationSettings* s) { +FMIStatus FMI3CSSimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; @@ -56,6 +58,14 @@ FMIStatus FMI3CSSimulate(const char* resourcePath, const FMISimulationSettings* size_t nRequiredIntermediateVariables = 0; fmi3IntermediateUpdateCallback intermediateUpdate = NULL; + char resourcePath[FMI_PATH_MAX] = ""; + +#ifdef _WIN32 + snprintf(resourcePath, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); +#else + snprintf(resourcePath, FMI_PATH_MAX, "%s/resources/", s->unzipdir); +#endif + if (s->recordIntermediateValues) { requiredIntermediateVariables = (fmi3ValueReference*)s->recorder->valueReferences; nRequiredIntermediateVariables = s->recorder->nVariables; diff --git a/fmusim/FMI3CSSimulation.h b/fmusim/FMI3CSSimulation.h index e1e587ad..ff037573 100644 --- a/fmusim/FMI3CSSimulation.h +++ b/fmusim/FMI3CSSimulation.h @@ -3,8 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI3CSSimulate( - //FMIInstance* S, - //const FMIModelDescription* modelDescription, - const char* resourcePath, - const FMISimulationSettings* settings); +FMIStatus FMI3CSSimulate(const FMISimulationSettings* settings); diff --git a/fmusim/FMI3MESimulation.c b/fmusim/FMI3MESimulation.c index a2664fef..45762981 100644 --- a/fmusim/FMI3MESimulation.c +++ b/fmusim/FMI3MESimulation.c @@ -6,10 +6,12 @@ #include "FMI3MESimulation.h" +#define FMI_PATH_MAX 4096 + #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings * s) { +FMIStatus FMI3MESimulate(const FMISimulationSettings * s) { FMIStatus status = FMIOK; @@ -40,6 +42,14 @@ FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings * FMISolver* solver = NULL; + char resourcePath[FMI_PATH_MAX] = ""; + +#ifdef _WIN32 + snprintf(resourcePath, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); +#else + snprintf(resourcePath, FMI_PATH_MAX, "%s/resources/", s->unzipdir); +#endif + CALL(FMI3InstantiateModelExchange(S, s->modelDescription->instantiationToken, resourcePath, @@ -92,6 +102,7 @@ FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings * CALL(FMI3EnterContinuousTimeMode(S)); } + CALL(FMIRecorderUpdateSizes(s->initialRecorder)); CALL(FMIRecorderUpdateSizes(s->recorder)); FMISolverParameters solverFunctions = { diff --git a/fmusim/FMI3MESimulation.h b/fmusim/FMI3MESimulation.h index 8f6a4cde..c3963467 100644 --- a/fmusim/FMI3MESimulation.h +++ b/fmusim/FMI3MESimulation.h @@ -3,4 +3,4 @@ #include "FMISimulation.h" -FMIStatus FMI3MESimulate(const char* resourcePath, const FMISimulationSettings* s); +FMIStatus FMI3MESimulate(const FMISimulationSettings* s); diff --git a/fmusim/FMISimulation.c b/fmusim/FMISimulation.c index bf69e6eb..98cb22fd 100644 --- a/fmusim/FMISimulation.c +++ b/fmusim/FMISimulation.c @@ -11,11 +11,9 @@ #include "FMI3MESimulation.h" #include "FMIUtil.h" -#define FMI_PATH_MAX 4096 #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) - FMIStatus FMIApplyStartValues(FMIInstance* S, const FMISimulationSettings* settings) { FMIStatus status = FMIOK; @@ -85,46 +83,30 @@ FMIStatus FMISimulate(const FMISimulationSettings* settings) { FMIStatus status = FMIOK; - const FMIModelDescription* modelDescription = settings->modelDescription; - const char* unzipdir = settings->unzipdir; - - char resourcePath[FMI_PATH_MAX] = ""; - -#ifdef _WIN32 - snprintf(resourcePath, FMI_PATH_MAX, "%s\\resources\\", unzipdir); -#else - snprintf(resourcePath, FMI_PATH_MAX, "%s/resources/", unzipdir); -#endif + const bool cs = settings->interfaceType == FMICoSimulation; - if (modelDescription->fmiMajorVersion == FMIMajorVersion1) { - - if (settings->interfaceType == FMICoSimulation) { - char fmuLocation[FMI_PATH_MAX] = ""; - CALL(FMIPathToURI(unzipdir, fmuLocation, FMI_PATH_MAX)); - CALL(FMI1CSSimulate(fmuLocation, settings)); + switch (settings->modelDescription->fmiMajorVersion) { + case FMIMajorVersion1: + if (cs) { + CALL(FMI1CSSimulate(settings)); } else { CALL(FMI1MESimulate(settings)); } - - } else if (modelDescription->fmiMajorVersion == FMIMajorVersion2) { - - char resourceURI[FMI_PATH_MAX] = ""; - CALL(FMIPathToURI(resourcePath, resourceURI, FMI_PATH_MAX)); - - if (settings->interfaceType == FMICoSimulation) { - CALL(FMI2CSSimulate(resourceURI, settings)); + break; + case FMIMajorVersion2: + if (cs) { + CALL(FMI2CSSimulate(settings)); } else { - CALL(FMI2MESimulate(resourceURI, settings)); + CALL(FMI2MESimulate(settings)); } - - } else { - - if (settings->interfaceType == FMICoSimulation) { - CALL(FMI3CSSimulate(resourcePath, settings)); + break; + case FMIMajorVersion3: + if (cs) { + CALL(FMI3CSSimulate(settings)); } else { - CALL(FMI3MESimulate(resourcePath, settings)); + CALL(FMI3MESimulate(settings)); } - + break; } TERMINATE: diff --git a/tests/test_fmusim.py b/tests/test_fmusim.py index bea96862..b1be1aa9 100644 --- a/tests/test_fmusim.py +++ b/tests/test_fmusim.py @@ -1,5 +1,4 @@ import os -import subprocess from itertools import product from pathlib import Path from subprocess import check_call From ce9e8098d36ee6c6b3acb9d44bba782266953719 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 15:20:46 +0200 Subject: [PATCH 5/9] Clean up --- fmusim/FMI1CSSimulation.c | 2 +- fmusim/FMI3MESimulation.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fmusim/FMI1CSSimulation.c b/fmusim/FMI1CSSimulation.c index 39157452..9c4a3f30 100644 --- a/fmusim/FMI1CSSimulation.c +++ b/fmusim/FMI1CSSimulation.c @@ -6,7 +6,7 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI1CSSimulate(const FMISimulationSettings * s) { +FMIStatus FMI1CSSimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; diff --git a/fmusim/FMI3MESimulation.c b/fmusim/FMI3MESimulation.c index 45762981..293cb6ce 100644 --- a/fmusim/FMI3MESimulation.c +++ b/fmusim/FMI3MESimulation.c @@ -11,7 +11,7 @@ #define CALL(f) do { status = f; if (status > FMIOK) goto TERMINATE; } while (0) -FMIStatus FMI3MESimulate(const FMISimulationSettings * s) { +FMIStatus FMI3MESimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; From faf5a31da62b57df2efe94681e6b9a9d83a7ae9d Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 15:30:29 +0200 Subject: [PATCH 6/9] Fix variable name on Linux --- fmusim/FMI2CSSimulation.c | 2 +- fmusim/FMI2MESimulation.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fmusim/FMI2CSSimulation.c b/fmusim/FMI2CSSimulation.c index d76742ce..a7516fbd 100644 --- a/fmusim/FMI2CSSimulation.c +++ b/fmusim/FMI2CSSimulation.c @@ -18,7 +18,7 @@ FMIStatus FMI2CSSimulate(const FMISimulationSettings* s) { #ifdef _WIN32 snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); #else - snprintf(fmuResourceLocation, FMI_PATH_MAX, "%s/resources/", s->unzipdir); + snprintf(resourceURI, FMI_PATH_MAX, "%s/resources/", s->unzipdir); #endif CALL(FMIPathToURI(resourceURI, resourceURI, FMI_PATH_MAX)); diff --git a/fmusim/FMI2MESimulation.c b/fmusim/FMI2MESimulation.c index 7191344c..1f7bf29d 100644 --- a/fmusim/FMI2MESimulation.c +++ b/fmusim/FMI2MESimulation.c @@ -23,7 +23,7 @@ FMIStatus FMI2MESimulate(const FMISimulationSettings* s) { #ifdef _WIN32 snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); #else - snprintf(fmuResourceLocation, FMI_PATH_MAX, "%s/resources/", s->unzipdir); + snprintf(resourceURI, FMI_PATH_MAX, "%s/resources/", s->unzipdir); #endif fmi2Real time; From 674667c7ef1ff8a1d58c86365b780928cf1e7961 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Mon, 19 Aug 2024 16:02:15 +0200 Subject: [PATCH 7/9] Fix resourceURI for FMI 2.0 ME --- fmusim/FMI2MESimulation.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fmusim/FMI2MESimulation.c b/fmusim/FMI2MESimulation.c index 1f7bf29d..fe7c3f26 100644 --- a/fmusim/FMI2MESimulation.c +++ b/fmusim/FMI2MESimulation.c @@ -14,10 +14,6 @@ FMIStatus FMI2MESimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; - FMIInstance* S = s->S; - - const bool needsCompletedIntegratorStep = s->modelDescription->modelExchange->needsCompletedIntegratorStep; - char resourceURI[FMI_PATH_MAX] = ""; #ifdef _WIN32 @@ -26,6 +22,12 @@ FMIStatus FMI2MESimulate(const FMISimulationSettings* s) { snprintf(resourceURI, FMI_PATH_MAX, "%s/resources/", s->unzipdir); #endif + CALL(FMIPathToURI(resourceURI, resourceURI, FMI_PATH_MAX)); + + FMIInstance* S = s->S; + + const bool needsCompletedIntegratorStep = s->modelDescription->modelExchange->needsCompletedIntegratorStep; + fmi2Real time; bool stateEvent = false; From 9b95f89965103e17fd349c76c03bbce9e71e2ac2 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Tue, 20 Aug 2024 09:47:04 +0200 Subject: [PATCH 8/9] Free initialRecorder --- fmusim-gui/SimulationThread.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fmusim-gui/SimulationThread.cpp b/fmusim-gui/SimulationThread.cpp index 4f816455..326de1a3 100644 --- a/fmusim-gui/SimulationThread.cpp +++ b/fmusim-gui/SimulationThread.cpp @@ -1,6 +1,5 @@ #include #include "SimulationThread.h" -#include SimulationThread* SimulationThread::currentSimulationThread = nullptr; @@ -17,6 +16,10 @@ SimulationThread::~SimulationThread() FMIFreeInput(settings->input); } + if (settings->initialRecorder) { + FMIFreeRecorder(settings->initialRecorder); + } + if (settings->recorder) { FMIFreeRecorder(settings->recorder); } From a37a15e87282ba345d56c83c5108d3c757b7f1d0 Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Tue, 20 Aug 2024 10:06:46 +0200 Subject: [PATCH 9/9] Fix resourceURI for FMI 2.0 --- fmusim/FMI2CSSimulation.c | 11 ++++++----- fmusim/FMI2MESimulation.c | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/fmusim/FMI2CSSimulation.c b/fmusim/FMI2CSSimulation.c index a7516fbd..3eafbce7 100644 --- a/fmusim/FMI2CSSimulation.c +++ b/fmusim/FMI2CSSimulation.c @@ -11,17 +11,18 @@ FMIStatus FMI2CSSimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; - FMIInstance* S = s->S; - + char resourcePath[FMI_PATH_MAX] = ""; char resourceURI[FMI_PATH_MAX] = ""; #ifdef _WIN32 - snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); + snprintf(resourcePath, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); #else - snprintf(resourceURI, FMI_PATH_MAX, "%s/resources/", s->unzipdir); + snprintf(resourcePath, FMI_PATH_MAX, "%s/resources/", s->unzipdir); #endif - CALL(FMIPathToURI(resourceURI, resourceURI, FMI_PATH_MAX)); + CALL(FMIPathToURI(resourcePath, resourceURI, FMI_PATH_MAX)); + + FMIInstance* S = s->S; CALL(FMI2Instantiate(S, resourceURI, diff --git a/fmusim/FMI2MESimulation.c b/fmusim/FMI2MESimulation.c index fe7c3f26..86a5747c 100644 --- a/fmusim/FMI2MESimulation.c +++ b/fmusim/FMI2MESimulation.c @@ -14,15 +14,16 @@ FMIStatus FMI2MESimulate(const FMISimulationSettings* s) { FMIStatus status = FMIOK; + char resourcePath[FMI_PATH_MAX] = ""; char resourceURI[FMI_PATH_MAX] = ""; #ifdef _WIN32 - snprintf(resourceURI, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); + snprintf(resourcePath, FMI_PATH_MAX, "%s\\resources\\", s->unzipdir); #else - snprintf(resourceURI, FMI_PATH_MAX, "%s/resources/", s->unzipdir); + snprintf(resourcePath, FMI_PATH_MAX, "%s/resources/", s->unzipdir); #endif - CALL(FMIPathToURI(resourceURI, resourceURI, FMI_PATH_MAX)); + CALL(FMIPathToURI(resourcePath, resourceURI, FMI_PATH_MAX)); FMIInstance* S = s->S;