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/fmu2_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->functions->componentEnvironment, comp->instanceName, fmi2OK, "INFO", "###### Initializing component ######");
31 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "INFO", "Init #r%d#=%g", VAR_R_HIGHT, comp->states[VAR_R_HIGHT]);
32 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "INFO", "Init #r%d#=%g",VAR_R_HIGHT_SPEED, comp->states[VAR_R_HIGHT_SPEED]);
33 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "INFO", "Init #r%d#=%g",VAR_R_GRATIVY, comp->reals [VAR_R_GRATIVY]);
34 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "INFO", "Init #r%d#=%g",VAR_R_BOUNCE_CONF, comp->reals [VAR_R_BOUNCE_CONF]);
35 /* comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "ERROR", "Bad reference: #r-1#");
36 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "ERROR", "Bad reference: #r1");
37 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "ERROR", "Bad reference: #t1#");
38 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2OK, "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 fmi2Real 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 comp->eventInfo.newDiscreteStatesNeeded = fmi2False;
60 comp->eventInfo.terminateSimulation = fmi2False;
61 comp->eventInfo.nominalsOfContinuousStatesChanged = fmi2False;
62 comp->eventInfo.nextEventTimeDefined = fmi2False;
63 comp->eventInfo.nextEventTime = -0.0;
64 if ((comp->states[VAR_R_HIGHT] < 0) && (comp->states[VAR_R_HIGHT_SPEED] < 0)) {
65 comp->states[VAR_R_HIGHT_SPEED] = - comp->reals[VAR_R_BOUNCE_CONF] * comp->states[VAR_R_HIGHT_SPEED];
66 comp->states[VAR_R_HIGHT] = 0;
68 comp->eventInfo.valuesOfContinuousStatesChanged = fmi2True;
71 comp->eventInfo.valuesOfContinuousStatesChanged = fmi2False;
72 return 1; /* Should not call the event update */
77 /* FMI 2.0 Common Functions */
78 const char* fmi_get_version()
83 fmi2Status fmi_set_debug_logging(fmi2Component c, fmi2Boolean loggingOn)
85 component_ptr_t comp = (fmi2Component)c;
89 comp->loggingOn = loggingOn;
94 fmi2Status fmi_get_real(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[])
96 component_ptr_t comp = (fmi2Component)c;
101 for (k = 0; k < nvr; k++) {
102 fmi2ValueReference cvr = vr[k];
103 if (cvr < N_STATES) {
104 value[k] = comp->states[cvr];
107 calc_get_derivatives(comp);
108 value[k] = comp->states_der[1];
111 value[k] = comp->reals[cvr];
118 fmi2Status fmi_get_integer(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[])
120 component_ptr_t comp = (fmi2Component)c;
125 for (k = 0; k < nvr; k++) {
126 value[k] = comp->integers[vr[k]];
132 fmi2Status fmi_get_boolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[])
134 component_ptr_t comp = (fmi2Component)c;
139 for (k = 0; k < nvr; k++) {
140 value[k] = comp->booleans[vr[k]];
146 fmi2Status fmi_get_string(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[])
148 component_ptr_t comp = (fmi2Component)c;
153 for (k = 0; k < nvr; k++) {
154 value[k] = comp->strings[vr[k]];
160 fmi2Status fmi_set_real(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[])
162 component_ptr_t comp = (fmi2Component)c;
167 for (k = 0; k < nvr; k++) {
168 fmi2ValueReference cvr = vr[k];
169 if (cvr < N_STATES) {
170 comp->states[cvr] = value[k];
173 comp->functions->logger(c, comp->instanceName,fmi2Warning, "WARNING", "Cannot set acceleration value (calculated)");
177 comp->reals[cvr] = value[k];
184 fmi2Status fmi_set_integer(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[])
186 component_ptr_t comp = (fmi2Component)c;
191 for (k = 0; k < nvr; k++) {
192 comp->integers[vr[k]] = value[k];
198 fmi2Status fmi_set_boolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[])
200 component_ptr_t comp = (fmi2Component)c;
205 for (k = 0; k < nvr; k++) {
206 comp->booleans[vr[k]] = value[k];
212 fmi2Status fmi_set_string(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[])
214 component_ptr_t comp = (fmi2Component)c;
219 for (k = 0; k < nvr; k++) {
222 fmi2String s_src = value[k];
224 len = strlen((char*)s_src) + 1;
225 s_dist = comp->functions->allocateMemory(len, sizeof(char));
226 if (s_dist == NULL) {
229 strcpy((char*)s_dist, (char*)s_src);
230 if(comp->strings[vr[k]]) {
231 comp->functions->freeMemory((void*)comp->strings[vr[k]]);
233 comp->strings[vr[k]] = s_dist;
236 /******* Logger test *******/
237 if(comp->loggingOn == fmi2True) {
238 for (k = 0; k < nvr; k++) {
239 fmi2ValueReference cvr = vr[k];
240 if (cvr == VAR_S_LOGGER_TEST) {
241 comp->functions->logger(comp->functions->componentEnvironment, comp->instanceName, fmi2Fatal, "INFO", "%s",value[k]);
245 /******* End of logger test *******/
250 /* FMI 2.0 ME Functions */
251 const char* fmi_get_model_types_platform()
253 return fmi2TypesPlatform;
256 /* static FILE* find_string(FILE* fp, char* str, int len) {
260 fmi2Component fmi_instantiate(fmi2String instanceName, fmi2Type fmuType,
261 fmi2String fmuGUID, fmi2String fmuLocation,
262 const fmi2CallbackFunctions *functions, fmi2Boolean visible,
263 fmi2Boolean loggingOn)
265 component_ptr_t comp;
268 comp = (component_ptr_t)functions->allocateMemory(1, sizeof(component_t));
271 } else if (strcmp(fmuGUID, FMI_GUID) != 0) {
274 sprintf(comp->instanceName, "%s", instanceName);
275 sprintf(comp->GUID, "%s",fmuGUID);
276 comp->functions = functions;
277 /*comp->functions->allocateMemory = functions->allocateMemory;*/
279 comp->loggingOn = loggingOn;
281 /* Set default values */
282 for (k = 0; k < N_STATES; k++) comp->states[k] = 0.0;
283 for (k = 0; k < N_STATES; k++) comp->states_prev[k] = 0.0; /* Used in CS only */
284 for (k = 0; k < N_STATES; k++) comp->states_nom[k] = 1.0;
285 for (k = 0; k < N_STATES; k++) comp->states_der[k] = 0.0;
286 for (k = 0; k < N_EVENT_INDICATORS; k++) comp->event_indicators[k] = 1e10;
287 for (k = 0; k < N_REAL; k++) comp->reals[k] = 0.0;
288 for (k = 0; k < N_INTEGER; k++) comp->integers[k] = 0;
289 for (k = 0; k < N_BOOLEAN; k++) comp->booleans[k] = fmi2False;
290 for (k = 0; k < N_STRING; k++) comp->strings[k] = NULL;
292 /* Used in CS only */
293 for (k = 0; k < N_INPUT_REAL; k++) {
294 for (p = 0; p < N_INPUT_REAL_MAX_ORDER + 1; p++) {
295 comp->input_real[k][p] = 0.0;
299 /* Used in CS only */
300 for (k = 0; k < N_OUTPUT_REAL; k++) {
301 for (p = 0; p < N_OUTPUT_REAL_MAX_ORDER + 1; p++) {
302 comp->output_real[k][p] = MAGIC_TEST_VALUE;
306 sprintf(comp->fmuLocation, "%s",fmuLocation);
307 comp->visible = visible;
312 void fmi_free_instance(fmi2Component c)
315 component_ptr_t comp = (fmi2Component)c;
316 for(i = 0; i < N_STRING; i++) {
317 comp->functions->freeMemory((void*)(comp->strings[i]));
318 comp->strings[i] = 0;
320 comp->functions->freeMemory(c);
323 fmi2Status fmi_setup_experiment(fmi2Component c, fmi2Boolean toleranceDefined,
324 fmi2Real tolerance, fmi2Real startTime,
325 fmi2Boolean stopTimeDefined,
328 component_ptr_t comp = (fmi2Component)c;
333 comp->toleranceControlled = toleranceDefined;
334 comp->relativeTolerance = tolerance;
336 comp->tStart = startTime;
337 comp->StopTimeDefined = stopTimeDefined;
338 comp->tStop = stopTime;
344 fmi2Status fmi_enter_initialization_mode(fmi2Component c)
354 fmi2Status fmi_exit_initialization_mode(fmi2Component c)
359 fmi2Status fmi_enter_event_mode(fmi2Component c)
364 fmi2Status fmi_new_discrete_states(fmi2Component c, fmi2EventInfo* eventInfo)
366 component_ptr_t comp = (fmi2Component)c;
370 calc_event_update(comp);
372 *eventInfo = comp->eventInfo;
377 fmi2Status fmi_enter_continuous_time_mode(fmi2Component c)
382 fmi2Status fmi_set_time(fmi2Component c, fmi2Real fmitime)
384 component_ptr_t comp = (fmi2Component)c;
388 comp->fmitime = fmitime;
393 fmi2Status fmi_set_continuous_states(fmi2Component c, const fmi2Real x[], size_t nx)
395 component_ptr_t comp = (fmi2Component)c;
400 for (k = 0; k < nx; k++) {
401 comp->states[k] = x[k];
407 fmi2Status fmi_completed_integrator_step(fmi2Component c,
408 fmi2Boolean noSetFMUStatePriorToCurrentPoint,
409 fmi2Boolean* enterEventMode, fmi2Boolean* terminateSimulation)
411 component_ptr_t comp = (fmi2Component)c;
415 *enterEventMode = fmi2False;
420 fmi2Status fmi_get_derivatives(fmi2Component c, fmi2Real derivatives[] , size_t nx)
422 component_ptr_t comp = (fmi2Component)c;
428 calc_get_derivatives(comp);
430 for (k = 0; k < nx; k++) {
431 derivatives[k] = comp->states_der[k];
437 fmi2Status fmi_get_event_indicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni)
439 component_ptr_t comp = (fmi2Component)c;
445 calc_get_event_indicators(comp);
447 for (k = 0; k < ni; k++) {
448 eventIndicators[k] = comp->event_indicators[k];
454 fmi2Status fmi_get_continuous_states(fmi2Component c, fmi2Real states[], size_t nx)
456 component_ptr_t comp = (fmi2Component)c;
462 for (k = 0; k < nx; k++) {
463 states[k] = comp->states[k];
469 fmi2Status fmi_get_nominals_of_continuousstates(fmi2Component c, fmi2Real x_nominal[], size_t nx)
471 component_ptr_t comp = (fmi2Component)c;
476 for (k = 0; k < nx; k++) {
477 x_nominal[k] = comp->states_nom[k];
483 fmi2Status fmi_terminate(fmi2Component c)
485 component_ptr_t comp = (fmi2Component)c;
493 /* FMI 2.0 CS Functions */
494 const char* fmi_get_types_platform()
496 return fmi2TypesPlatform;
499 fmi2Status fmi_reset(fmi2Component c)
504 fmi2Status fmi_set_real_input_derivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[])
507 component_ptr_t comp = (fmi2Component)c;
510 for (k = 0; k < nvr; k++) {
511 comp->input_real[vr[k]][order[k]] = value[k];
512 if (value[k] != MAGIC_TEST_VALUE) {/* Tests that the value is set to MAGIC_TEST_VALUE */
520 fmi2Status fmi_get_real_output_derivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[])
522 component_ptr_t comp = (fmi2Component)c;
525 for (k = 0; k < nvr; k++) {
526 value[k] = comp->output_real[vr[k]][order[k]];
532 fmi2Status fmi_cancel_step(fmi2Component c)
537 fmi2Status fmi_do_step(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean newStep)
539 component_ptr_t comp = (fmi2Component)c;
544 fmi2Real tstart = currentCommunicationPoint;
546 fmi2Real tend = currentCommunicationPoint + communicationStepSize;
548 fmi2Real hdef = 0.01; /* Default time step length */
549 fmi2Real z_cur[N_EVENT_INDICATORS];
550 fmi2Real z_pre[N_EVENT_INDICATORS];
551 fmi2Real states[N_STATES];
552 fmi2Real states_der[N_STATES];
553 fmi2EventInfo eventInfo;
554 fmi2Boolean callEventUpdate;
555 fmi2Boolean terminateSimulation;
556 fmi2Status fmi2Status;
560 fmi_get_continuous_states(comp, states, N_STATES);
561 fmi_get_event_indicators(comp, z_pre, N_EVENT_INDICATORS);
565 callEventUpdate = fmi2False;
566 eventInfo = comp->eventInfo;
568 while (tcur < tend && counter < 100) {
570 int zero_crossning_event = 0;
573 fmi_set_time(comp, tcur);
574 fmi_get_event_indicators(comp, z_cur, N_EVENT_INDICATORS);
576 /* Check if an event inidcator has triggered */
577 for (k = 0; k < N_EVENT_INDICATORS; k++) {
578 if (z_cur[k]*z_pre[k] < 0) {
579 zero_crossning_event = 1;
584 /* Handle any events */
585 if (callEventUpdate || zero_crossning_event ||
586 (eventInfo.nextEventTimeDefined && tcur == eventInfo.nextEventTime)) {
587 fmi2Status = fmi_new_discrete_states(comp, &eventInfo);
588 fmi2Status = fmi_get_continuous_states(comp, states, N_STATES);
589 fmi2Status = fmi_get_event_indicators(comp, z_cur, N_EVENT_INDICATORS);
590 fmi2Status = fmi_get_event_indicators(comp, z_pre, N_EVENT_INDICATORS);
593 /* Updated next time step */
594 if (eventInfo.nextEventTimeDefined) {
595 if (tcur + hdef < eventInfo.nextEventTime) {
598 hcur = eventInfo.nextEventTime - tcur;
605 double t_full = tcur + hcur;
607 hcur = (tend - tcur);
614 /* Integrate a step */
615 fmi2Status = fmi_get_derivatives(comp, states_der, N_STATES);
616 for (k = 0; k < N_STATES; k++) {
617 states[k] = states[k] + hcur*states_der[k];
618 /* if (k == 0) printf("states[%u] = %f states_der[k] = %f hcur =%f\n", k, states[k], states_der[k], hcur); */
622 fmi2Status = fmi_set_continuous_states(comp, states, N_STATES);
623 /* Step is complete */
624 fmi2Status = fmi_completed_integrator_step(comp, fmi2True,
625 &callEventUpdate, &terminateSimulation);
627 if(fmi2Status != fmi2OK) break;
630 for (k = 0; k < N_STATES; k++) { /* Update states */
631 comp->reals[k] = comp->states[k];
637 fmi2Status fmi_get_status(fmi2Component c, const fmi2StatusKind s, fmi2Status* value)
640 case fmi2DoStepStatus:
641 /* Return fmiPending if we are waiting. Otherwise the result from fmiDoStep */
644 default: /* Not defined for status for this function */
649 fmi2Status fmi_get_real_status(fmi2Component c, const fmi2StatusKind s, fmi2Real* value)
652 case fmi2LastSuccessfulTime:
653 /* Return fmiPending if we are waiting. Otherwise return end time for last call to fmiDoStep */
656 default: /* Not defined for status for this function */
661 fmi2Status fmi_get_integer_status(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value)
664 default: /* Not defined for status for this function */
669 fmi2Status fmi_get_boolean_status(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value)
672 default: /* Not defined for status for this function */
677 fmi2Status fmi_get_string_status(fmi2Component c, const fmi2StatusKind s, fmi2String* value)
680 case fmi2PendingStatus:
681 *value = "Did fmi2DoStep really return with fmi2Pending? Then its time to implement this function";
683 default: /* Not defined for status for this function */