2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 FMILIB_License.txt file for more details.
13 You should have received a copy of the FMILIB_License.txt file
14 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
20 #include <fmu_dummy/fmu1_model.h>
22 /* Model calculation functions */
23 static int calc_initialize(component_ptr_t comp)
25 comp->states[VAR_R_HIGHT] = 1.0;
26 comp->states[VAR_R_HIGHT_SPEED] = 4;
27 comp->reals [VAR_R_GRATIVY] = -9.81;
28 comp->reals [VAR_R_BOUNCE_CONF] = 0.5;
30 comp->functions.logger(comp, comp->instanceName, fmiOK, "INFO", "###### Initializing component ######");
31 comp->functions.logger(comp, comp->instanceName, fmiOK, "INFO", "Init #r%d#=%g", VAR_R_HIGHT, comp->states[VAR_R_HIGHT]);
32 comp->functions.logger(comp, comp->instanceName, fmiOK, "INFO", "Init #r%d#=%g",VAR_R_HIGHT_SPEED, comp->states[VAR_R_HIGHT_SPEED]);
33 comp->functions.logger(comp, comp->instanceName, fmiOK, "INFO", "Init #r%d#=%g",VAR_R_GRATIVY, comp->reals [VAR_R_GRATIVY]);
34 comp->functions.logger(comp, comp->instanceName, fmiOK, "INFO", "Init #r%d#=%g",VAR_R_BOUNCE_CONF, comp->reals [VAR_R_BOUNCE_CONF]);
35 comp->functions.logger(comp, comp->instanceName, fmiOK, "ERROR", "Bad reference: #r-1#");
36 comp->functions.logger(comp, comp->instanceName, fmiOK, "ERROR", "Bad reference: #r1");
37 comp->functions.logger(comp, comp->instanceName, fmiOK, "ERROR", "Bad reference: #t1#");
38 comp->functions.logger(comp, comp->instanceName, fmiOK, "ERROR", "Bad reference: #r10#");
43 static int calc_get_derivatives(component_ptr_t comp)
45 comp->states_der[VAR_R_HIGHT] = comp->states[VAR_R_HIGHT_SPEED];
46 comp->states_der[VAR_R_HIGHT_SPEED] = comp->reals[VAR_R_GRATIVY];
50 static int calc_get_event_indicators(component_ptr_t comp)
52 fmiReal event_tol = 1e-16;
53 comp->event_indicators[EVENT_HIGHT] = comp->states[VAR_R_HIGHT] + (comp->states[VAR_R_HIGHT] >= 0 ? event_tol : -event_tol);
57 static int calc_event_update(component_ptr_t comp)
59 if (comp->states[VAR_R_HIGHT] < 0) {
60 comp->states[VAR_R_HIGHT_SPEED] = - comp->reals[VAR_R_BOUNCE_CONF] * comp->states[VAR_R_HIGHT_SPEED];
61 comp->states[VAR_R_HIGHT] = 0;
63 comp->eventInfo.iterationConverged = fmiTrue;
64 comp->eventInfo.stateValueReferencesChanged = fmiFalse;
65 comp->eventInfo.stateValuesChanged = fmiTrue;
66 comp->eventInfo.terminateSimulation = fmiFalse;
67 comp->eventInfo.upcomingTimeEvent = fmiFalse;
68 comp->eventInfo.nextEventTime = -0.0;
71 return 1; /* Should not call the event update */
76 /* FMI 1.0 Common Functions */
77 const char* fmi_get_version()
82 fmiStatus fmi_set_debug_logging(fmiComponent c, fmiBoolean loggingOn)
84 component_ptr_t comp = (fmiComponent)c;
88 comp->loggingOn = loggingOn;
93 fmiStatus fmi_get_real(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[])
95 component_ptr_t comp = (fmiComponent)c;
100 for (k = 0; k < nvr; k++) {
101 fmiValueReference cvr = vr[k];
102 if (cvr < N_STATES) {
103 value[k] = comp->states[cvr];
106 value[k] = comp->reals[cvr];
113 fmiStatus fmi_get_integer(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[])
115 component_ptr_t comp = (fmiComponent)c;
120 for (k = 0; k < nvr; k++) {
121 value[k] = comp->integers[vr[k]];
127 fmiStatus fmi_get_boolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[])
129 component_ptr_t comp = (fmiComponent)c;
134 for (k = 0; k < nvr; k++) {
135 value[k] = comp->booleans[vr[k]];
141 fmiStatus fmi_get_string(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[])
143 component_ptr_t comp = (fmiComponent)c;
148 for (k = 0; k < nvr; k++) {
149 value[k] = comp->strings[vr[k]];
155 fmiStatus fmi_set_real(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[])
157 component_ptr_t comp = (fmiComponent)c;
162 for (k = 0; k < nvr; k++) {
163 fmiValueReference cvr = vr[k];
164 if (cvr < N_STATES) {
165 comp->states[cvr] = value[k];
168 comp->reals[cvr] = value[k];
175 fmiStatus fmi_set_integer(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[])
177 component_ptr_t comp = (fmiComponent)c;
182 for (k = 0; k < nvr; k++) {
183 comp->integers[vr[k]] = value[k];
189 fmiStatus fmi_set_boolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[])
191 component_ptr_t comp = (fmiComponent)c;
196 for (k = 0; k < nvr; k++) {
197 comp->booleans[vr[k]] = value[k];
203 fmiStatus fmi_set_string(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[])
205 component_ptr_t comp = (fmiComponent)c;
210 for (k = 0; k < nvr; k++) {
213 fmiString s_src = value[k];
215 len = strlen((char*)s_src) + 1;
216 s_dist = comp->functions.allocateMemory(len, sizeof(char));
217 if (s_dist == NULL) {
220 strcpy((char*)s_dist, (char*)s_src);
221 if(comp->strings[vr[k]]) {
222 comp->functions.freeMemory((void*)comp->strings[vr[k]]);
224 comp->strings[vr[k]] = s_dist;
227 /******* Logger test *******/
228 if(comp->loggingOn == fmiTrue) {
229 for (k = 0; k < nvr; k++) {
230 fmiValueReference cvr = vr[k];
231 if (cvr == VAR_S_LOGGER_TEST) {
232 comp->functions.logger(comp, comp->instanceName, fmiFatal, "INFO", "%s",value[k]);
236 /******* End of logger test *******/
241 /* FMI 1.0 ME Functions */
242 const char* fmi_get_model_types_platform()
244 return FMI_PLATFORM_TYPE;
247 #define FMI_TEST_LOGGER_TEST_RESULT_FILE "C:\\P510-JModelica\\FMIToolbox\\trunk\\external\\FMIL\\build\\testfolder\\"
248 #define FMI_TEST_LOGGER_TEST_SOURCE_FILE "C:\\P510-JModelica\\FMIToolbox\\trunk\\external\\FMIL\\build\\testfolder\\"
250 /* static FILE* find_string(FILE* fp, char* str, int len) {
254 fmiComponent fmi_instantiate_model(fmiString instanceName, fmiString GUID, fmiCallbackFunctions functions, fmiBoolean loggingOn)
256 component_ptr_t comp;
259 comp = (component_ptr_t)functions.allocateMemory(1, sizeof(component_t));
262 } else if (strcmp(GUID, FMI_GUID) != 0) {
265 sprintf(comp->instanceName, "%s", instanceName);
266 sprintf(comp->GUID, "%s",GUID);
267 comp->functions = functions;
268 comp->loggingOn = loggingOn;
270 comp->callEventUpdate = fmiFalse;
272 /* Set default values */
273 for (k = 0; k < N_STATES; k++) comp->states[k] = 0.0;
274 for (k = 0; k < N_STATES; k++) comp->states_prev[k] = 0.0; /* Used in CS only */
275 for (k = 0; k < N_STATES; k++) comp->states_nom[k] = 1.0;
276 for (k = 0; k < N_STATES; k++) comp->states_vr[k] = k;
277 for (k = 0; k < N_STATES; k++) comp->states_der[k] = 0.0;
278 for (k = 0; k < N_EVENT_INDICATORS; k++) comp->event_indicators[k] = 1e10;
279 for (k = 0; k < N_REAL; k++) comp->reals[k] = 0.0;
280 for (k = 0; k < N_INTEGER; k++) comp->integers[k] = 0;
281 for (k = 0; k < N_BOOLEAN; k++) comp->booleans[k] = fmiFalse;
282 for (k = 0; k < N_STRING; k++) comp->strings[k] = NULL;
284 /* Used in CS only */
285 for (k = 0; k < N_INPUT_REAL; k++) {
286 for (p = 0; p < N_INPUT_REAL_MAX_ORDER + 1; p++) {
287 comp->input_real[k][p] = 0.0;
291 /* Used in CS only */
292 for (k = 0; k < N_OUTPUT_REAL; k++) {
293 for (p = 0; p < N_OUTPUT_REAL_MAX_ORDER + 1; p++) {
294 comp->output_real[k][p] = MAGIC_TEST_VALUE;
302 void fmi_free_model_instance(fmiComponent c)
305 component_ptr_t comp = (fmiComponent)c;
306 for(i = 0; i < N_STRING; i++) {
307 comp->functions.freeMemory((void*)(comp->strings[i]));
308 comp->strings[i] = 0;
310 comp->functions.freeMemory(c);
313 fmiStatus fmi_set_time(fmiComponent c, fmiReal fmitime)
315 component_ptr_t comp = (fmiComponent)c;
319 comp->fmitime = fmitime;
324 fmiStatus fmi_set_continuous_states(fmiComponent c, const fmiReal x[], size_t nx)
326 component_ptr_t comp = (fmiComponent)c;
331 for (k = 0; k < nx; k++) {
332 comp->states[k] = x[k];
338 fmiStatus fmi_completed_integrator_step(fmiComponent c, fmiBoolean* callEventUpdate)
340 component_ptr_t comp = (fmiComponent)c;
344 *callEventUpdate = comp->callEventUpdate;
349 fmiStatus fmi_initialize(fmiComponent c, fmiBoolean toleranceControlled, fmiReal relativeTolerance, fmiEventInfo* eventInfo)
351 component_ptr_t comp = (fmiComponent)c;
356 comp->eventInfo.iterationConverged = fmiFalse;
357 comp->eventInfo.stateValueReferencesChanged = fmiFalse;
358 comp->eventInfo.stateValuesChanged = fmiFalse;
359 comp->eventInfo.terminateSimulation = fmiFalse;
360 comp->eventInfo.upcomingTimeEvent = fmiFalse;
361 comp->eventInfo.nextEventTime = -0.0;
363 comp->toleranceControlled = toleranceControlled;
364 comp->relativeTolerance = relativeTolerance;
366 calc_initialize(comp);
368 *eventInfo = comp->eventInfo;
374 fmiStatus fmi_get_derivatives(fmiComponent c, fmiReal derivatives[] , size_t nx)
376 component_ptr_t comp = (fmiComponent)c;
382 calc_get_derivatives(comp);
384 for (k = 0; k < nx; k++) {
385 derivatives[k] = comp->states_der[k];
391 fmiStatus fmi_get_event_indicators(fmiComponent c, fmiReal eventIndicators[], size_t ni)
393 component_ptr_t comp = (fmiComponent)c;
399 calc_get_event_indicators(comp);
401 for (k = 0; k < ni; k++) {
402 eventIndicators[k] = comp->event_indicators[k];
408 fmiStatus fmi_event_update(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo* eventInfo)
410 component_ptr_t comp = (fmiComponent)c;
414 calc_event_update(comp);
416 *eventInfo = comp->eventInfo;
421 fmiStatus fmi_get_continuous_states(fmiComponent c, fmiReal states[], size_t nx)
423 component_ptr_t comp = (fmiComponent)c;
429 for (k = 0; k < nx; k++) {
430 states[k] = comp->states[k];
436 fmiStatus fmi_get_nominal_continuousstates(fmiComponent c, fmiReal x_nominal[], size_t nx)
438 component_ptr_t comp = (fmiComponent)c;
443 for (k = 0; k < nx; k++) {
444 x_nominal[k] = comp->states_nom[k];
450 fmiStatus fmi_get_state_value_references(fmiComponent c, fmiValueReference vrx[], size_t nx)
452 component_ptr_t comp = (fmiComponent)c;
457 for (k = 0; k < nx; k++) {
458 vrx[k] = comp->states_vr[k];
464 fmiStatus fmi_terminate(fmiComponent c)
466 component_ptr_t comp = (fmiComponent)c;
474 /* FMI 1.0 CS Functions */
475 const char* fmi_get_types_platform()
477 return FMI_PLATFORM_TYPE;
480 fmiComponent fmi_instantiate_slave(fmiString instanceName, fmiString fmuGUID, fmiString fmuLocation, fmiString mimeType, fmiReal timeout, fmiBoolean visible, fmiBoolean interactive, fmiCallbackFunctions functions, fmiBoolean loggingOn)
482 component_ptr_t comp;
484 comp = fmi_instantiate_model(instanceName, fmuGUID, functions, loggingOn);
487 } else if (strcmp(fmuGUID, FMI_GUID) != 0) {
490 sprintf(comp->fmuLocation, "%s",fmuLocation);
491 sprintf(comp->mimeType, "%s",mimeType);
492 comp->timeout = timeout;
493 comp->visible = visible;
494 comp->interactive = interactive;
499 fmiStatus fmi_initialize_slave(fmiComponent c, fmiReal tStart, fmiBoolean StopTimeDefined, fmiReal tStop)
501 component_ptr_t comp = (fmiComponent)c;
502 fmiReal relativeTolerance;
503 fmiEventInfo eventInfo;
504 fmiBoolean toleranceControlled;
507 comp->tStart = tStart;
508 comp->StopTimeDefined = StopTimeDefined;
511 toleranceControlled = fmiTrue;
512 relativeTolerance = 1e-4;
514 return fmi_initialize((fmiComponent)comp, toleranceControlled, relativeTolerance, &eventInfo);
517 fmiStatus fmi_terminate_slave(fmiComponent c)
519 return fmi_terminate(c);
522 fmiStatus fmi_reset_slave(fmiComponent c)
527 void fmi_free_slave_instance(fmiComponent c)
529 fmi_free_model_instance(c);
532 fmiStatus fmi_set_real_input_derivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], const fmiReal value[])
535 component_ptr_t comp = (fmiComponent)c;
538 for (k = 0; k < nvr; k++) {
539 comp->input_real[vr[k]][order[k]] = value[k];
540 if (value[k] != MAGIC_TEST_VALUE) {/* Tests that the value is set to MAGIC_TEST_VALUE */
548 fmiStatus fmi_get_real_output_derivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], fmiReal value[])
550 component_ptr_t comp = (fmiComponent)c;
553 for (k = 0; k < nvr; k++) {
554 value[k] = comp->output_real[vr[k]][order[k]];
560 fmiStatus fmi_cancel_step(fmiComponent c)
565 fmiStatus fmi_do_step(fmiComponent c, fmiReal currentCommunicationPoint, fmiReal communicationStepSize, fmiBoolean newStep)
567 component_ptr_t comp = (fmiComponent)c;
572 fmiReal tstart = currentCommunicationPoint;
574 fmiReal tend = currentCommunicationPoint + communicationStepSize;
576 fmiReal hdef = 0.01; /* Default time step length */
577 fmiReal z_cur[N_EVENT_INDICATORS];
578 fmiReal z_pre[N_EVENT_INDICATORS];
579 fmiReal states[N_STATES];
580 fmiReal states_der[N_STATES];
581 fmiEventInfo eventInfo;
582 fmiBoolean callEventUpdate;
583 fmiBoolean intermediateResults = fmiFalse;
588 fmi_get_continuous_states(comp, states, N_STATES);
589 fmi_get_event_indicators(comp, z_pre, N_EVENT_INDICATORS);
593 callEventUpdate = fmiFalse;
594 eventInfo = comp->eventInfo;
596 while (tcur < tend && counter < 100) {
598 int zero_crossning_event = 0;
601 fmi_set_time(comp, tcur);
602 fmi_get_event_indicators(comp, z_cur, N_EVENT_INDICATORS);
604 /* Check if an event inidcator has triggered */
605 for (k = 0; k < N_EVENT_INDICATORS; k++) {
606 if (z_cur[k]*z_pre[k] < 0) {
607 zero_crossning_event = 1;
612 /* Handle any events */
613 if (callEventUpdate || zero_crossning_event || (eventInfo.upcomingTimeEvent && tcur == eventInfo.nextEventTime)) {
614 fmistatus = fmi_event_update(comp, intermediateResults, &eventInfo);
615 fmistatus = fmi_get_continuous_states(comp, states, N_STATES);
616 fmistatus = fmi_get_event_indicators(comp, z_cur, N_EVENT_INDICATORS);
617 fmistatus = fmi_get_event_indicators(comp, z_pre, N_EVENT_INDICATORS);
620 /* Updated next time step */
621 if (eventInfo.upcomingTimeEvent) {
622 if (tcur + hdef < eventInfo.nextEventTime) {
625 hcur = eventInfo.nextEventTime - tcur;
632 double t_full = tcur + hcur;
634 hcur = (tend - tcur);
641 /* Integrate a step */
642 fmistatus = fmi_get_derivatives(comp, states_der, N_STATES);
643 for (k = 0; k < N_STATES; k++) {
644 states[k] = states[k] + hcur*states_der[k];
645 /* if (k == 0) printf("states[%u] = %f states_der[k] = %f hcur =%f\n", k, states[k], states_der[k], hcur); */
649 fmistatus = fmi_set_continuous_states(comp, states, N_STATES);
650 /* Step is complete */
651 fmistatus = fmi_completed_integrator_step(comp, &callEventUpdate);
653 if(fmistatus != fmiOK) break;
655 for (k = 0; k < N_STATES; k++) { /* Update states */
656 comp->reals[k] = comp->states[k];
662 fmiStatus fmi_get_status(fmiComponent c, const fmiStatusKind s, fmiStatus* value)
665 case fmiDoStepStatus:
666 /* Return fmiPending if we are waiting. Otherwise the result from fmiDoStep */
669 default: /* Not defined for status for this function */
674 fmiStatus fmi_get_real_status(fmiComponent c, const fmiStatusKind s, fmiReal* value)
677 case fmiLastSuccessfulTime:
678 /* Return fmiPending if we are waiting. Otherwise return end time for last call to fmiDoStep */
681 default: /* Not defined for status for this function */
686 fmiStatus fmi_get_integer_status(fmiComponent c, const fmiStatusKind s, fmiInteger* value)
689 default: /* Not defined for status for this function */
694 fmiStatus fmi_get_boolean_status(fmiComponent c, const fmiStatusKind s, fmiBoolean* value)
697 default: /* Not defined for status for this function */
702 fmiStatus fmi_get_string_status(fmiComponent c, const fmiStatusKind s, fmiString* value)
705 case fmiPendingStatus:
706 *value = "Did fmiDoStep really return with fmiPending? Then its time to implement this function";
708 default: /* Not defined for status for this function */