adevs_fmi.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /**
  2. * Copyright (c) 2014, James Nutaro
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. * The views and conclusions contained in the software and documentation are those
  26. * of the authors and should not be interpreted as representing official policies,
  27. * either expressed or implied, of the FreeBSD Project.
  28. *
  29. * Bugs, comments, and questions can be sent to nutaro@gmail.com
  30. */
  31. #ifndef _adevs_fmi_h_
  32. #define _adevs_fmi_h_
  33. #include <algorithm>
  34. #include <cmath>
  35. #include <iostream>
  36. #include <cstdlib>
  37. #include <cstdio>
  38. #include <cassert>
  39. #include "adevs_hybrid.h"
  40. #include "fmi2Functions.h"
  41. #include "fmi2FunctionTypes.h"
  42. #include "fmi2TypesPlatform.h"
  43. // Functions for loading DLL and so files
  44. #ifdef _WIN32
  45. #include <windows.h>
  46. #define OPEN_LIB(name) LoadLibrary(name)
  47. #define GET_FUNC(hndl,name) GetProcAddress(hndl,name)
  48. #define CLOSE_LIB(hndl) FreeLibrary(hndl)
  49. #else
  50. #include <dlfcn.h>
  51. #define OPEN_LIB(name) dlopen(name,RTLD_LAZY)
  52. #define GET_FUNC(hndl,name) dlsym(hndl,name)
  53. #define CLOSE_LIB(hndl) dlclose(hndl)
  54. #endif
  55. namespace adevs
  56. {
  57. /**
  58. * Load an FMI wrapped continuous system model for use in a
  59. * discrete event simulation. The FMI can then be attached
  60. * to any of the ODE solvers and event detectors in adevs
  61. * for simulation with the Hybrid class. This FMI loader
  62. * does not automatically extract model information from the
  63. * description XML, and so that information must be provided
  64. * explicitly by the end-user, but you probably need to know
  65. * this information regardless if you are using the FMI inside
  66. * of a larger discrete event simulation.
  67. */
  68. template <typename X> class FMI:
  69. public ode_system<X>
  70. {
  71. public:
  72. /**
  73. * This constructs a wrapper around an FMI. The constructor
  74. * must be provided with the FMI's GUID, the number of state variables,
  75. * number of event indicators, and the path to the .so file
  76. * that contains the FMI functions for this model.
  77. */
  78. FMI(const char* modelname,
  79. const char* guid,
  80. const char* resource_location,
  81. int num_state_variables,
  82. int num_event_indicators,
  83. const char* shared_lib_name,
  84. const double tolerance = 1E-8,
  85. int num_extra_event_indicators = 0,
  86. double start_time = 0.0);
  87. /// Copy the initial state of the model to q
  88. virtual void init(double* q);
  89. /// Compute the derivative for state q and put it in dq
  90. virtual void der_func(const double* q, double* dq);
  91. /// Compute the state event functions for state q and put them in z
  92. virtual void state_event_func(const double* q, double* z);
  93. /// Compute the time event function using state q
  94. virtual double time_event_func(const double* q);
  95. /**
  96. * This method is invoked immediately following an update of the
  97. * continuous state variables and signal to the FMI the end
  98. * of an integration state.
  99. */
  100. virtual void postStep(double* q);
  101. /**
  102. * Like the postStep() method, but this is called at the end
  103. * of a trial step made by the numerical integrator. Trial steps
  104. * are used to locate state events and to estimate numerical
  105. * errors. The state vector q passed to this method may not be
  106. * the final vector assigned to the model at the end of
  107. * the current integration step. The get that value use
  108. * the postStep() method.
  109. */
  110. virtual void postTrialStep(double* q);
  111. /**
  112. * The internal transition function. This function will process all events
  113. * required by the FMI. Any derived class should call this method for the
  114. * parent class, then set or get any variables as appropriate, and then
  115. * call the base class method again to account for these changes.
  116. */
  117. virtual void internal_event(double* q,
  118. const bool* state_event);
  119. /**
  120. * The external transition See the notes on the internal_event function for
  121. * derived classes.
  122. */
  123. virtual void external_event(double* q, double e,
  124. const Bag<X>& xb);
  125. /**
  126. * The confluent transition function. See the notes on the internal_event function for
  127. * derived classes.
  128. */
  129. virtual void confluent_event(double *q, const bool* state_event,
  130. const Bag<X>& xb);
  131. /**
  132. * The output function. This can read variables for the FMI, but should
  133. * not make any modifications to those variables.
  134. */
  135. virtual void output_func(const double *q, const bool* state_event,
  136. Bag<X>& yb);
  137. /**
  138. * Garbage collection function. This works just like the Atomic gc_output method.
  139. * The default implementation does nothing.
  140. */
  141. virtual void gc_output(Bag<X>& gb);
  142. /// Destructor
  143. virtual ~FMI();
  144. /// Get the current time
  145. double get_time() const { return t_now; }
  146. /// Get the value of a real variable
  147. double get_real(int k);
  148. /// Set the value of a real variable
  149. void set_real(int k, double val);
  150. /// Get the value of an integer variable
  151. int get_int(int k);
  152. /// Set the value of an integer variable
  153. void set_int(int k, int val);
  154. /// Get the value of a boolean variable
  155. bool get_bool(int k);
  156. /// Set the value of a boolean variable
  157. void set_bool(int k, bool val);
  158. /// Get the value of a string variable
  159. std::string get_string(int k);
  160. /// Set the value of a string variable
  161. void set_string(int k, std::string& val);
  162. private:
  163. // Reference to the FMI
  164. fmi2Component c;
  165. // Pointer to the FMI interface
  166. fmi2Component (*_fmi2Instantiate)(fmi2String, fmi2Type,
  167. fmi2String, fmi2String, const fmi2CallbackFunctions*,
  168. fmi2Boolean, fmi2Boolean);
  169. void (*_fmi2FreeInstance)(fmi2Component);
  170. fmi2Status (*_fmi2SetupExperiment)(fmi2Component, fmi2Boolean,
  171. fmi2Real, fmi2Real, fmi2Boolean, fmi2Real);
  172. fmi2Status (*_fmi2EnterInitializationMode)(fmi2Component);
  173. fmi2Status (*_fmi2ExitInitializationMode)(fmi2Component);
  174. fmi2Status (*_fmi2GetReal)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Real*);
  175. fmi2Status (*_fmi2GetInteger)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Integer*);
  176. fmi2Status (*_fmi2GetBoolean)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Boolean*);
  177. fmi2Status (*_fmi2GetString)(fmi2Component, const fmi2ValueReference*, size_t, fmi2String*);
  178. fmi2Status (*_fmi2SetReal)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Real*);
  179. fmi2Status (*_fmi2SetInteger)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Integer*);
  180. fmi2Status (*_fmi2SetBoolean)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Boolean*);
  181. fmi2Status (*_fmi2SetString)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2String*);
  182. fmi2Status (*_fmi2EnterEventMode)(fmi2Component);
  183. fmi2Status (*_fmi2NewDiscreteStates)(fmi2Component,fmi2EventInfo*);
  184. fmi2Status (*_fmi2EnterContinuousTimeMode)(fmi2Component);
  185. fmi2Status (*_fmi2CompletedIntegratorStep)(fmi2Component, fmi2Boolean, fmi2Boolean*, fmi2Boolean*);
  186. fmi2Status (*_fmi2SetTime)(fmi2Component, fmi2Real);
  187. fmi2Status (*_fmi2SetContinuousStates)(fmi2Component, const fmi2Real*, size_t);
  188. fmi2Status (*_fmi2GetDerivatives)(fmi2Component, fmi2Real*, size_t);
  189. fmi2Status (*_fmi2GetEventIndicators)(fmi2Component, fmi2Real*, size_t);
  190. fmi2Status (*_fmi2GetContinuousStates)(fmi2Component, fmi2Real*, size_t);
  191. // Instant of the next time event
  192. double next_time_event;
  193. // Current time
  194. double t_now;
  195. // so library handle
  196. #ifdef _WIN32
  197. HINSTANCE so_hndl;
  198. #else
  199. void* so_hndl;
  200. #endif
  201. // Are we in continuous time mode?
  202. bool cont_time_mode;
  203. // Number of event indicators that are not governed by the FMI
  204. int num_extra_event_indicators;
  205. // Start time of the simulation
  206. double start_time;
  207. static void fmilogger(
  208. fmi2ComponentEnvironment componentEnvironment,
  209. fmi2String instanceName,
  210. fmi2Status status,
  211. fmi2String category,
  212. fmi2String message,...)
  213. {
  214. if (message != NULL){
  215. fprintf(stderr, message,"\n");
  216. }
  217. }
  218. fmi2CallbackFunctions* callbackFuncs;
  219. void iterate_events();
  220. };
  221. template <typename X>
  222. FMI<X>::FMI(const char* modelname,
  223. const char* guid,
  224. const char* resource_location,
  225. int num_state_variables,
  226. int num_event_indicators,
  227. const char* so_file_name,
  228. const double tolerance,
  229. int num_extra_event_indicators,
  230. double start_time):
  231. // One extra variable at the end for time
  232. ode_system<X>(num_state_variables+1,num_event_indicators+num_extra_event_indicators),
  233. next_time_event(adevs_inf<double>()),
  234. t_now(start_time),
  235. so_hndl(NULL),
  236. cont_time_mode(false),
  237. num_extra_event_indicators(num_extra_event_indicators)
  238. {
  239. fmi2CallbackFunctions tmp = {adevs::FMI<X>::fmilogger,calloc,free,NULL,NULL};
  240. callbackFuncs = new fmi2CallbackFunctions(tmp);
  241. so_hndl = OPEN_LIB(so_file_name);
  242. if (so_hndl == NULL)
  243. {
  244. throw adevs::exception("Could not load so file",this);
  245. }
  246. // This only works with a POSIX compliant compiler/system
  247. _fmi2Instantiate = (fmi2Component (*)(fmi2String, fmi2Type,
  248. fmi2String, fmi2String, const fmi2CallbackFunctions*,
  249. fmi2Boolean, fmi2Boolean))GET_FUNC(so_hndl,"fmi2Instantiate");
  250. assert(_fmi2Instantiate != NULL);
  251. _fmi2FreeInstance = (void (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2FreeInstance");
  252. assert(_fmi2FreeInstance != NULL);
  253. _fmi2SetupExperiment = (fmi2Status (*)(fmi2Component, fmi2Boolean,
  254. fmi2Real, fmi2Real, fmi2Boolean, fmi2Real))GET_FUNC(so_hndl,"fmi2SetupExperiment");
  255. assert(_fmi2SetupExperiment != NULL);
  256. _fmi2EnterInitializationMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterInitializationMode");
  257. assert(_fmi2EnterInitializationMode != NULL);
  258. _fmi2ExitInitializationMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2ExitInitializationMode");
  259. assert(_fmi2ExitInitializationMode != NULL);
  260. _fmi2GetReal = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Real*))
  261. GET_FUNC(so_hndl,"fmi2GetReal");
  262. assert(_fmi2GetReal != NULL);
  263. _fmi2GetInteger = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Integer*))
  264. GET_FUNC(so_hndl,"fmi2GetInteger");
  265. assert(_fmi2GetInteger != NULL);
  266. _fmi2GetBoolean = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Boolean*))
  267. GET_FUNC(so_hndl,"fmi2GetBoolean");
  268. assert(_fmi2GetBoolean != NULL);
  269. _fmi2GetString = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2String*))
  270. GET_FUNC(so_hndl,"fmi2GetString");
  271. assert(_fmi2GetString != NULL);
  272. _fmi2SetReal = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Real*))
  273. GET_FUNC(so_hndl,"fmi2SetReal");
  274. assert(_fmi2SetReal != NULL);
  275. _fmi2SetInteger = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Integer*))
  276. GET_FUNC(so_hndl,"fmi2SetInteger");
  277. assert(_fmi2SetInteger != NULL);
  278. _fmi2SetBoolean = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Boolean*))
  279. GET_FUNC(so_hndl,"fmi2SetBoolean");
  280. assert(_fmi2SetBoolean != NULL);
  281. _fmi2SetString = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2String*))
  282. GET_FUNC(so_hndl,"fmi2SetString");
  283. assert(_fmi2SetString != NULL);
  284. _fmi2EnterEventMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterEventMode");
  285. assert(_fmi2EnterEventMode != NULL);
  286. _fmi2NewDiscreteStates = (fmi2Status (*)(fmi2Component,fmi2EventInfo*))GET_FUNC(so_hndl,"fmi2NewDiscreteStates");
  287. assert(_fmi2NewDiscreteStates != NULL);
  288. _fmi2EnterContinuousTimeMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterContinuousTimeMode");
  289. assert(_fmi2EnterContinuousTimeMode != NULL);
  290. _fmi2CompletedIntegratorStep = (fmi2Status (*)(fmi2Component, fmi2Boolean, fmi2Boolean*, fmi2Boolean*))
  291. GET_FUNC(so_hndl,"fmi2CompletedIntegratorStep");
  292. assert(_fmi2CompletedIntegratorStep != NULL);
  293. _fmi2SetTime = (fmi2Status (*)(fmi2Component, fmi2Real))GET_FUNC(so_hndl,"fmi2SetTime");
  294. assert(_fmi2SetTime != NULL);
  295. _fmi2SetContinuousStates = (fmi2Status (*)(fmi2Component, const fmi2Real*, size_t))
  296. GET_FUNC(so_hndl,"fmi2SetContinuousStates");
  297. assert(_fmi2SetContinuousStates != NULL);
  298. _fmi2GetDerivatives = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetDerivatives");
  299. assert(_fmi2GetDerivatives != NULL);
  300. _fmi2GetEventIndicators = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetEventIndicators");
  301. assert(_fmi2GetEventIndicators != NULL);
  302. _fmi2GetContinuousStates = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetContinuousStates");
  303. assert(_fmi2GetContinuousStates != NULL);
  304. // Create the FMI component
  305. c = _fmi2Instantiate(modelname,fmi2ModelExchange,guid,resource_location,callbackFuncs,fmi2False,fmi2False);
  306. assert(c != NULL);
  307. _fmi2SetupExperiment(c,fmi2True,tolerance,-1.0,fmi2False,-1.0);
  308. }
  309. template <typename X>
  310. void FMI<X>::iterate_events()
  311. {
  312. fmi2Status status;
  313. // Put into consistent initial state
  314. fmi2EventInfo eventInfo;
  315. do
  316. {
  317. status = _fmi2NewDiscreteStates(c,&eventInfo);
  318. assert(status == fmi2OK);
  319. }
  320. while (eventInfo.newDiscreteStatesNeeded == fmi2True);
  321. if (eventInfo.nextEventTimeDefined == fmi2True)
  322. next_time_event = eventInfo.nextEventTime;
  323. else
  324. next_time_event = adevs_inf<double>();
  325. assert(status == fmi2OK);
  326. }
  327. template <typename X>
  328. void FMI<X>::init(double* q)
  329. {
  330. fmi2Status status;
  331. // Initialize all variables
  332. status = _fmi2EnterInitializationMode(c);
  333. assert(status == fmi2OK);
  334. // Done with initialization
  335. status = _fmi2ExitInitializationMode(c);
  336. assert(status == fmi2OK);
  337. // Put into consistent initial state
  338. iterate_events();
  339. // Enter continuous time mode to start integration
  340. status = _fmi2EnterContinuousTimeMode(c);
  341. assert(status == fmi2OK);
  342. // Set initial value for time
  343. status = _fmi2SetTime(c,t_now);
  344. assert(status == fmi2OK);
  345. // Get starting state variable values
  346. status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
  347. assert(status == fmi2OK);
  348. q[this->numVars()-1] = t_now;
  349. cont_time_mode = true;
  350. }
  351. template <typename X>
  352. void FMI<X>::der_func(const double* q, double* dq)
  353. {
  354. fmi2Status status;
  355. if (!cont_time_mode)
  356. {
  357. status = _fmi2EnterContinuousTimeMode(c);
  358. assert(status == fmi2OK);
  359. cont_time_mode = true;
  360. }
  361. status =_fmi2SetTime(c,q[this->numVars()-1]);
  362. assert(status == fmi2OK);
  363. status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
  364. assert(status == fmi2OK);
  365. status = _fmi2GetDerivatives(c,dq,this->numVars()-1);
  366. assert(status == fmi2OK);
  367. dq[this->numVars()-1] = 1.0;
  368. }
  369. template <typename X>
  370. void FMI<X>::state_event_func(const double* q, double* z)
  371. {
  372. fmi2Status status;
  373. if (!cont_time_mode)
  374. {
  375. status = _fmi2EnterContinuousTimeMode(c);
  376. assert(status == fmi2OK);
  377. cont_time_mode = true;
  378. }
  379. status = _fmi2SetTime(c,q[this->numVars()-1]);
  380. assert(status == fmi2OK);
  381. status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
  382. assert(status == fmi2OK);
  383. status = _fmi2GetEventIndicators(c,z,this->numEvents()-num_extra_event_indicators);
  384. assert(status == fmi2OK);
  385. }
  386. template <typename X>
  387. double FMI<X>::time_event_func(const double* q)
  388. {
  389. return next_time_event-q[this->numVars()-1];
  390. }
  391. template <typename X>
  392. void FMI<X>::postStep(double* q)
  393. {
  394. assert(cont_time_mode);
  395. // Don't advance the FMI state by zero units of time
  396. // when in continuous mode
  397. if (q[this->numVars()-1] <= t_now)
  398. return;
  399. // Try to complete the integration step
  400. fmi2Status status;
  401. fmi2Boolean enterEventMode;
  402. fmi2Boolean terminateSimulation;
  403. t_now = q[this->numVars()-1];
  404. status = _fmi2SetTime(c,t_now);
  405. assert(status == fmi2OK);
  406. status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
  407. assert(status == fmi2OK);
  408. status = _fmi2CompletedIntegratorStep(c,fmi2True,&enterEventMode,&terminateSimulation);
  409. assert(status == fmi2OK);
  410. // Force an event if one is indicated
  411. if (enterEventMode == fmi2True)
  412. next_time_event = t_now;
  413. }
  414. template <typename X>
  415. void FMI<X>::postTrialStep(double* q)
  416. {
  417. assert(cont_time_mode);
  418. // Restore values changed by der_func and state_event_func
  419. fmi2Status status;
  420. status = _fmi2SetTime(c,q[this->numVars()-1]);
  421. assert(status == fmi2OK);
  422. status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
  423. assert(status == fmi2OK);
  424. }
  425. template <typename X>
  426. void FMI<X>::internal_event(double* q, const bool* state_event)
  427. {
  428. fmi2Status status;
  429. // postStep will have updated the continuous variables, so
  430. // we just process discrete events here.
  431. if (cont_time_mode)
  432. {
  433. status = _fmi2EnterEventMode(c);
  434. assert(status == fmi2OK);
  435. cont_time_mode = false;
  436. }
  437. // Process events
  438. iterate_events();
  439. // Update the state variable array
  440. status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
  441. assert(status == fmi2OK);
  442. }
  443. template <typename X>
  444. void FMI<X>::external_event(double* q, double e, const Bag<X>& xb)
  445. {
  446. fmi2Status status;
  447. // Go to event mode if we have not yet done so
  448. if (cont_time_mode)
  449. {
  450. status = _fmi2EnterEventMode(c);
  451. assert(status == fmi2OK);
  452. cont_time_mode = false;
  453. }
  454. // process any events that need processing
  455. iterate_events();
  456. status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
  457. assert(status == fmi2OK);
  458. }
  459. template <typename X>
  460. void FMI<X>::confluent_event(double *q, const bool* state_event, const Bag<X>& xb)
  461. {
  462. fmi2Status status;
  463. // postStep will have updated the continuous variables, so
  464. // we just process discrete events here.
  465. if (cont_time_mode)
  466. {
  467. status = _fmi2EnterEventMode(c);
  468. assert(status == fmi2OK);
  469. cont_time_mode = false;
  470. }
  471. iterate_events();
  472. status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
  473. assert(status == fmi2OK);
  474. }
  475. template <typename X>
  476. void FMI<X>::output_func(const double *q, const bool* state_event, Bag<X>& yb)
  477. {
  478. }
  479. template <typename X>
  480. void FMI<X>::gc_output(Bag<X>& gb)
  481. {
  482. }
  483. template <typename X>
  484. FMI<X>::~FMI()
  485. {
  486. _fmi2FreeInstance(c);
  487. delete callbackFuncs;
  488. CLOSE_LIB(so_hndl);
  489. }
  490. template <typename X>
  491. double FMI<X>::get_real(int k)
  492. {
  493. const fmi2ValueReference ref = k;
  494. fmi2Real val;
  495. fmi2Status status = _fmi2GetReal(c,&ref,1,&val);
  496. assert(status == fmi2OK);
  497. return val;
  498. }
  499. template <typename X>
  500. void FMI<X>::set_real(int k, double val)
  501. {
  502. const fmi2ValueReference ref = k;
  503. fmi2Real fmi_val = val;
  504. fmi2Status status = _fmi2SetReal(c,&ref,1,&fmi_val);
  505. assert(status == fmi2OK);
  506. }
  507. template <typename X>
  508. int FMI<X>::get_int(int k)
  509. {
  510. const fmi2ValueReference ref = k;
  511. fmi2Integer val;
  512. fmi2Status status = _fmi2GetInteger(c,&ref,1,&val);
  513. assert(status == fmi2OK);
  514. return val;
  515. }
  516. template <typename X>
  517. void FMI<X>::set_int(int k, int val)
  518. {
  519. const fmi2ValueReference ref = k;
  520. fmi2Integer fmi_val = val;
  521. fmi2Status status = _fmi2SetInteger(c,&ref,1,&fmi_val);
  522. assert(status == fmi2OK);
  523. }
  524. template <typename X>
  525. bool FMI<X>::get_bool(int k)
  526. {
  527. const fmi2ValueReference ref = k;
  528. fmi2Boolean val;
  529. fmi2Status status = _fmi2GetBoolean(c,&ref,1,&val);
  530. assert(status == fmi2OK);
  531. return (val == fmi2True);
  532. }
  533. template <typename X>
  534. void FMI<X>::set_bool(int k, bool val)
  535. {
  536. const fmi2ValueReference ref = k;
  537. fmi2Boolean fmi_val = fmi2False;
  538. if (val) fmi_val = fmi2True;
  539. fmi2Status status = _fmi2SetBoolean(c,&ref,1,&fmi_val);
  540. assert(status == fmi2OK);
  541. }
  542. template <typename X>
  543. std::string FMI<X>::get_string(int k)
  544. {
  545. const fmi2ValueReference ref = k;
  546. fmi2String val;
  547. fmi2Status status = _fmi2GetString(c,&ref,1,&val);
  548. assert(status == fmi2OK);
  549. return val;
  550. }
  551. template <typename X>
  552. void FMI<X>::set_string(int k, std::string& val)
  553. {
  554. const fmi2ValueReference ref = k;
  555. fmi2String fmi_val = fmi2False;
  556. fmi2Status status = _fmi2SetString(c,&ref,1,&fmi_val);
  557. assert(status == fmi2OK);
  558. }
  559. } // end of namespace
  560. #endif