fmu2_model_interface.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /*
  2. * This file is part of OpenModelica.
  3. *
  4. * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
  5. * c/o Linköpings universitet, Department of Computer and Information Science,
  6. * SE-58183 Linköping, Sweden.
  7. *
  8. * All rights reserved.
  9. *
  10. * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
  11. * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
  12. * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
  13. * OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
  14. *
  15. * The OpenModelica software and the Open Source Modelica
  16. * Consortium (OSMC) Public License (OSMC-PL) are obtained
  17. * from OSMC, either from the above address,
  18. * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
  19. * http://www.openmodelica.org, and in the OpenModelica distribution.
  20. * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
  21. *
  22. * This program is distributed WITHOUT ANY WARRANTY; without
  23. * even the implied warranty of MERCHANTABILITY or FITNESS
  24. * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
  25. * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
  26. *
  27. * See the full OSMC Public License conditions for more details.
  28. *
  29. */
  30. #include "simulation_data.h"
  31. #include "simulation/solver/stateset.h"
  32. #include "simulation/solver/model_help.h"
  33. #if !defined(OMC_NUM_NONLINEAR_SYSTEMS) || OMC_NUM_NONLINEAR_SYSTEMS>0
  34. #include "simulation/solver/nonlinearSystem.h"
  35. #endif
  36. #if !defined(OMC_NUM_LINEAR_SYSTEMS) || OMC_NUM_LINEAR_SYSTEMS>0
  37. #include "simulation/solver/linearSystem.h"
  38. #endif
  39. #if !defined(OMC_NUM_MIXED_SYSTEMS) || OMC_NUM_MIXED_SYSTEMS>0
  40. #include "simulation/solver/mixedSystem.h"
  41. #endif
  42. #include "simulation/solver/delay.h"
  43. #include "simulation/simulation_info_json.h"
  44. #include "simulation/simulation_input_xml.h"
  45. /*
  46. DLLExport pthread_key_t fmu2_thread_data_key;
  47. */
  48. fmi2Boolean isCategoryLogged(ModelInstance *comp, int categoryIndex);
  49. static fmi2String logCategoriesNames[] = {"logEvents", "logSingularLinearSystems", "logNonlinearSystems", "logDynamicStateSelection",
  50. "logStatusWarning", "logStatusDiscard", "logStatusError", "logStatusFatal", "logStatusPending", "logAll", "logFmi2Call"};
  51. // macro to be used to log messages. The macro check if current
  52. // log category is valid and, if true, call the logger provided by simulator.
  53. #define FILTERED_LOG(instance, status, categoryIndex, message, ...) if (isCategoryLogged(instance, categoryIndex)) \
  54. instance->functions->logger(instance->functions->componentEnvironment, instance->instanceName, status, \
  55. logCategoriesNames[categoryIndex], message, ##__VA_ARGS__);
  56. // array of value references of states
  57. #if NUMBER_OF_REALS>0
  58. fmi2ValueReference vrStates[NUMBER_OF_STATES] = STATES;
  59. fmi2ValueReference vrStatesDerivatives[NUMBER_OF_STATES] = STATESDERIVATIVES;
  60. #endif
  61. // ---------------------------------------------------------------------------
  62. // Private helpers used below to validate function arguments
  63. // ---------------------------------------------------------------------------
  64. const char* stateToString(ModelInstance *comp) {
  65. switch (comp->state) {
  66. case modelInstantiated: return "Instantiated";
  67. case modelInitializationMode: return "Initialization Mode";
  68. case modelEventMode: return "Event Mode";
  69. case modelContinuousTimeMode: return "Continuous-Time Mode";
  70. case modelTerminated: return "Terminated";
  71. case modelError: return "Error";
  72. default: break;
  73. }
  74. return "Unknown";
  75. }
  76. static fmi2Boolean invalidNumber(ModelInstance *comp, const char *f, const char *arg, int n, int nExpected) {
  77. if (n != nExpected) {
  78. comp->state = modelError;
  79. FILTERED_LOG(comp, fmi2Error, LOG_STATUSERROR, "%s: Invalid argument %s = %d. Expected %d.", f, arg, n, nExpected)
  80. return fmi2True;
  81. }
  82. return fmi2False;
  83. }
  84. static fmi2Boolean invalidState(ModelInstance *comp, const char *f, int statesExpected) {
  85. if (!comp)
  86. return fmi2True;
  87. if (!(comp->state & statesExpected)) {
  88. FILTERED_LOG(comp, fmi2Error, LOG_STATUSERROR, "%s: Illegal call sequence. %s is not allowed in %s state.", f, f, stateToString(comp))
  89. comp->state = modelError;
  90. return fmi2True;
  91. }
  92. return fmi2False;
  93. }
  94. static fmi2Boolean nullPointer(ModelInstance* comp, const char *f, const char *arg, const void *p) {
  95. if (!p) {
  96. comp->state = modelError;
  97. FILTERED_LOG(comp, fmi2Error, LOG_STATUSERROR, "%s: Invalid argument %s = NULL.", f, arg)
  98. return fmi2True;
  99. }
  100. return fmi2False;
  101. }
  102. static fmi2Boolean vrOutOfRange(ModelInstance *comp, const char *f, fmi2ValueReference vr, int end) {
  103. if (vr >= end) {
  104. comp->state = modelError;
  105. FILTERED_LOG(comp, fmi2Error, LOG_STATUSERROR, "%s: Illegal value reference %u.", f, vr)
  106. return fmi2True;
  107. }
  108. return fmi2False;
  109. }
  110. static fmi2Status unsupportedFunction(fmi2Component c, const char *fName, int statesExpected) {
  111. ModelInstance *comp = (ModelInstance *)c;
  112. fmi2CallbackLogger log = comp->functions->logger;
  113. if (invalidState(comp, fName, statesExpected))
  114. return fmi2Error;
  115. FILTERED_LOG(comp, fmi2Error, LOG_STATUSERROR, "%s: Function not implemented.", fName)
  116. return fmi2Error;
  117. }
  118. // ---------------------------------------------------------------------------
  119. // Private helpers logger
  120. // ---------------------------------------------------------------------------
  121. // return fmi2True if logging category is on. Else return fmi2False.
  122. fmi2Boolean isCategoryLogged(ModelInstance *comp, int categoryIndex) {
  123. if (categoryIndex < NUMBER_OF_CATEGORIES && (comp->logCategories[categoryIndex] || comp->logCategories[LOG_ALL])) {
  124. return fmi2True;
  125. }
  126. return fmi2False;
  127. }
  128. // ---------------------------------------------------------------------------
  129. // Private helpers functions
  130. // ---------------------------------------------------------------------------
  131. fmi2Status fmi2EventUpdate(fmi2Component c, fmi2EventInfo* eventInfo)
  132. {
  133. int i;
  134. ModelInstance* comp = (ModelInstance *)c;
  135. threadData_t *threadData = comp->threadData;
  136. if (nullPointer(comp, "fmi2EventUpdate", "eventInfo", eventInfo))
  137. return fmi2Error;
  138. eventInfo->valuesOfContinuousStatesChanged = fmi2False;
  139. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EventUpdate: Start Event Update! Next Sample Event %g", eventInfo->nextEventTime)
  140. /* try */
  141. MMC_TRY_INTERNAL(simulationJumpBuffer)
  142. #if !defined(OMC_NO_STATESELECTION)
  143. if (stateSelection(comp->fmuData, comp->threadData, 1, 1))
  144. {
  145. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EventUpdate: Need to iterate state values changed!")
  146. /* if new set is calculated reinit the solver */
  147. eventInfo->valuesOfContinuousStatesChanged = fmi2True;
  148. }
  149. #endif
  150. storePreValues(comp->fmuData);
  151. /* activate sample event */
  152. for(i=0; i<comp->fmuData->modelData->nSamples; ++i)
  153. {
  154. if(comp->fmuData->simulationInfo->nextSampleTimes[i] <= comp->fmuData->localData[0]->timeValue)
  155. {
  156. comp->fmuData->simulationInfo->samples[i] = 1;
  157. infoStreamPrint(LOG_EVENTS, 0, "[%ld] sample(%g, %g)", comp->fmuData->modelData->samplesInfo[i].index, comp->fmuData->modelData->samplesInfo[i].start, comp->fmuData->modelData->samplesInfo[i].interval);
  158. }
  159. }
  160. comp->fmuData->callback->functionDAE(comp->fmuData, comp->threadData);
  161. /* deactivate sample events */
  162. for(i=0; i<comp->fmuData->modelData->nSamples; ++i)
  163. {
  164. if(comp->fmuData->simulationInfo->samples[i])
  165. {
  166. comp->fmuData->simulationInfo->samples[i] = 0;
  167. comp->fmuData->simulationInfo->nextSampleTimes[i] += comp->fmuData->modelData->samplesInfo[i].interval;
  168. }
  169. }
  170. for(i=0; i<comp->fmuData->modelData->nSamples; ++i)
  171. if((i == 0) || (comp->fmuData->simulationInfo->nextSampleTimes[i] < comp->fmuData->simulationInfo->nextSampleEvent))
  172. comp->fmuData->simulationInfo->nextSampleEvent = comp->fmuData->simulationInfo->nextSampleTimes[i];
  173. if(comp->fmuData->callback->checkForDiscreteChanges(comp->fmuData, comp->threadData) || comp->fmuData->simulationInfo->needToIterate || checkRelations(comp->fmuData) || eventInfo->valuesOfContinuousStatesChanged)
  174. {
  175. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EventUpdate: Need to iterate(discrete changes)!")
  176. eventInfo->newDiscreteStatesNeeded = fmi2True;
  177. eventInfo->nominalsOfContinuousStatesChanged = fmi2False;
  178. eventInfo->valuesOfContinuousStatesChanged = fmi2True;
  179. eventInfo->terminateSimulation = fmi2False;
  180. }
  181. else
  182. {
  183. eventInfo->newDiscreteStatesNeeded = fmi2False;
  184. eventInfo->nominalsOfContinuousStatesChanged = fmi2False;
  185. eventInfo->terminateSimulation = fmi2False;
  186. }
  187. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EventUpdate: newDiscreteStatesNeeded %s",eventInfo->newDiscreteStatesNeeded?"true":"false");
  188. /* due to an event overwrite old values */
  189. overwriteOldSimulationData(comp->fmuData);
  190. /* TODO: check the event iteration for relation
  191. * in fmi2 import and export. This is an workaround,
  192. * since the iteration seem not starting.
  193. */
  194. storePreValues(comp->fmuData);
  195. updateRelationsPre(comp->fmuData);
  196. //Get Next Event Time
  197. double nextSampleEvent=0;
  198. nextSampleEvent = getNextSampleTimeFMU(comp->fmuData);
  199. if (nextSampleEvent == -1)
  200. {
  201. eventInfo->nextEventTimeDefined = fmi2False;
  202. }
  203. else
  204. {
  205. eventInfo->nextEventTimeDefined = fmi2True;
  206. eventInfo->nextEventTime = nextSampleEvent;
  207. }
  208. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EventUpdate: Checked for Sample Events! Next Sample Event %g",eventInfo->nextEventTime)
  209. return fmi2OK;
  210. /* catch */
  211. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  212. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2EventUpdate: terminated by an assertion.")
  213. comp->_need_update = 1;
  214. return fmi2Error;
  215. }
  216. fmi2Status fmi2EventIteration(fmi2Component c, fmi2EventInfo *eventInfo)
  217. {
  218. fmi2Status status = fmi2OK;
  219. eventInfo->newDiscreteStatesNeeded = fmi2True;
  220. eventInfo->terminateSimulation = fmi2False;
  221. while (eventInfo->newDiscreteStatesNeeded && !eventInfo->terminateSimulation) {
  222. status = fmi2NewDiscreteStates(c, eventInfo);
  223. }
  224. return status;
  225. }
  226. /***************************************************
  227. Common Functions
  228. ****************************************************/
  229. const char* fmi2GetTypesPlatform() {
  230. return fmi2TypesPlatform;
  231. }
  232. const char* fmi2GetVersion() {
  233. return fmi2Version;
  234. }
  235. fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
  236. int i, j;
  237. ModelInstance *comp = (ModelInstance *)c;
  238. comp->loggingOn = loggingOn;
  239. for (j = 0; j < NUMBER_OF_CATEGORIES; j++) {
  240. comp->logCategories[j] = fmi2False;
  241. }
  242. for (i = 0; i < nCategories; i++) {
  243. fmi2Boolean categoryFound = fmi2False;
  244. for (j = 0; j < NUMBER_OF_CATEGORIES; j++) {
  245. if (strcmp(logCategoriesNames[j], categories[i]) == 0) {
  246. comp->logCategories[j] = loggingOn;
  247. categoryFound = fmi2True;
  248. break;
  249. }
  250. }
  251. if (!categoryFound) {
  252. comp->functions->logger(comp->componentEnvironment, comp->instanceName, fmi2Warning, logCategoriesNames[LOG_STATUSERROR],
  253. "logging category '%s' is not supported by model", categories[i]);
  254. }
  255. }
  256. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetDebugLogging")
  257. return fmi2OK;
  258. }
  259. fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, fmi2String fmuResourceLocation, const fmi2CallbackFunctions* functions,
  260. fmi2Boolean visible, fmi2Boolean loggingOn) {
  261. // ignoring arguments: fmuResourceLocation, visible
  262. ModelInstance *comp;
  263. if (!functions->logger) {
  264. return NULL;
  265. }
  266. if (!functions->allocateMemory || !functions->freeMemory) {
  267. functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error", "fmi2Instantiate: Missing callback function.");
  268. return NULL;
  269. }
  270. if (!instanceName || strlen(instanceName) == 0) {
  271. functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error", "fmi2Instantiate: Missing instance name.");
  272. return NULL;
  273. }
  274. if (strcmp(fmuGUID, MODEL_GUID) != 0) {
  275. functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error", "fmi2Instantiate: Wrong GUID %s. Expected %s.", fmuGUID, MODEL_GUID);
  276. return NULL;
  277. }
  278. comp = (ModelInstance *)functions->allocateMemory(1, sizeof(ModelInstance));
  279. if (comp) {
  280. DATA* fmudata = NULL;
  281. MODEL_DATA* modelData = NULL;
  282. SIMULATION_INFO* simInfo = NULL;
  283. threadData_t *threadData = NULL;
  284. int i;
  285. comp->instanceName = (fmi2String)functions->allocateMemory(1 + strlen(instanceName), sizeof(char));
  286. comp->GUID = (fmi2String)functions->allocateMemory(1 + strlen(fmuGUID), sizeof(char));
  287. fmudata = (DATA *)functions->allocateMemory(1, sizeof(DATA));
  288. modelData = (MODEL_DATA *)functions->allocateMemory(1, sizeof(MODEL_DATA));
  289. simInfo = (SIMULATION_INFO *)functions->allocateMemory(1, sizeof(SIMULATION_INFO));
  290. fmudata->modelData = modelData;
  291. fmudata->simulationInfo = simInfo;
  292. threadData = (threadData_t *)functions->allocateMemory(1, sizeof(threadData_t));
  293. memset(threadData, 0, sizeof(threadData_t));
  294. /*
  295. pthread_key_create(&fmu2_thread_data_key,NULL);
  296. pthread_setspecific(fmu2_thread_data_key, threadData);
  297. */
  298. comp->threadData = threadData;
  299. comp->fmuData = fmudata;
  300. if (!comp->fmuData) {
  301. functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error", "fmi2Instantiate: Could not initialize the global data structure file.");
  302. return NULL;
  303. }
  304. // set all categories to on or off. fmi2SetDebugLogging should be called to choose specific categories.
  305. for (i = 0; i < NUMBER_OF_CATEGORIES; i++) {
  306. comp->logCategories[i] = loggingOn;
  307. }
  308. }
  309. if (!comp || !comp->instanceName || !comp->GUID) {
  310. functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error", "fmi2Instantiate: Out of memory.");
  311. return NULL;
  312. }
  313. strcpy((char*)comp->instanceName, (const char*)instanceName);
  314. comp->type = fmuType;
  315. strcpy((char*)comp->GUID, (const char*)fmuGUID);
  316. comp->functions = functions;
  317. comp->componentEnvironment = functions->componentEnvironment;
  318. comp->loggingOn = loggingOn;
  319. comp->state = modelInstantiated;
  320. /* intialize modelData */
  321. fmu2_model_interface_setupDataStruc(comp->fmuData);
  322. useStream[LOG_STDOUT] = 1;
  323. useStream[LOG_ASSERT] = 1;
  324. initializeDataStruc(comp->fmuData, comp->threadData);
  325. /* setup model data with default start data */
  326. setDefaultStartValues(comp);
  327. setAllVarsToStart(comp->fmuData);
  328. setAllParamsToStart(comp->fmuData);
  329. comp->fmuData->callback->read_input_fmu(comp->fmuData->modelData, comp->fmuData->simulationInfo);
  330. #if !defined(OMC_MINIMAL_METADATA)
  331. modelInfoInit(&(comp->fmuData->modelData->modelDataXml));
  332. #endif
  333. /* read input vars */
  334. //input_function(comp->fmuData);
  335. /* initial sample and delay before initial the system */
  336. comp->fmuData->callback->callExternalObjectConstructors(comp->fmuData, comp->threadData);
  337. #if !defined(OMC_NUM_NONLINEAR_SYSTEMS) || OMC_NUM_NONLINEAR_SYSTEMS>0
  338. /* allocate memory for non-linear system solvers */
  339. initializeNonlinearSystems(comp->fmuData, comp->threadData);
  340. #endif
  341. #if !defined(OMC_NUM_LINEAR_SYSTEMS) || OMC_NUM_LINEAR_SYSTEMS>0
  342. /* allocate memory for non-linear system solvers */
  343. initializeLinearSystems(comp->fmuData, comp->threadData);
  344. #endif
  345. #if !defined(OMC_NUM_MIXED_SYSTEMS) || OMC_NUM_MIXED_SYSTEMS>0
  346. /* allocate memory for mixed system solvers */
  347. initializeMixedSystems(comp->fmuData, comp->threadData);
  348. #endif
  349. #if !defined(OMC_NO_STATESELECTION)
  350. /* allocate memory for state selection */
  351. initializeStateSetJacobians(comp->fmuData, comp->threadData);
  352. #endif
  353. #ifdef FMU_EXPERIMENTAL
  354. /* allocate memory for Jacobian */
  355. comp->_has_jacobian = !comp->fmuData->callback->initialAnalyticJacobianA(comp->fmuData, comp->threadData);
  356. #endif
  357. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2Instantiate: GUID=%s", fmuGUID)
  358. return comp;
  359. }
  360. void fmi2FreeInstance(fmi2Component c) {
  361. ModelInstance *comp = (ModelInstance *)c;
  362. if (!comp) return;
  363. if (invalidState(comp, "fmi2FreeInstance", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  364. return;
  365. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2FreeInstance")
  366. /* free simuation data */
  367. comp->functions->freeMemory(comp->fmuData->modelData);
  368. comp->functions->freeMemory(comp->fmuData->simulationInfo);
  369. /* free fmuData */
  370. comp->functions->freeMemory(comp->threadData);
  371. comp->functions->freeMemory(comp->fmuData);
  372. /* free instanceName & GUID */
  373. if (comp->instanceName) comp->functions->freeMemory((void*)comp->instanceName);
  374. if (comp->GUID) comp->functions->freeMemory((void*)comp->GUID);
  375. /* free comp */
  376. comp->functions->freeMemory(comp);
  377. }
  378. fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
  379. ModelInstance *comp = (ModelInstance *)c;
  380. if (invalidState(comp, "fmi2SetupExperiment", modelInstantiated))
  381. return fmi2Error;
  382. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetupExperiment: toleranceDefined=%d tolerance=%g startTime=%g stopTimeDefined=%d stopTime=%g", toleranceDefined, tolerance,
  383. startTime, stopTimeDefined, stopTime)
  384. comp->toleranceDefined = toleranceDefined;
  385. comp->tolerance = tolerance;
  386. comp->startTime = startTime;
  387. comp->stopTimeDefined = stopTimeDefined;
  388. comp->stopTime = stopTime;
  389. return fmi2OK;
  390. }
  391. fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
  392. ModelInstance *comp = (ModelInstance *)c;
  393. threadData_t *threadData = comp->threadData;
  394. double nextSampleEvent;
  395. threadData->currentErrorStage = ERROR_SIMULATION;
  396. if (invalidState(comp, "fmi2EnterInitializationMode", modelInstantiated))
  397. return fmi2Error;
  398. printf("PowerSystem first logging message...\n");
  399. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EnterInitializationMode...")
  400. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Testing access to component members...")
  401. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Tolerance = %g", comp->tolerance)
  402. /* set zero-crossing tolerance */
  403. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Setting zero crossing tolerance...")
  404. setZCtol(comp->tolerance);
  405. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Setting start values...")
  406. setStartValues(comp);
  407. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Copying start values to init values...")
  408. copyStartValuestoInitValues(comp->fmuData);
  409. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "MMC_TRY_INTERNAL...")
  410. /* try */
  411. MMC_TRY_INTERNAL(simulationJumpBuffer)
  412. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "initialization...")
  413. if (initialization(comp->fmuData, comp->threadData, "", "", 0.0, 5)) {
  414. comp->state = modelError;
  415. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2EnterInitializationMode: failed")
  416. return fmi2Error;
  417. }
  418. else
  419. {
  420. /*TODO: Simulation stop time is need to calculate in before hand all sample events
  421. We shouldn't generate them all in beforehand */
  422. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "initSample...")
  423. initSample(comp->fmuData, comp->threadData, comp->fmuData->localData[0]->timeValue, 100 /*should be stopTime*/);
  424. #if !defined(OMC_NDELAY_EXPRESSIONS) || OMC_NDELAY_EXPRESSIONS>0
  425. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "initDelay...")
  426. initDelay(comp->fmuData, comp->fmuData->localData[0]->timeValue);
  427. #endif
  428. /* due to an event overwrite old values */
  429. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "overwriteOldSimulationData...")
  430. overwriteOldSimulationData(comp->fmuData);
  431. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "comp->eventInfo.terminateSimulation...")
  432. comp->eventInfo.terminateSimulation = fmi2False;
  433. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "comp->eventInfo.valuesOfContinuousStatesChanged...")
  434. comp->eventInfo.valuesOfContinuousStatesChanged = fmi2True;
  435. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Getting next sample event...")
  436. /* Get next event time (sample calls)*/
  437. nextSampleEvent = 0;
  438. nextSampleEvent = getNextSampleTimeFMU(comp->fmuData);
  439. if (nextSampleEvent == -1) {
  440. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "No next sample event...")
  441. comp->eventInfo.nextEventTimeDefined = fmi2False;
  442. } else {
  443. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Next sample event found...")
  444. comp->eventInfo.nextEventTimeDefined = fmi2True;
  445. comp->eventInfo.nextEventTime = nextSampleEvent;
  446. fmi2EventUpdate(comp, &(comp->eventInfo));
  447. }
  448. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "Setting comp->state to modelInitializationMode...")
  449. comp->state = modelInitializationMode;
  450. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2EnterInitializationMode: succeed")
  451. return fmi2OK;
  452. }
  453. /* catch */
  454. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  455. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2EnterInitializationMode: terminated by an assertion.")
  456. return fmi2Error;
  457. }
  458. fmi2Status fmi2ExitInitializationMode(fmi2Component c) {
  459. ModelInstance *comp = (ModelInstance *)c;
  460. if (invalidState(comp, "fmi2ExitInitializationMode", modelInitializationMode))
  461. return fmi2Error;
  462. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2ExitInitializationMode...")
  463. comp->state = modelEventMode;
  464. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2ExitInitializationMode: succeed")
  465. return fmi2OK;
  466. }
  467. fmi2Status fmi2Terminate(fmi2Component c) {
  468. ModelInstance *comp = (ModelInstance *)c;
  469. if (invalidState(comp, "fmi2Terminate", modelEventMode|modelContinuousTimeMode))
  470. return fmi2Error;
  471. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2Terminate")
  472. /* call external objects destructors */
  473. comp->fmuData->callback->callExternalObjectDestructors(comp->fmuData, comp->threadData);
  474. #if !defined(OMC_NUM_NONLINEAR_SYSTEMS) || OMC_NUM_NONLINEAR_SYSTEMS>0
  475. /* free nonlinear system data */
  476. freeNonlinearSystems(comp->fmuData, comp->threadData);
  477. #endif
  478. #if !defined(OMC_NUM_MIXED_SYSTEMS) || OMC_NUM_MIXED_SYSTEMS>0
  479. /* free mixed system data */
  480. freeMixedSystems(comp->fmuData, comp->threadData);
  481. #endif
  482. #if !defined(OMC_NUM_LINEAR_SYSTEMS) || OMC_NUM_LINEAR_SYSTEMS>0
  483. /* free linear system data */
  484. freeLinearSystems(comp->fmuData, comp->threadData);
  485. #endif
  486. #if !defined(OMC_NO_STATESELECTION)
  487. /* free stateset data */
  488. freeStateSetData(comp->fmuData);
  489. #endif
  490. /* free data struct */
  491. deInitializeDataStruc(comp->fmuData);
  492. comp->state = modelTerminated;
  493. return fmi2OK;
  494. }
  495. /*!
  496. * Is called by the environment to reset the FMU after a simulation run. Before starting a new run, fmi2EnterInitializationMode has to be called.
  497. */
  498. fmi2Status fmi2Reset(fmi2Component c) {
  499. ModelInstance* comp = (ModelInstance *)c;
  500. if (invalidState(comp, "fmi2Reset", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  501. return fmi2Error;
  502. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2Reset")
  503. if (comp->state & modelTerminated) {
  504. /* intialize modelData */
  505. fmu2_model_interface_setupDataStruc(comp->fmuData);
  506. initializeDataStruc(comp->fmuData, comp->threadData);
  507. }
  508. /* reset the values to start */
  509. setDefaultStartValues(comp);
  510. setAllVarsToStart(comp->fmuData);
  511. setAllParamsToStart(comp->fmuData);
  512. comp->state = modelInstantiated;
  513. return fmi2OK;
  514. }
  515. fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
  516. int i;
  517. ModelInstance *comp = (ModelInstance *)c;
  518. if (invalidState(comp, "fmi2GetReal", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  519. return fmi2Error;
  520. if (nvr > 0 && nullPointer(comp, "fmi2GetReal", "vr[]", vr))
  521. return fmi2Error;
  522. if (nvr > 0 && nullPointer(comp, "fmi2GetReal", "value[]", value))
  523. return fmi2Error;
  524. #if NUMBER_OF_REALS > 0
  525. for (i = 0; i < nvr; i++) {
  526. if (vrOutOfRange(comp, "fmi2GetReal", vr[i], NUMBER_OF_REALS))
  527. return fmi2Error;
  528. value[i] = getReal(comp, vr[i]); // to be implemented by the includer of this file
  529. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetReal: #r%u# = %.16g", vr[i], value[i])
  530. }
  531. #endif
  532. return fmi2OK;
  533. }
  534. fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
  535. int i;
  536. ModelInstance *comp = (ModelInstance *)c;
  537. if (invalidState(comp, "fmi2GetInteger", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  538. return fmi2Error;
  539. if (nvr > 0 && nullPointer(comp, "fmi2GetInteger", "vr[]", vr))
  540. return fmi2Error;
  541. if (nvr > 0 && nullPointer(comp, "fmi2GetInteger", "value[]", value))
  542. return fmi2Error;
  543. for (i = 0; i < nvr; i++) {
  544. if (vrOutOfRange(comp, "fmi2GetInteger", vr[i], NUMBER_OF_INTEGERS))
  545. return fmi2Error;
  546. value[i] = getInteger(comp, vr[i]); // to be implemented by the includer of this file
  547. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetInteger: #i%u# = %d", vr[i], value[i])
  548. }
  549. return fmi2OK;
  550. }
  551. fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]){
  552. int i;
  553. ModelInstance *comp = (ModelInstance *)c;
  554. if (invalidState(comp, "fmi2GetBoolean", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  555. return fmi2Error;
  556. if (nvr > 0 && nullPointer(comp, "fmi2GetBoolean", "vr[]", vr))
  557. return fmi2Error;
  558. if (nvr > 0 && nullPointer(comp, "fmi2GetBoolean", "value[]", value))
  559. return fmi2Error;
  560. for (i = 0; i < nvr; i++) {
  561. if (vrOutOfRange(comp, "fmi2GetBoolean", vr[i], NUMBER_OF_BOOLEANS))
  562. return fmi2Error;
  563. value[i] = getBoolean(comp, vr[i]); // to be implemented by the includer of this file
  564. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetBoolean: #b%u# = %s", vr[i], value[i]? "true" : "false")
  565. }
  566. return fmi2OK;
  567. }
  568. fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
  569. int i;
  570. ModelInstance *comp = (ModelInstance *)c;
  571. if (invalidState(comp, "fmi2GetString", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  572. return fmi2Error;
  573. if (nvr>0 && nullPointer(comp, "fmi2GetString", "vr[]", vr))
  574. return fmi2Error;
  575. if (nvr>0 && nullPointer(comp, "fmi2GetString", "value[]", value))
  576. return fmi2Error;
  577. for (i=0; i<nvr; i++) {
  578. if (vrOutOfRange(comp, "fmi2GetString", vr[i], NUMBER_OF_STRINGS))
  579. return fmi2Error;
  580. value[i] = getString(comp, vr[i]); // to be implemented by the includer of this file
  581. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetString: #s%u# = '%s'", vr[i], value[i])
  582. }
  583. return fmi2OK;
  584. }
  585. fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
  586. int i;
  587. ModelInstance *comp = (ModelInstance *)c;
  588. if (invalidState(comp, "fmi2SetReal", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode))
  589. return fmi2Error;
  590. if (nvr > 0 && nullPointer(comp, "fmi2SetReal", "vr[]", vr))
  591. return fmi2Error;
  592. if (nvr > 0 && nullPointer(comp, "fmi2SetReal", "value[]", value))
  593. return fmi2Error;
  594. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetReal: nvr = %d", nvr)
  595. // no check whether setting the value is allowed in the current state
  596. for (i = 0; i < nvr; i++) {
  597. if (vrOutOfRange(comp, "fmi2SetReal", vr[i], NUMBER_OF_REALS+NUMBER_OF_STATES))
  598. return fmi2Error;
  599. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetReal: #r%d# = %.16g", vr[i], value[i])
  600. if (setReal(comp, vr[i], value[i]) != fmi2OK) // to be implemented by the includer of this file
  601. return fmi2Error;
  602. }
  603. comp->_need_update = 1;
  604. return fmi2OK;
  605. }
  606. fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
  607. int i;
  608. ModelInstance *comp = (ModelInstance *)c;
  609. if (invalidState(comp, "fmi2SetInteger", modelInstantiated|modelInitializationMode|modelEventMode))
  610. return fmi2Error;
  611. if (nvr > 0 && nullPointer(comp, "fmi2SetInteger", "vr[]", vr))
  612. return fmi2Error;
  613. if (nvr > 0 && nullPointer(comp, "fmi2SetInteger", "value[]", value))
  614. return fmi2Error;
  615. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetInteger: nvr = %d", nvr)
  616. for (i = 0; i < nvr; i++) {
  617. if (vrOutOfRange(comp, "fmi2SetInteger", vr[i], NUMBER_OF_INTEGERS))
  618. return fmi2Error;
  619. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetInteger: #i%d# = %d", vr[i], value[i])
  620. if (setInteger(comp, vr[i], value[i]) != fmi2OK) // to be implemented by the includer of this file
  621. return fmi2Error;
  622. }
  623. comp->_need_update = 1;
  624. return fmi2OK;
  625. }
  626. fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
  627. int i;
  628. ModelInstance *comp = (ModelInstance *)c;
  629. if (invalidState(comp, "fmi2SetBoolean", modelInstantiated|modelInitializationMode|modelEventMode))
  630. return fmi2Error;
  631. if (nvr>0 && nullPointer(comp, "fmi2SetBoolean", "vr[]", vr))
  632. return fmi2Error;
  633. if (nvr>0 && nullPointer(comp, "fmi2SetBoolean", "value[]", value))
  634. return fmi2Error;
  635. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetBoolean: nvr = %d", nvr)
  636. for (i = 0; i < nvr; i++) {
  637. if (vrOutOfRange(comp, "fmi2SetBoolean", vr[i], NUMBER_OF_BOOLEANS))
  638. return fmi2Error;
  639. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetBoolean: #b%d# = %s", vr[i], value[i] ? "true" : "false")
  640. if (setBoolean(comp, vr[i], value[i]) != fmi2OK) // to be implemented by the includer of this file
  641. return fmi2Error;
  642. }
  643. comp->_need_update = 1;
  644. return fmi2OK;
  645. }
  646. fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
  647. int i, n;
  648. ModelInstance *comp = (ModelInstance *)c;
  649. if (invalidState(comp, "fmi2SetString", modelInstantiated|modelInitializationMode|modelEventMode))
  650. return fmi2Error;
  651. if (nvr>0 && nullPointer(comp, "fmi2SetString", "vr[]", vr))
  652. return fmi2Error;
  653. if (nvr>0 && nullPointer(comp, "fmi2SetString", "value[]", value))
  654. return fmi2Error;
  655. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetString: nvr = %d", nvr)
  656. for (i = 0; i < nvr; i++) {
  657. if (vrOutOfRange(comp, "fmi2SetString", vr[i], NUMBER_OF_STRINGS))
  658. return fmi2Error;
  659. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetString: #s%d# = '%s'", vr[i], value[i])
  660. if (setString(comp, vr[i], value[i]) != fmi2OK) // to be implemented by the includer of this file
  661. return fmi2Error;
  662. }
  663. comp->_need_update = 1;
  664. return fmi2OK;
  665. }
  666. fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
  667. return unsupportedFunction(c, "fmi2GetFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  668. }
  669. fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {
  670. return unsupportedFunction(c, "fmi2SetFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  671. }
  672. fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
  673. return unsupportedFunction(c, "fmi2FreeFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  674. }
  675. fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) {
  676. return unsupportedFunction(c, "fmi2SerializedFMUstateSize", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  677. }
  678. fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) {
  679. return unsupportedFunction(c, "fmi2SerializeFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  680. }
  681. fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
  682. return unsupportedFunction(c, "fmi2DeSerializeFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  683. }
  684. fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, const fmi2ValueReference vKnown_ref[] , size_t nKnown,
  685. const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
  686. #ifndef FMU_EXPERIMENTAL
  687. return unsupportedFunction(c, "fmi2GetDirectionalDerivative", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  688. #else
  689. int i,j;
  690. ModelInstance *comp = (ModelInstance *)c;
  691. if (invalidState(comp, "fmi2GetDirectionalDerivative", modelInstantiated|modelEventMode|modelContinuousTimeMode))
  692. return fmi2Error;
  693. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetDirectionalDerivative")
  694. if (!comp->_has_jacobian)
  695. return unsupportedFunction(c, "fmi2GetDirectionalDerivative", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
  696. /***************************************/
  697. #if NUMBER_OF_STATES>0
  698. // This code assumes that the FMU variables are always sorted,
  699. // states first and then derivatives.
  700. // This is true for the actual OMC FMUs.
  701. // Anyway we'll check that the references are in the valid range
  702. for (i = 0; i < nUnknown; i++) {
  703. if (vUnknown_ref[i]>=NUMBER_OF_STATES)
  704. // We are only computing the A part of the Jacobian for now
  705. // so unknowns can only be states
  706. return fmi2Error;
  707. }
  708. for (i = 0; i < nKnown; i++) {
  709. if (vKnown_ref[i]>=2*NUMBER_OF_STATES) {
  710. // We are only computing the A part of the Jacobian for now
  711. // so knowns can only be states derivatives
  712. return fmi2Error;
  713. }
  714. }
  715. comp->fmuData->callback->functionFMIJacobian(comp->fmuData, comp->threadData, vUnknown_ref, nUnknown, vKnown_ref, nKnown, (double*)dvKnown, dvUnknown);
  716. #endif
  717. /***************************************/
  718. return fmi2OK;
  719. #endif
  720. }
  721. /***************************************************
  722. Functions for FMI2 for Model Exchange
  723. ****************************************************/
  724. fmi2Status fmi2EnterEventMode(fmi2Component c) {
  725. ModelInstance *comp = (ModelInstance *)c;
  726. if (invalidState(comp, "fmi2EnterEventMode", modelInitializationMode|modelContinuousTimeMode|modelEventMode))
  727. return fmi2Error;
  728. FILTERED_LOG(comp, fmi2OK, LOG_EVENTS, "fmi2EnterEventMode")
  729. comp->state = modelEventMode;
  730. return fmi2OK;
  731. }
  732. fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo* eventInfo) {
  733. ModelInstance *comp = (ModelInstance *)c;
  734. double nextSampleEvent = 0;
  735. fmi2Status returnValue = fmi2OK;
  736. if (invalidState(comp, "fmi2NewDiscreteStates", modelEventMode))
  737. return fmi2Error;
  738. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2NewDiscreteStates")
  739. eventInfo->newDiscreteStatesNeeded = fmi2False;
  740. eventInfo->terminateSimulation = fmi2False;
  741. eventInfo->nominalsOfContinuousStatesChanged = fmi2False;
  742. eventInfo->valuesOfContinuousStatesChanged = fmi2False;
  743. eventInfo->nextEventTimeDefined = fmi2False;
  744. eventInfo->nextEventTime = 0;
  745. returnValue = fmi2EventUpdate(comp, eventInfo);
  746. return returnValue;
  747. }
  748. fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) {
  749. ModelInstance *comp = (ModelInstance *)c;
  750. if (invalidState(comp, "fmi2EnterContinuousTimeMode", modelEventMode))
  751. return fmi2Error;
  752. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL,"fmi2EnterContinuousTimeMode")
  753. comp->state = modelContinuousTimeMode;
  754. return fmi2OK;
  755. }
  756. fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint, fmi2Boolean* enterEventMode, fmi2Boolean* terminateSimulation) {
  757. ModelInstance *comp = (ModelInstance *)c;
  758. threadData_t *threadData = comp->threadData;
  759. if (invalidState(comp, "fmi2CompletedIntegratorStep", modelContinuousTimeMode))
  760. return fmi2Error;
  761. if (nullPointer(comp, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode))
  762. return fmi2Error;
  763. if (nullPointer(comp, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation))
  764. return fmi2Error;
  765. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL,"fmi2CompletedIntegratorStep")
  766. /* try */
  767. MMC_TRY_INTERNAL(simulationJumpBuffer)
  768. comp->fmuData->callback->functionAlgebraics(comp->fmuData, comp->threadData);
  769. comp->fmuData->callback->output_function(comp->fmuData, comp->threadData);
  770. comp->fmuData->callback->function_storeDelayed(comp->fmuData, comp->threadData);
  771. storePreValues(comp->fmuData);
  772. *enterEventMode = fmi2False;
  773. *terminateSimulation = fmi2False;
  774. /******** check state selection ********/
  775. #if !defined(OMC_NO_STATESELECTION)
  776. if (stateSelection(comp->fmuData, comp->threadData, 1, 0))
  777. {
  778. /* if new set is calculated reinit the solver */
  779. *enterEventMode = fmi2True;
  780. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL,"fmi2CompletedIntegratorStep: Need to iterate state values changed!")
  781. }
  782. #endif
  783. /* TODO: fix the extrapolation in non-linear system
  784. * then we can stop to save all variables in
  785. * in the whole ringbuffer
  786. */
  787. overwriteOldSimulationData(comp->fmuData);
  788. return fmi2OK;
  789. /* catch */
  790. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  791. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2CompletedIntegratorStep: terminated by an assertion.")
  792. return fmi2Error;
  793. }
  794. fmi2Status fmi2SetTime(fmi2Component c, fmi2Real t) {
  795. ModelInstance *comp = (ModelInstance *)c;
  796. if (invalidState(comp, "fmi2SetTime", modelInstantiated|modelEventMode|modelContinuousTimeMode))
  797. return fmi2Error;
  798. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetTime: time=%.16g", t)
  799. comp->fmuData->localData[0]->timeValue = t;
  800. comp->_need_update = 1;
  801. return fmi2OK;
  802. }
  803. fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx) {
  804. ModelInstance *comp = (ModelInstance *)c;
  805. int i;
  806. /* According to FMI RC2 specification fmi2SetContinuousStates should only be allowed in Continuous-Time Mode.
  807. * The following code is done only to make the FMUs compatible with Dymola because Dymola is trying to call fmi2SetContinuousStates after fmi2EnterInitializationMode.
  808. */
  809. if (invalidState(comp, "fmi2SetContinuousStates", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode))
  810. /*if (invalidState(comp, "fmi2SetContinuousStates", modelContinuousTimeMode))*/
  811. return fmi2Error;
  812. if (invalidNumber(comp, "fmi2SetContinuousStates", "nx", nx, NUMBER_OF_STATES))
  813. return fmi2Error;
  814. if (nullPointer(comp, "fmi2SetContinuousStates", "x[]", x))
  815. return fmi2Error;
  816. #if NUMBER_OF_REALS>0
  817. for (i = 0; i < nx; i++) {
  818. fmi2ValueReference vr = vrStates[i];
  819. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2SetContinuousStates: #r%d# = %.16g", vr, x[i])
  820. if (vr < 0 || vr >= NUMBER_OF_REALS|| setReal(comp, vr, x[i]) != fmi2OK) { // to be implemented by the includer of this file
  821. return fmi2Error;
  822. }
  823. }
  824. #endif
  825. comp->_need_update = 1;
  826. return fmi2OK;
  827. }
  828. fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) {
  829. int i;
  830. ModelInstance* comp = (ModelInstance *)c;
  831. threadData_t *threadData = comp->threadData;
  832. if (invalidState(comp, "fmi2GetDerivatives", modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  833. return fmi2Error;
  834. if (invalidNumber(comp, "fmi2GetDerivatives", "nx", nx, NUMBER_OF_STATES))
  835. return fmi2Error;
  836. if (nullPointer(comp, "fmi2GetDerivatives", "derivatives[]", derivatives))
  837. return fmi2Error;
  838. /* try */
  839. MMC_TRY_INTERNAL(simulationJumpBuffer)
  840. if (comp->_need_update){
  841. comp->fmuData->callback->functionODE(comp->fmuData, comp->threadData);
  842. overwriteOldSimulationData(comp->fmuData);
  843. comp->_need_update = 0;
  844. }
  845. #if NUMBER_OF_STATES>0
  846. for (i = 0; i < nx; i++) {
  847. fmi2ValueReference vr = vrStatesDerivatives[i];
  848. derivatives[i] = getReal(comp, vr); // to be implemented by the includer of this file
  849. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetDerivatives: #r%d# = %.16g", vr, derivatives[i])
  850. }
  851. #endif
  852. return fmi2OK;
  853. /* catch */
  854. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  855. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2GetDerivatives: terminated by an assertion.")
  856. return fmi2Error;
  857. }
  858. fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t nx) {
  859. int i;
  860. ModelInstance *comp = (ModelInstance *)c;
  861. threadData_t *threadData = comp->threadData;
  862. /* According to FMI RC2 specification fmi2GetEventIndicators should only be allowed in Event Mode, Continuous-Time Mode & terminated.
  863. * The following code is done only to make the FMUs compatible with Dymola because Dymola is trying to call fmi2GetEventIndicators after fmi2EnterInitializationMode.
  864. */
  865. if (invalidState(comp, "fmi2GetEventIndicators", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  866. /*if (invalidState(comp, "fmi2GetEventIndicators", modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))*/
  867. return fmi2Error;
  868. if (invalidNumber(comp, "fmi2GetEventIndicators", "nx", nx, NUMBER_OF_EVENT_INDICATORS))
  869. return fmi2Error;
  870. /* try */
  871. MMC_TRY_INTERNAL(simulationJumpBuffer)
  872. #if NUMBER_OF_EVENT_INDICATORS>0
  873. /* eval needed equations*/
  874. if (comp->_need_update){
  875. comp->fmuData->callback->functionODE(comp->fmuData, comp->threadData);
  876. comp->_need_update = 0;
  877. }
  878. comp->fmuData->callback->function_ZeroCrossings(comp->fmuData, comp->threadData, comp->fmuData->simulationInfo->zeroCrossings);
  879. for (i = 0; i < nx; i++) {
  880. eventIndicators[i] = comp->fmuData->simulationInfo->zeroCrossings[i];
  881. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetEventIndicators: z%d = %.16g", i, eventIndicators[i])
  882. }
  883. #endif
  884. return fmi2OK;
  885. /* catch */
  886. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  887. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "error", "fmi2GetEventIndicators: terminated by an assertion.");
  888. return fmi2Error;
  889. }
  890. fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real x[], size_t nx) {
  891. int i;
  892. ModelInstance *comp = (ModelInstance *)c;
  893. if (invalidState(comp, "fmi2GetContinuousStates", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  894. return fmi2Error;
  895. if (invalidNumber(comp, "fmi2GetContinuousStates", "nx", nx, NUMBER_OF_STATES))
  896. return fmi2Error;
  897. if (nullPointer(comp, "fmi2GetContinuousStates", "states[]", x))
  898. return fmi2Error;
  899. #if NUMBER_OF_REALS>0
  900. for (i = 0; i < nx; i++) {
  901. fmi2ValueReference vr = vrStates[i];
  902. x[i] = getReal(comp, vr); // to be implemented by the includer of this file
  903. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetContinuousStates: #r%u# = %.16g", vr, x[i])
  904. }
  905. #endif
  906. return fmi2OK;
  907. }
  908. fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) {
  909. int i;
  910. ModelInstance *comp = (ModelInstance *)c;
  911. if (invalidState(comp, "fmi2GetNominalsOfContinuousStates", modelInstantiated|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  912. return fmi2Error;
  913. if (invalidNumber(comp, "fmi2GetNominalsOfContinuousStates", "nx", nx, NUMBER_OF_STATES))
  914. return fmi2Error;
  915. if (nullPointer(comp, "fmi2GetNominalsOfContinuousStates", "x_nominal[]", x_nominal))
  916. return fmi2Error;
  917. x_nominal[0] = 1;
  918. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetNominalsOfContinuousStates: x_nominal[0..%d] = 1.0", nx-1)
  919. for (i = 0; i < nx; i++)
  920. x_nominal[i] = 1;
  921. return fmi2OK;
  922. }
  923. /***************************************************
  924. Functions for FMI2 for Co-Simulation
  925. ****************************************************/
  926. fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[]) {
  927. // TODO Write code here
  928. return fmi2OK;
  929. }
  930. fmi2Status fmi2GetRealOutputDerivatives (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[]) {
  931. // TODO Write code here
  932. return fmi2OK;
  933. }
  934. fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
  935. ModelInstance *comp = (ModelInstance *)c;
  936. fmi2CallbackFunctions* functions = (fmi2CallbackFunctions*)comp->functions;
  937. int i, zc_event = 0, time_event = 0;
  938. fmi2Status status = fmi2OK;
  939. fmi2Real* states = (fmi2Real*)functions->allocateMemory(NUMBER_OF_STATES, sizeof(fmi2Real));
  940. fmi2Real* states_der = (fmi2Real*)functions->allocateMemory(NUMBER_OF_STATES, sizeof(fmi2Real));
  941. fmi2Real* event_indicators = (fmi2Real*)functions->allocateMemory(NUMBER_OF_EVENT_INDICATORS, sizeof(fmi2Real));
  942. fmi2Real* event_indicators_prev = (fmi2Real*)functions->allocateMemory(NUMBER_OF_EVENT_INDICATORS, sizeof(fmi2Real));
  943. fmi2Real t = comp->fmuData->localData[0]->timeValue;
  944. fmi2Real tNext, tEnd;
  945. fmi2Boolean enterEventMode = fmi2False, terminateSimulation = fmi2False;
  946. fmi2EventInfo eventInfo;
  947. eventInfo.newDiscreteStatesNeeded = fmi2False;
  948. eventInfo.terminateSimulation = fmi2False;
  949. eventInfo.nominalsOfContinuousStatesChanged = fmi2False;
  950. eventInfo.valuesOfContinuousStatesChanged = fmi2True;
  951. eventInfo.nextEventTimeDefined = fmi2False;
  952. eventInfo.nextEventTime = -0.0;
  953. /* fprintf(stderr, "DoStep %g + %g State: %d\n", currentCommunicationPoint, communicationStepSize, comp->state); */
  954. fmi2EnterEventMode(c);
  955. fmi2EventIteration(c, &eventInfo);
  956. fmi2EnterContinuousTimeMode(c);
  957. if (NUMBER_OF_STATES > 0)
  958. {
  959. status = fmi2GetDerivatives(c, states_der, NUMBER_OF_STATES);
  960. if (status != fmi2OK)
  961. {
  962. functions->freeMemory(states);
  963. functions->freeMemory(states_der);
  964. functions->freeMemory(event_indicators);
  965. functions->freeMemory(event_indicators_prev);
  966. return fmi2Error;
  967. }
  968. status = fmi2GetContinuousStates(c, states, NUMBER_OF_STATES);
  969. if (status != fmi2OK)
  970. {
  971. functions->freeMemory(states);
  972. functions->freeMemory(states_der);
  973. functions->freeMemory(event_indicators);
  974. functions->freeMemory(event_indicators_prev);
  975. return fmi2Error;
  976. }
  977. }
  978. if (NUMBER_OF_EVENT_INDICATORS > 0)
  979. {
  980. status = fmi2GetEventIndicators(c, event_indicators_prev, NUMBER_OF_EVENT_INDICATORS);
  981. if (status != fmi2OK)
  982. {
  983. functions->freeMemory(states);
  984. functions->freeMemory(states_der);
  985. functions->freeMemory(event_indicators);
  986. functions->freeMemory(event_indicators_prev);
  987. return fmi2Error;
  988. }
  989. }
  990. tNext = currentCommunicationPoint + communicationStepSize;
  991. /* adjust tNext step to get tEnd exactly */
  992. if (comp->stopTimeDefined)
  993. {
  994. tEnd = comp->stopTime;
  995. }
  996. else
  997. {
  998. tEnd = currentCommunicationPoint + 2*communicationStepSize + 1;
  999. }
  1000. if(tNext > tEnd - communicationStepSize/1e16) {
  1001. tNext = tEnd;
  1002. }
  1003. /* adjust for time events */
  1004. if (eventInfo.nextEventTimeDefined && (tNext >= eventInfo.nextEventTime)) {
  1005. tNext = eventInfo.nextEventTime;
  1006. time_event = 1;
  1007. }
  1008. fmi2SetTime(c, tNext);
  1009. /* integrate */
  1010. for (i = 0; i < NUMBER_OF_STATES; i++) {
  1011. states[i] = states[i] + communicationStepSize * states_der[i];
  1012. }
  1013. /* set the continuous states */
  1014. if (NUMBER_OF_STATES > 0)
  1015. {
  1016. status = fmi2SetContinuousStates(c, states, NUMBER_OF_STATES);
  1017. if (status != fmi2OK)
  1018. {
  1019. functions->freeMemory(states);
  1020. functions->freeMemory(states_der);
  1021. functions->freeMemory(event_indicators);
  1022. functions->freeMemory(event_indicators_prev);
  1023. return fmi2Error;
  1024. }
  1025. }
  1026. /* signal completed integrator step */
  1027. status = fmi2CompletedIntegratorStep(c, fmi2True, &enterEventMode, &terminateSimulation);
  1028. if (status != fmi2OK)
  1029. {
  1030. functions->freeMemory(states);
  1031. functions->freeMemory(states_der);
  1032. functions->freeMemory(event_indicators);
  1033. functions->freeMemory(event_indicators_prev);
  1034. return fmi2Error;
  1035. }
  1036. /* check for events */
  1037. if (NUMBER_OF_EVENT_INDICATORS > 0)
  1038. {
  1039. status = fmi2GetEventIndicators(c, event_indicators, NUMBER_OF_EVENT_INDICATORS);
  1040. if (status != fmi2OK)
  1041. {
  1042. functions->freeMemory(states);
  1043. functions->freeMemory(states_der);
  1044. functions->freeMemory(event_indicators);
  1045. functions->freeMemory(event_indicators_prev);
  1046. return fmi2Error;
  1047. }
  1048. for (i = 0; i < NUMBER_OF_EVENT_INDICATORS; i++)
  1049. {
  1050. if (event_indicators[i]*event_indicators_prev[i] < 0) {
  1051. zc_event = 1;
  1052. break;
  1053. }
  1054. }
  1055. /* fprintf(stderr, "enterEventMode = %d, zc_event = %d, time_event = %d\n", enterEventMode, zc_event, time_event); */
  1056. if (enterEventMode || zc_event || time_event) {
  1057. fmi2EnterEventMode(c);
  1058. fmi2EventIteration(c, &eventInfo);
  1059. if(eventInfo.valuesOfContinuousStatesChanged)
  1060. fmi2GetContinuousStates(c, states, NUMBER_OF_STATES);
  1061. if( eventInfo.nominalsOfContinuousStatesChanged)
  1062. fmi2GetNominalsOfContinuousStates(c, states, NUMBER_OF_STATES);
  1063. fmi2GetEventIndicators(c, event_indicators_prev, NUMBER_OF_EVENT_INDICATORS);
  1064. fmi2EnterContinuousTimeMode(c);
  1065. }
  1066. }
  1067. functions->freeMemory(states);
  1068. functions->freeMemory(states_der);
  1069. functions->freeMemory(event_indicators);
  1070. functions->freeMemory(event_indicators_prev);
  1071. return fmi2OK;
  1072. }
  1073. fmi2Status fmi2CancelStep(fmi2Component c) {
  1074. // TODO Write code here
  1075. return fmi2OK;
  1076. }
  1077. fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status* value) {
  1078. // TODO Write code here
  1079. return fmi2OK;
  1080. }
  1081. fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real* value) {
  1082. // TODO Write code here
  1083. return fmi2OK;
  1084. }
  1085. fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value) {
  1086. // TODO Write code here
  1087. return fmi2OK;
  1088. }
  1089. fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value) {
  1090. // TODO Write code here
  1091. return fmi2OK;
  1092. }
  1093. fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String* value) {
  1094. // TODO Write code here
  1095. return fmi2OK;
  1096. }
  1097. // ---------------------------------------------------------------------------
  1098. // FMI functions: set external functions
  1099. // ---------------------------------------------------------------------------
  1100. fmi2Status fmi2SetExternalFunction(fmi2Component c, fmi2ValueReference vr[], size_t nvr, const void* value[])
  1101. {
  1102. unsigned int i=0;
  1103. ModelInstance* comp = (ModelInstance *)c;
  1104. if (invalidState(comp, "fmi2Terminate", modelInstantiated))
  1105. return fmi2Error;
  1106. if (nvr>0 && nullPointer(comp, "fmi2SetExternalFunction", "vr[]", vr))
  1107. return fmi2Error;
  1108. if (nvr>0 && nullPointer(comp, "fmi2SetExternalFunction", "value[]", value))
  1109. return fmi2Error;
  1110. if (comp->loggingOn) comp->functions->logger(c, comp->instanceName, fmi2OK, "log",
  1111. "fmi2SetExternalFunction");
  1112. // no check wether setting the value is allowed in the current state
  1113. for (i=0; i<nvr; i++) {
  1114. if (vrOutOfRange(comp, "fmi2SetExternalFunction", vr[i], NUMBER_OF_EXTERNALFUNCTIONS))
  1115. return fmi2Error;
  1116. if (setExternalFunction(comp, vr[i],value[i]) != fmi2OK) // to be implemented by the includer of this file
  1117. return fmi2Error;
  1118. }
  1119. return fmi2OK;
  1120. }
  1121. #ifdef FMU_EXPERIMENTAL
  1122. fmi2Status fmi2GetSpecificDerivatives(fmi2Component c, fmi2Real derivatives[], const fmi2ValueReference dr[], size_t nvr) {
  1123. int i,nx;
  1124. ModelInstance* comp = (ModelInstance *)c;
  1125. threadData_t *threadData = comp->threadData;
  1126. /* TODO
  1127. if (invalidState(comp, "fmi2GetSpecificDerivatives", modelEventMode|modelContinuousTimeMode|modelTerminated|modelError))
  1128. return fmi2Error;
  1129. if (invalidNumber(comp, "fmi2GetSpecificDerivatives", "nx", nx, NUMBER_OF_STATES))
  1130. return fmi2Error;
  1131. if (nullPointer(comp, "fmi2GetSpecificDerivatives", "derivatives[]", derivatives))
  1132. return fmi2Error;
  1133. */
  1134. /* try */
  1135. MMC_TRY_INTERNAL(simulationJumpBuffer)
  1136. #if NUMBER_OF_STATES>0
  1137. for (i = 0; i < nvr; i++) {
  1138. // This assumes that OMC layouts first the states then the derivatives
  1139. nx = dr[i]-NUMBER_OF_STATES;
  1140. comp->fmuData->callback->functionODEPartial(comp->fmuData, comp->threadData, nx);
  1141. derivatives[i] = getReal(comp, dr[i]); // to be implemented by the includer of this file
  1142. FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2GetSpecificDerivatives: #r%d# = %.16g", dr[i], derivatives[i])
  1143. }
  1144. #endif
  1145. return fmi2OK;
  1146. /* catch */
  1147. MMC_CATCH_INTERNAL(simulationJumpBuffer)
  1148. FILTERED_LOG(comp, fmi2Error, LOG_FMI2_CALL, "fmi2GetSpecificDerivatives: terminated by an assertion.")
  1149. return fmi2Error;
  1150. }
  1151. #endif