1313namespace {
1414
1515
16- fmiStatus toCommonStatusFromFmi3 (fmi3Status status) {
17- switch (status) {
18- case fmi3OK:
19- return fmiOK;
20- case fmi3Warning:
21- return fmiWarning;
22- case fmi3Discard:
23- return fmiDiscard;
24- case fmi3Error:
25- return fmiError;
26- case fmi3Fatal:
27- return fmiFatal;
28- default :
29- return fmiStatusUnknown;
30- }
31- }
32-
3316 fmi3Status toFmi3StatusFromCommon (fmiStatus status) {
3417 switch (status) {
3518 case fmiOK:
@@ -66,13 +49,23 @@ namespace {
6649 // A struct that holds all the data for one model instance.
6750 struct Fmi3Component {
6851
52+ enum class State {
53+ Instantiated = 1 << 0 ,
54+ InitializationMode = 1 << 1 ,
55+ StepMode = 1 << 2 ,
56+ Terminated = 1 << 3 ,
57+ Invalid = 1 << 4
58+ };
59+
6960 Fmi3Component (std::unique_ptr<fmu4cpp::fmu_base> slave, fmi3InstanceEnvironment env, fmi3LogMessageCallback logCallback)
70- : slave(std::move(slave)),
61+ : state(State::Instantiated),
62+ slave (std::move(slave)),
7163 logger(std::make_unique<fmi3Logger>(env, logCallback, this ->slave->instanceName ())) {
7264
7365 this ->slave ->__set_logger (logger.get ());
7466 }
7567
68+ State state;
7669 std::unique_ptr<fmu4cpp::fmu_base> slave;
7770 std::unique_ptr<fmu4cpp::logger> logger;
7871 };
@@ -87,7 +80,7 @@ namespace {
8780 FMU_TYPE (type) values[], \
8881 size_t nValues) { \
8982 const auto component = static_cast <Fmi3Component *>(c); \
90- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error) , std::string (" Unsupported function fmi3Get" ) + #type); \
83+ component->logger ->log (fmiError , std::string (" Unsupported function fmi3Get" ) + #type); \
9184 return fmi3Error; \
9285 }
9386
@@ -99,7 +92,7 @@ namespace {
9992 const FMU_TYPE (type) values[], \
10093 size_t nValues) { \
10194 const auto component = static_cast <Fmi3Component *>(c); \
102- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error) , std::string (" Unsupported function fmi3Set" ) + #type); \
95+ component->logger ->log (fmiError , std::string (" Unsupported function fmi3Set" ) + #type); \
10396 return fmi3Error; \
10497 }
10598
@@ -191,10 +184,18 @@ fmi3Instance fmi3InstantiateCoSimulation(
191184 return nullptr ;
192185 }
193186
194- auto c = std::make_unique<Fmi3Component>(std::move (slave), instanceEnvironment, logMessage);
195- c->logger ->setDebugLogging (loggingOn);
187+ try {
188+ auto c = std::make_unique<Fmi3Component>(std::move (slave), instanceEnvironment, logMessage);
189+ c->logger ->setDebugLogging (loggingOn);
190+
191+ return c.release ();
192+ } catch (const std::exception &e) {
196193
197- return c.release ();
194+ fmi3Logger l (instanceEnvironment, logMessage, instanceName);
195+ l.log (fmiFatal, " Unable to instantiate model! " + std::string (e.what ()));
196+
197+ return nullptr ;
198+ }
198199}
199200
200201fmi3Status fmi3EnterEventMode (fmi3Instance instance) {
@@ -220,27 +221,43 @@ fmi3Status fmi3EnterInitializationMode(fmi3Instance c,
220221 const auto component = static_cast <Fmi3Component *>(c);
221222
222223 try {
224+
225+ if (component->state != Fmi3Component::State::Instantiated) {
226+ throw std::logic_error (" Invalid state. Expected Instantiated." );
227+ }
228+
223229 component->slave ->enter_initialisation_mode (startTime, stop, tol);
230+ component->state = Fmi3Component::State::InitializationMode;
224231 return fmi3OK;
225232 } catch (const fmu4cpp::fatal_error &ex) {
226- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
233+ component->logger ->log (fmiFatal, ex.what ());
234+ component->state = Fmi3Component::State::Invalid;
227235 return fmi3Fatal;
228236 } catch (const std::exception &ex) {
229- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
237+ component->logger ->log (fmiError, ex.what ());
238+ component->state = Fmi3Component::State::Terminated;
230239 return fmi3Error;
231240 }
232241}
233242
234243fmi3Status fmi3ExitInitializationMode (fmi3Instance c) {
235244 const auto component = static_cast <Fmi3Component *>(c);
236245 try {
246+
247+ if (component->state != Fmi3Component::State::InitializationMode) {
248+ throw std::logic_error (" Invalid state. Expected InitializationMode." );
249+ }
250+
237251 component->slave ->exit_initialisation_mode ();
252+ component->state = Fmi3Component::State::StepMode;
238253 return fmi3OK;
239254 } catch (const fmu4cpp::fatal_error &ex) {
240- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
255+ component->logger ->log (fmiFatal, ex.what ());
256+ component->state = Fmi3Component::State::Invalid;
241257 return fmi3Fatal;
242258 } catch (const std::exception &ex) {
243- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
259+ component->logger ->log (fmiError, ex.what ());
260+ component->state = Fmi3Component::State::Terminated;
244261 return fmi3Error;
245262 }
246263}
@@ -249,12 +266,15 @@ fmi3Status fmi3Terminate(fmi3Instance c) {
249266 const auto component = static_cast <Fmi3Component *>(c);
250267 try {
251268 component->slave ->terminate ();
269+ component->state = Fmi3Component::State::Terminated;
252270 return fmi3OK;
253271 } catch (const fmu4cpp::fatal_error &ex) {
254- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
272+ component->logger ->log (fmiFatal, ex.what ());
273+ component->state = Fmi3Component::State::Invalid;
255274 return fmi3Fatal;
256275 } catch (const std::exception &ex) {
257- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
276+ component->logger ->log (fmiError, ex.what ());
277+ component->state = Fmi3Component::State::Terminated;
258278 return fmi3Error;
259279 }
260280}
@@ -270,6 +290,11 @@ fmi3Status fmi3DoStep(fmi3Instance c,
270290
271291 const auto component = static_cast <Fmi3Component *>(c);
272292 try {
293+
294+ if (component->state != Fmi3Component::State::StepMode) {
295+ throw std::logic_error (" Invalid state. Expected StepMode." );
296+ }
297+
273298 if (component->slave ->step (currentCommunicationPoint, communicationStepSize)) {
274299 *earlyReturn = false ;
275300 *terminateSimulation = false ;
@@ -278,12 +303,16 @@ fmi3Status fmi3DoStep(fmi3Instance c,
278303 return fmi3OK;
279304 }
280305
306+ component->logger ->log (fmiWarning, " Step returned false!" );
307+
281308 return fmi3Discard;
282309 } catch (const fmu4cpp::fatal_error &ex) {
283- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
310+ component->logger ->log (fmiFatal, ex.what ());
311+ component->state = Fmi3Component::State::Invalid;
284312 return fmi3Fatal;
285313 } catch (const std::exception &ex) {
286- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
314+ component->logger ->log (fmiError, ex.what ());
315+ component->state = Fmi3Component::State::Terminated;
287316 return fmi3Error;
288317 }
289318}
@@ -294,8 +323,19 @@ fmi3Status fmi3CancelStep(fmi3Instance) {
294323
295324fmi3Status fmi3Reset (fmi3Instance c) {
296325 const auto component = static_cast <Fmi3Component *>(c);
297- component->slave ->reset ();
298- return fmi3OK;
326+ try {
327+ component->slave ->reset ();
328+ component->state = Fmi3Component::State::Instantiated;
329+ return fmi3OK;
330+ } catch (const fmu4cpp::fatal_error &ex) {
331+ component->logger ->log (fmiFatal, ex.what ());
332+ component->state = Fmi3Component::State::Invalid;
333+ return fmi3Fatal;
334+ } catch (const std::exception &ex) {
335+ component->logger ->log (fmiError, ex.what ());
336+ component->state = Fmi3Component::State::Terminated;
337+ return fmi3Error;
338+ }
299339}
300340
301341fmi3Status fmi3GetInt32 (
@@ -310,10 +350,12 @@ fmi3Status fmi3GetInt32(
310350 component->slave ->get_integer (vr, nvr, value);
311351 return fmi3OK;
312352 } catch (const fmu4cpp::fatal_error &ex) {
313- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
353+ component->logger ->log (fmiFatal, ex.what ());
354+ component->state = Fmi3Component::State::Invalid;
314355 return fmi3Fatal;
315356 } catch (const std::exception &ex) {
316- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
357+ component->logger ->log (fmiError, ex.what ());
358+ component->state = Fmi3Component::State::Terminated;
317359 return fmi3Error;
318360 }
319361}
@@ -330,10 +372,12 @@ fmi3Status fmi3GetFloat64(
330372 component->slave ->get_real (vr, nvr, value);
331373 return fmi3OK;
332374 } catch (const fmu4cpp::fatal_error &ex) {
333- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
375+ component->logger ->log (fmiFatal, ex.what ());
376+ component->state = Fmi3Component::State::Invalid;
334377 return fmi3Fatal;
335378 } catch (const std::exception &ex) {
336- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
379+ component->logger ->log (fmiError, ex.what ());
380+ component->state = Fmi3Component::State::Terminated;
337381 return fmi3Error;
338382 }
339383}
@@ -350,10 +394,12 @@ fmi3Status fmi3GetBoolean(
350394 component->slave ->get_boolean (vr, nvr, value);
351395 return fmi3OK;
352396 } catch (const fmu4cpp::fatal_error &ex) {
353- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
397+ component->logger ->log (fmiFatal, ex.what ());
398+ component->state = Fmi3Component::State::Invalid;
354399 return fmi3Fatal;
355400 } catch (const std::exception &ex) {
356- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
401+ component->logger ->log (fmiError, ex.what ());
402+ component->state = Fmi3Component::State::Terminated;
357403 return fmi3Error;
358404 }
359405}
@@ -370,10 +416,12 @@ fmi3Status fmi3GetString(
370416 component->slave ->get_string (vr, nvr, value);
371417 return fmi3OK;
372418 } catch (const fmu4cpp::fatal_error &ex) {
373- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
419+ component->logger ->log (fmiFatal, ex.what ());
420+ component->state = Fmi3Component::State::Invalid;
374421 return fmi3Fatal;
375422 } catch (const std::exception &ex) {
376- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
423+ component->logger ->log (fmiError, ex.what ());
424+ component->state = Fmi3Component::State::Terminated;
377425 return fmi3Error;
378426 }
379427}
@@ -390,10 +438,12 @@ fmi3Status fmi3SetInt32(
390438 component->slave ->set_integer (vr, nvr, value);
391439 return fmi3OK;
392440 } catch (const fmu4cpp::fatal_error &ex) {
393- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
441+ component->logger ->log (fmiFatal, ex.what ());
442+ component->state = Fmi3Component::State::Invalid;
394443 return fmi3Fatal;
395444 } catch (const std::exception &ex) {
396- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
445+ component->logger ->log (fmiError, ex.what ());
446+ component->state = Fmi3Component::State::Terminated;
397447 return fmi3Error;
398448 }
399449}
@@ -410,10 +460,12 @@ fmi3Status fmi3SetFloat64(
410460 component->slave ->set_real (vr, nvr, value);
411461 return fmi3OK;
412462 } catch (const fmu4cpp::fatal_error &ex) {
413- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
463+ component->logger ->log (fmiFatal, ex.what ());
464+ component->state = Fmi3Component::State::Invalid;
414465 return fmi3Fatal;
415466 } catch (const std::exception &ex) {
416- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
467+ component->logger ->log (fmiError, ex.what ());
468+ component->state = Fmi3Component::State::Terminated;
417469 return fmi3Error;
418470 }
419471}
@@ -430,10 +482,12 @@ fmi3Status fmi3SetBoolean(
430482 component->slave ->set_boolean (vr, nvr, value);
431483 return fmi3OK;
432484 } catch (const fmu4cpp::fatal_error &ex) {
433- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
485+ component->logger ->log (fmiFatal, ex.what ());
486+ component->state = Fmi3Component::State::Invalid;
434487 return fmi3Fatal;
435488 } catch (const std::exception &ex) {
436- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
489+ component->logger ->log (fmiError, ex.what ());
490+ component->state = Fmi3Component::State::Terminated;
437491 return fmi3Error;
438492 }
439493}
@@ -450,10 +504,12 @@ fmi3Status fmi3SetString(
450504 component->slave ->set_string (vr, nvr, value);
451505 return fmi3OK;
452506 } catch (const fmu4cpp::fatal_error &ex) {
453- component->logger ->log (toCommonStatusFromFmi3 (fmi3Fatal), ex.what ());
507+ component->logger ->log (fmiFatal, ex.what ());
508+ component->state = Fmi3Component::State::Invalid;
454509 return fmi3Fatal;
455510 } catch (const std::exception &ex) {
456- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error), ex.what ());
511+ component->logger ->log (fmiError, ex.what ());
512+ component->state = Fmi3Component::State::Terminated;
457513 return fmi3Error;
458514 }
459515}
@@ -467,7 +523,7 @@ fmi3Status fmi3GetBinary(fmi3Instance c,
467523
468524 const auto component = static_cast <Fmi3Component *>(c);
469525
470- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error) , " Unsupported function fmi3GetBinary" );
526+ component->logger ->log (fmiError , " Unsupported function fmi3GetBinary" );
471527 return fmi3Error;
472528}
473529
@@ -480,7 +536,7 @@ fmi3Status fmi3SetBinary(fmi3Instance c,
480536
481537 const auto component = static_cast <Fmi3Component *>(c);
482538
483- component->logger ->log (toCommonStatusFromFmi3 (fmi3Error) , " Unsupported function fmi3SetBinary" );
539+ component->logger ->log (fmiError , " Unsupported function fmi3SetBinary" );
484540 return fmi3Error;
485541}
486542
@@ -800,7 +856,10 @@ fmi3Status fmi3ActivateModelPartition(fmi3Instance instance,
800856}
801857
802858void fmi3FreeInstance (fmi3Instance c) {
803- const auto component = static_cast <Fmi3Component *>(c);
804- delete component;
859+ if (c) {
860+ const auto component = static_cast <Fmi3Component *>(c);
861+ component->state = Fmi3Component::State::Invalid;
862+ delete component;
863+ }
805864}
806865}
0 commit comments