Skip to content

Commit 9ca5b5a

Browse files
committed
fmi2 state and test
1 parent c6b0fe1 commit 9ca5b5a

5 files changed

Lines changed: 145 additions & 9 deletions

File tree

export/src/fmu4cpp/fmi2/fmi2.cpp

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ fmi2Status fmi2GetDirectionalDerivative(fmi2Component,
473473

474474

475475
fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *state) {
476+
476477
const auto component = static_cast<Fmi2Component *>(c);
477478

478479
try {
@@ -491,6 +492,7 @@ fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *state) {
491492
}
492493

493494
fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate state) {
495+
494496
const auto component = static_cast<Fmi2Component *>(c);
495497

496498
try {
@@ -509,6 +511,11 @@ fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate state) {
509511

510512

511513
fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *state) {
514+
515+
if (state == nullptr || *state == nullptr) {
516+
return fmi2OK;
517+
}
518+
512519
const auto component = static_cast<Fmi2Component *>(c);
513520

514521
try {
@@ -525,23 +532,68 @@ fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *state) {
525532
}
526533
}
527534

528-
fmi2Status fmi2SerializedFMUstateSize(fmi2Component, fmi2FMUstate, size_t *) {
535+
fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate state, size_t *size) {
529536

530-
return fmi2Error;
537+
const auto component = static_cast<Fmi2Component *>(c);
538+
539+
try {
540+
541+
component->slave->serializedFMUStateSize(state, *size);
542+
return fmi2OK;
543+
544+
} catch (const fmu4cpp::fatal_error &ex) {
545+
component->logger->log(fmiFatal, ex.what());
546+
return fmi2Fatal;
547+
} catch (const std::exception &ex) {
548+
component->logger->log(fmiError, ex.what());
549+
return fmi2Error;
550+
}
531551
}
532552

533-
fmi2Status fmi2SerializeFMUstate(fmi2Component, fmi2FMUstate, fmi2Byte[], size_t) {
553+
fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate state, fmi2Byte data[], size_t size) {
534554

535-
return fmi2Error;
555+
const auto component = static_cast<Fmi2Component *>(c);
556+
557+
try {
558+
559+
std::vector<uint8_t> serializedState(size);
560+
component->slave->serializeFMUState(state, serializedState);
561+
std::memcpy(data, serializedState.data(), size);
562+
return fmi2OK;
563+
564+
} catch (const fmu4cpp::fatal_error &ex) {
565+
component->logger->log(fmiFatal, ex.what());
566+
return fmi2Fatal;
567+
} catch (const std::exception &ex) {
568+
component->logger->log(fmiError, ex.what());
569+
return fmi2Error;
570+
}
536571
}
537572

538-
fmi2Status fmi2DeSerializeFMUstate(fmi2Component, const fmi2Byte[], size_t, fmi2FMUstate *) {
573+
fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte data[], size_t size, fmi2FMUstate *state) {
539574

540-
return fmi2Error;
575+
const auto component = static_cast<Fmi2Component *>(c);
576+
577+
try {
578+
579+
std::vector<uint8_t> serializedState(data, data + size);
580+
component->slave->deserializeFMUState(serializedState, state);
581+
return fmi2OK;
582+
583+
} catch (const fmu4cpp::fatal_error &ex) {
584+
component->logger->log(fmiFatal, ex.what());
585+
return fmi2Fatal;
586+
} catch (const std::exception &ex) {
587+
component->logger->log(fmiError, ex.what());
588+
return fmi2Error;
589+
}
541590
}
542591

543592
void fmi2FreeInstance(fmi2Component c) {
544-
const auto component = static_cast<Fmi2Component *>(c);
545-
delete component;
593+
if (c) {
594+
const auto component = static_cast<Fmi2Component *>(c);
595+
delete component;
596+
c = nullptr;
597+
}
546598
}
547599
}

export/src/fmu4cpp/fmi3/fmi3.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,11 @@ fmi3Status fmi3SetFMUState(fmi3Instance c, fmi3FMUState state) {
641641

642642

643643
fmi3Status fmi3FreeFMUState(fmi3Instance c, fmi3FMUState *state) {
644+
645+
if (state == nullptr || *state == nullptr) {
646+
return fmi3OK;
647+
}
648+
644649
const auto component = static_cast<Fmi3Component *>(c);
645650

646651
try {
@@ -660,6 +665,7 @@ fmi3Status fmi3FreeFMUState(fmi3Instance c, fmi3FMUState *state) {
660665
}
661666

662667
fmi3Status fmi3SerializedFMUStateSize(fmi3Instance c, fmi3FMUState state, size_t *size) {
668+
663669
const auto component = static_cast<Fmi3Component *>(c);
664670

665671
try {
@@ -939,6 +945,7 @@ void fmi3FreeInstance(fmi3Instance c) {
939945
const auto component = static_cast<Fmi3Component *>(c);
940946
component->state = Fmi3Component::State::Invalid;
941947
delete component;
948+
c = nullptr;
942949
}
943950
}
944951
}

export/tests/fmi2/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11

22
make_test("fmi2" array_test array_test.cpp)
33
make_test("fmi2" identity_test identity_test.cpp)
4+
make_test("fmi2" bouncing_ball_test bouncing_ball_test.cpp)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
#include <catch2/catch_approx.hpp>
3+
#include <catch2/catch_test_macros.hpp>
4+
5+
#include "fmi2/fmi2Functions.h"
6+
7+
#include "BouncingBall.hpp"
8+
9+
10+
std::string fmu4cpp::model_identifier() {
11+
return "bouncing_ball";
12+
}
13+
14+
15+
TEST_CASE("BouncingBall_test") {
16+
17+
BouncingBall model({});
18+
const auto guid = model.guid();
19+
20+
auto c = fmi2Instantiate("bouncing_ball", fmi2CoSimulation, guid.c_str(), "", nullptr, false, false);
21+
REQUIRE(c);
22+
23+
REQUIRE(fmi2SetupExperiment(c, fmi2False, 0, 0, fmi2False, 0) == fmi2OK);
24+
REQUIRE(fmi2EnterInitializationMode(c) == fmi2OK);
25+
REQUIRE(fmi2ExitInitializationMode(c) == fmi2OK);
26+
27+
double t = 0;
28+
double dt = 0.1;
29+
30+
REQUIRE(fmi2DoStep(c, t, dt, true) == fmi2OK);
31+
t += dt;
32+
33+
const auto heightVr = model.get_real_variable("height")->value_reference();
34+
35+
double height;
36+
REQUIRE(fmi2GetReal(c, &heightVr, 1, &height) == fmi2OK);
37+
REQUIRE(height < 10.0);
38+
39+
double heightState = height;
40+
41+
fmi2FMUstate state;
42+
REQUIRE(fmi2GetFMUstate(c, &state) == fmi2OK);
43+
44+
REQUIRE(fmi2DoStep(c, t, dt, true) == fmi2OK);
45+
t += dt;
46+
47+
REQUIRE(fmi2GetReal(c, &heightVr, 1, &height) == fmi2OK);
48+
CHECK(height != Catch::Approx(heightState));
49+
50+
REQUIRE(fmi2SetFMUstate(c, state) == fmi2OK);
51+
REQUIRE(fmi2GetReal(c, &heightVr, 1, &height) == fmi2OK);
52+
CHECK(height == Catch::Approx(heightState));
53+
54+
55+
size_t serializedSize;
56+
fmi2SerializedFMUstateSize(c, state, &serializedSize);
57+
CHECK(serializedSize > 0);
58+
59+
std::vector<char> serializedData(serializedSize);
60+
fmi2SerializeFMUstate(c, state, serializedData.data(), serializedSize);
61+
fmi2DeSerializeFMUstate(c, serializedData.data(), serializedSize, &state);
62+
63+
REQUIRE(fmi2DoStep(c, t, dt, true) == fmi2OK);
64+
65+
REQUIRE(fmi2GetReal(c, &heightVr, 1, &height) == fmi2OK);
66+
CHECK(height != Catch::Approx(heightState));
67+
68+
REQUIRE(fmi2SetFMUstate(c, state) == fmi2OK);
69+
REQUIRE(fmi2GetReal(c, &heightVr, 1, &height) == fmi2OK);
70+
CHECK(height == Catch::Approx(heightState));
71+
72+
73+
REQUIRE(fmi2FreeFMUstate(c, &state) == fmi2OK);
74+
REQUIRE(state == nullptr);
75+
}

export/tests/fmi3/bouncing_ball_test.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ TEST_CASE("BouncingBall_test") {
1717
BouncingBall model({});
1818
const auto guid = model.guid();
1919

20-
auto c = fmi3InstantiateCoSimulation("array", guid.c_str(), "", false, false, false, false, nullptr, 0, nullptr, nullptr, nullptr);
20+
auto c = fmi3InstantiateCoSimulation("bouncing_ball", guid.c_str(), "", false, false, false, false, nullptr, 0, nullptr, nullptr, nullptr);
2121
REQUIRE(c);
2222

2323
REQUIRE(fmi3EnterInitializationMode(c, false, 0, 0, false, 0) == fmi3OK);
@@ -74,4 +74,5 @@ TEST_CASE("BouncingBall_test") {
7474

7575

7676
REQUIRE(fmi3FreeFMUState(c, &state) == fmi3OK);
77+
REQUIRE(state == nullptr);
7778
}

0 commit comments

Comments
 (0)