Skip to content

Commit 0ae06cd

Browse files
committed
updates wrt. state
1 parent 6f8408c commit 0ae06cd

7 files changed

Lines changed: 356 additions & 35 deletions

File tree

export/include/fmu4cpp/fmu_base.hpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <vector>
1111

1212
#include "fmu_base.hpp"
13+
#include "fmu_except.hpp"
1314
#include "fmu_variable.hpp"
1415
#include "logger.hpp"
1516
#include "model_info.hpp"
@@ -203,7 +204,7 @@ namespace fmu4cpp {
203204
}
204205
}
205206

206-
void set_binary(const unsigned int vr[], size_t nvr, const size_t valueSizes[], const uint8_t* const value[]) {
207+
void set_binary(const unsigned int vr[], size_t nvr, const size_t valueSizes[], const uint8_t *const value[]) {
207208
#ifdef FMI2
208209
static_assert("set_binary not available for FMI2");
209210
#endif
@@ -228,18 +229,27 @@ namespace fmu4cpp {
228229
}
229230

230231
virtual void *getFMUState() {
231-
log(fmiError, "getFMUState not implemented");
232-
return nullptr;
232+
throw fatal_error("getFMUState not implemented");
233233
}
234234

235-
virtual bool setFmuState(void *state) {
236-
log(fmiError, "getFMUState not implemented");
237-
return false;
235+
virtual void setFmuState(void *state) {
236+
throw fatal_error("getFMUState not implemented");
238237
}
239238

240-
virtual bool freeFmuState(void **state) {
241-
log(fmiError, "getFMUState not implemented");
242-
return false;
239+
virtual void freeFmuState(void **state) {
240+
throw fatal_error("getFMUState not implemented");
241+
}
242+
243+
virtual void serializedFMUStateSize(void *state, size_t &size) {
244+
throw fatal_error("serializedFMUStateSize not implemented");
245+
}
246+
247+
virtual void serializeFMUState(void *state, std::vector<uint8_t> &serializedState) {
248+
throw fatal_error("serializeFMUState not implemented");
249+
}
250+
251+
virtual void deserializeFMUState(const std::vector<uint8_t> &serializedState, void **state) {
252+
throw fatal_error("deserializeFMUState not implemented");
243253
}
244254

245255
[[nodiscard]] std::vector<unsigned int> get_value_refs() const;
@@ -315,7 +325,6 @@ namespace fmu4cpp {
315325
std::vector<BinaryVariable> binary_;
316326
std::vector<std::string> binaryBuffer_;
317327
std::unordered_map<unsigned int, size_t> vrToBinaryIndices_;
318-
319328
};
320329

321330

export/src/fmu4cpp/fmi2/fmi2.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const char *fmi2GetVersion(void) {
7676
return "2.0";
7777
}
7878

79-
FMI2_Export void write_description(const char *location, const char* modelIdentifier) {
79+
FMI2_Export void write_description(const char *location, const char *modelIdentifier) {
8080
const auto instance = fmu4cpp::createInstance({});
8181
const auto xml = instance->make_description();
8282
std::ofstream of(location);
@@ -475,33 +475,54 @@ fmi2Status fmi2GetDirectionalDerivative(fmi2Component,
475475
fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *state) {
476476
const auto component = static_cast<Fmi2Component *>(c);
477477

478-
if (auto s = component->slave->getFMUState()) {
478+
try {
479+
480+
const auto s = component->slave->getFMUState();
479481
*state = s;
480482
return fmi2OK;
481-
}
482483

483-
return fmi2Error;
484+
} catch (const fmu4cpp::fatal_error &ex) {
485+
component->logger->log(fmiFatal, ex.what());
486+
return fmi2Fatal;
487+
} catch (const std::exception &ex) {
488+
component->logger->log(fmiError, ex.what());
489+
return fmi2Error;
490+
}
484491
}
485492

486493
fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate state) {
487494
const auto component = static_cast<Fmi2Component *>(c);
488495

489-
if (component->slave->setFmuState(state)) {
496+
try {
497+
498+
component->slave->setFmuState(state);
490499
return fmi2OK;
491-
}
492500

493-
return fmi2Error;
501+
} catch (const fmu4cpp::fatal_error &ex) {
502+
component->logger->log(fmiFatal, ex.what());
503+
return fmi2Fatal;
504+
} catch (const std::exception &ex) {
505+
component->logger->log(fmiError, ex.what());
506+
return fmi2Error;
507+
}
494508
}
495509

496510

497511
fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *state) {
498512
const auto component = static_cast<Fmi2Component *>(c);
499513

500-
if (component->slave->freeFmuState(state)) {
514+
try {
515+
516+
component->slave->freeFmuState(state);
501517
return fmi2OK;
502-
}
503518

504-
return fmi2Error;
519+
} catch (const fmu4cpp::fatal_error &ex) {
520+
component->logger->log(fmiFatal, ex.what());
521+
return fmi2Fatal;
522+
} catch (const std::exception &ex) {
523+
component->logger->log(fmiError, ex.what());
524+
return fmi2Error;
525+
}
505526
}
506527

507528
fmi2Status fmi2SerializedFMUstateSize(fmi2Component, fmi2FMUstate, size_t *) {

export/src/fmu4cpp/fmi3/fmi3.cpp

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -602,48 +602,122 @@ fmi3Status fmi3GetDirectionalDerivative(fmi3Instance instance,
602602
fmi3Status fmi3GetFMUState(fmi3Instance c, fmi3FMUState *state) {
603603
const auto component = static_cast<Fmi3Component *>(c);
604604

605-
if (auto s = component->slave->getFMUState()) {
605+
try {
606+
607+
const auto s = component->slave->getFMUState();
606608
*state = s;
607609
return fmi3OK;
608-
}
609610

610-
return fmi3Error;
611+
} catch (const fmu4cpp::fatal_error &ex) {
612+
component->logger->log(fmiFatal, ex.what());
613+
component->state = Fmi3Component::State::Invalid;
614+
return fmi3Fatal;
615+
} catch (const std::exception &ex) {
616+
component->logger->log(fmiError, ex.what());
617+
component->state = Fmi3Component::State::Terminated;
618+
return fmi3Error;
619+
}
611620
}
612621

613622
fmi3Status fmi3SetFMUState(fmi3Instance c, fmi3FMUState state) {
614623
const auto component = static_cast<Fmi3Component *>(c);
615624

616-
if (component->slave->setFmuState(state)) {
625+
try {
626+
627+
component->slave->setFmuState(state);
617628
return fmi3OK;
618-
}
619629

620-
return fmi3Error;
630+
} catch (const fmu4cpp::fatal_error &ex) {
631+
component->logger->log(fmiFatal, ex.what());
632+
component->state = Fmi3Component::State::Invalid;
633+
return fmi3Fatal;
634+
} catch (const std::exception &ex) {
635+
component->logger->log(fmiError, ex.what());
636+
component->state = Fmi3Component::State::Terminated;
637+
return fmi3Error;
638+
}
621639
}
622640

623641

624642
fmi3Status fmi3FreeFMUState(fmi3Instance c, fmi3FMUState *state) {
625643
const auto component = static_cast<Fmi3Component *>(c);
626644

627-
if (component->slave->freeFmuState(state)) {
645+
try {
646+
647+
component->slave->freeFmuState(state);
628648
return fmi3OK;
629-
}
630649

631-
return fmi3Error;
650+
} catch (const fmu4cpp::fatal_error &ex) {
651+
component->logger->log(fmiFatal, ex.what());
652+
component->state = Fmi3Component::State::Invalid;
653+
return fmi3Fatal;
654+
} catch (const std::exception &ex) {
655+
component->logger->log(fmiError, ex.what());
656+
component->state = Fmi3Component::State::Terminated;
657+
return fmi3Error;
658+
}
632659
}
633660

634-
fmi3Status fmi3SerializedFMUStateSize(fmi3Instance, fmi3FMUState, size_t *) {
661+
fmi3Status fmi3SerializedFMUStateSize(fmi3Instance c, fmi3FMUState state, size_t *size) {
662+
const auto component = static_cast<Fmi3Component *>(c);
635663

636-
return fmi3Error;
664+
try {
665+
666+
component->slave->serializedFMUStateSize(state, *size);
667+
return fmi3OK;
668+
669+
} catch (const fmu4cpp::fatal_error &ex) {
670+
component->logger->log(fmiFatal, ex.what());
671+
component->state = Fmi3Component::State::Invalid;
672+
return fmi3Fatal;
673+
} catch (const std::exception &ex) {
674+
component->logger->log(fmiError, ex.what());
675+
component->state = Fmi3Component::State::Terminated;
676+
return fmi3Error;
677+
}
637678
}
638679

639-
fmi3Status fmi3SerializeFMUState(fmi3Instance, fmi3FMUState, fmi3Byte[], size_t) {
680+
fmi3Status fmi3SerializeFMUState(fmi3Instance c, fmi3FMUState state, fmi3Byte data[], size_t size) {
640681

641-
return fmi3Error;
682+
const auto component = static_cast<Fmi3Component *>(c);
683+
684+
try {
685+
686+
std::vector<uint8_t> serializedState(size);
687+
component->slave->serializeFMUState(state, serializedState);
688+
std::memcpy(data, serializedState.data(), size);
689+
return fmi3OK;
690+
691+
} catch (const fmu4cpp::fatal_error &ex) {
692+
component->logger->log(fmiFatal, ex.what());
693+
component->state = Fmi3Component::State::Invalid;
694+
return fmi3Fatal;
695+
} catch (const std::exception &ex) {
696+
component->logger->log(fmiError, ex.what());
697+
component->state = Fmi3Component::State::Terminated;
698+
return fmi3Error;
699+
}
642700
}
643701

644-
fmi3Status fmi3DeserializeFMUState(fmi3Instance, const fmi3Byte[], size_t, fmi3FMUState *) {
702+
fmi3Status fmi3DeserializeFMUState(fmi3Instance c, const fmi3Byte data[], size_t size, fmi3FMUState *state) {
645703

646-
return fmi3Error;
704+
const auto component = static_cast<Fmi3Component *>(c);
705+
706+
try {
707+
708+
std::vector serializedState(data, data + size);
709+
component->slave->deserializeFMUState(serializedState, state);
710+
return fmi3OK;
711+
712+
} catch (const fmu4cpp::fatal_error &ex) {
713+
component->logger->log(fmiFatal, ex.what());
714+
component->state = Fmi3Component::State::Invalid;
715+
return fmi3Fatal;
716+
} catch (const std::exception &ex) {
717+
component->logger->log(fmiError, ex.what());
718+
component->state = Fmi3Component::State::Terminated;
719+
return fmi3Error;
720+
}
647721
}
648722

649723
fmi3Status fmi3GetClock(fmi3Instance instance,

export/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function(make_test fmi_version modelIdentifier sources)
1111
)
1212
target_include_directories(${target_name}
1313
PRIVATE
14+
"${PROJECT_SOURCE_DIR}/export/tests/models"
1415
"${PROJECT_SOURCE_DIR}/export/tests/external"
1516
"${PROJECT_SOURCE_DIR}/export/include"
1617
"${PROJECT_SOURCE_DIR}/export/src"

export/tests/fmi3/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
make_test("fmi3" array_test array_test.cpp)
33
make_test("fmi3" identity_test identity_test.cpp)
44
make_test("fmi3" binary_test binary_test.cpp)
5+
make_test("fmi3" bouncing_ball_test bouncing_ball_test.cpp)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
#include <catch2/catch_approx.hpp>
3+
#include <catch2/catch_test_macros.hpp>
4+
5+
#include "fmi3/fmi3Functions.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 = fmi3InstantiateCoSimulation("array", guid.c_str(), "", false, false, false, false, nullptr, 0, nullptr, nullptr, nullptr);
21+
REQUIRE(c);
22+
23+
REQUIRE(fmi3EnterInitializationMode(c, false, 0, 0, false, 0) == fmi3OK);
24+
REQUIRE(fmi3ExitInitializationMode(c) == fmi3OK);
25+
26+
double t = 0;
27+
double dt = 0.1;
28+
29+
bool eventhandlingNeeded;
30+
bool terminateSimulation;
31+
bool earlyReturn;
32+
double lastSucessfulTime;
33+
REQUIRE(fmi3DoStep(c, t, dt, true, &eventhandlingNeeded, &terminateSimulation, &earlyReturn, &lastSucessfulTime) == fmi3OK);
34+
t += dt;
35+
36+
const auto heightVr = model.get_real_variable("height")->value_reference();
37+
38+
double height;
39+
REQUIRE(fmi3GetFloat64(c, &heightVr, 1, &height, 1) == fmi3OK);
40+
REQUIRE(height < 10.0);
41+
42+
double heightState = height;
43+
44+
fmi3FMUState state;
45+
REQUIRE(fmi3GetFMUState(c, &state) == fmi3OK);
46+
47+
REQUIRE(fmi3DoStep(c, t, dt, true, &eventhandlingNeeded, &terminateSimulation, &earlyReturn, &lastSucessfulTime) == fmi3OK);
48+
t += dt;
49+
50+
REQUIRE(fmi3GetFloat64(c, &heightVr, 1, &height, 1) == fmi3OK);
51+
CHECK(height != Catch::Approx(heightState));
52+
53+
REQUIRE(fmi3SetFMUState(c, state) == fmi3OK);
54+
REQUIRE(fmi3GetFloat64(c, &heightVr, 1, &height, 1) == fmi3OK);
55+
CHECK(height == Catch::Approx(heightState));
56+
57+
58+
size_t serializedSize;
59+
fmi3SerializedFMUStateSize(c, state, &serializedSize);
60+
CHECK(serializedSize > 0);
61+
62+
std::vector<uint8_t> serializedData(serializedSize);
63+
fmi3SerializeFMUState(c, state, serializedData.data(), serializedSize);
64+
fmi3DeserializeFMUState(c, serializedData.data(), serializedSize, &state);
65+
66+
REQUIRE(fmi3DoStep(c, t, dt, true, &eventhandlingNeeded, &terminateSimulation, &earlyReturn, &lastSucessfulTime) == fmi3OK);
67+
68+
REQUIRE(fmi3GetFloat64(c, &heightVr, 1, &height, 1) == fmi3OK);
69+
CHECK(height != Catch::Approx(heightState));
70+
71+
REQUIRE(fmi3SetFMUState(c, state) == fmi3OK);
72+
REQUIRE(fmi3GetFloat64(c, &heightVr, 1, &height, 1) == fmi3OK);
73+
CHECK(height == Catch::Approx(heightState));
74+
75+
76+
REQUIRE(fmi3FreeFMUState(c, &state) == fmi3OK);
77+
}

0 commit comments

Comments
 (0)