]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/Test/FMI1/fmu_dummy/fmu1_model.c
Merge remote-tracking branch 'origin/master' into release/1.35.1
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / Test / FMI1 / fmu_dummy / fmu1_model.c
1 /*
2 Copyright (C) 2012 Modelon AB
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
6
7
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.
12
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>.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19
20 #include <fmu_dummy/fmu1_model.h>
21
22 /* Model calculation functions */
23 static int calc_initialize(component_ptr_t comp)
24 {
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;
29         if(comp->loggingOn) {
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#");
39         }
40         return 0;
41 }
42
43 static int calc_get_derivatives(component_ptr_t comp)
44 {
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];
47         return 0;
48 }
49
50 static int calc_get_event_indicators(component_ptr_t comp)
51 {       
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);
54         return 0;
55 }
56
57 static int calc_event_update(component_ptr_t comp)
58 {       
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;
62
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;
69                 return 0;
70         } else {
71                 return 1; /* Should not call the event update */
72         }
73 }
74
75
76 /* FMI 1.0 Common Functions */
77 const char* fmi_get_version()
78 {
79         return FMI_VERSION;
80 }
81
82 fmiStatus fmi_set_debug_logging(fmiComponent c, fmiBoolean loggingOn)
83 {
84         component_ptr_t comp = (fmiComponent)c;
85         if (comp == NULL) {
86                 return fmiFatal;
87         } else {
88                 comp->loggingOn = loggingOn;
89                 return fmiOK;
90         }
91 }
92
93 fmiStatus fmi_get_real(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[])
94 {
95         component_ptr_t comp = (fmiComponent)c;
96         if (comp == NULL) {
97                 return fmiFatal;
98         } else {
99                 size_t k;
100                 for (k = 0; k < nvr; k++) {
101                         fmiValueReference cvr = vr[k];
102                         if (cvr < N_STATES) {
103                                 value[k] = comp->states[cvr];
104                         } 
105                         else {
106                                 value[k] = comp->reals[cvr];
107                         }       
108                 }
109                 return fmiOK;
110         }
111 }
112
113 fmiStatus fmi_get_integer(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[])
114 {
115         component_ptr_t comp = (fmiComponent)c;
116         if (comp == NULL) {
117                 return fmiFatal;
118         } else {
119                 size_t k;
120                 for (k = 0; k < nvr; k++) {
121                         value[k] = comp->integers[vr[k]];
122                 }
123                 return fmiOK;
124         }
125 }
126
127 fmiStatus fmi_get_boolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[])
128 {
129         component_ptr_t comp = (fmiComponent)c;
130         if (comp == NULL) {
131                 return fmiFatal;
132         } else {
133                 size_t k;
134                 for (k = 0; k < nvr; k++) {
135                         value[k] = comp->booleans[vr[k]];
136                 }
137                 return fmiOK;
138         }
139 }
140
141 fmiStatus fmi_get_string(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString  value[])
142 {
143         component_ptr_t comp = (fmiComponent)c;
144         if (comp == NULL) {
145                 return fmiFatal;
146         } else {
147                 size_t k;
148                 for (k = 0; k < nvr; k++) {
149                         value[k] = comp->strings[vr[k]];
150                 }
151                 return fmiOK;
152         }
153 }
154
155 fmiStatus fmi_set_real(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[])
156 {
157         component_ptr_t comp = (fmiComponent)c;
158         if (comp == NULL) {
159                 return fmiFatal;
160         } else {
161                 size_t k;
162                 for (k = 0; k < nvr; k++) {
163                         fmiValueReference cvr = vr[k];
164                         if (cvr < N_STATES) {
165                                 comp->states[cvr] = value[k]; 
166                         } 
167                         else {
168                                 comp->reals[cvr] = value[k]; 
169                         }                       
170                 }
171                 return fmiOK;
172         }
173 }
174
175 fmiStatus fmi_set_integer(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[])
176 {
177         component_ptr_t comp = (fmiComponent)c;
178         if (comp == NULL) {
179                 return fmiFatal;
180         } else {
181                 size_t k;
182                 for (k = 0; k < nvr; k++) {
183                         comp->integers[vr[k]] = value[k]; 
184                 }
185                 return fmiOK;
186         }
187 }
188
189 fmiStatus fmi_set_boolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[])
190 {
191         component_ptr_t comp = (fmiComponent)c;
192         if (comp == NULL) {
193                 return fmiFatal;
194         } else {
195                 size_t k;
196                 for (k = 0; k < nvr; k++) {
197                         comp->booleans[vr[k]] = value[k]; 
198                 }
199                 return fmiOK;
200         }
201 }
202
203 fmiStatus fmi_set_string(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString  value[])
204 {
205         component_ptr_t comp = (fmiComponent)c;
206         if (comp == NULL) {
207                 return fmiFatal;
208         } else {
209                 size_t k;
210                 for (k = 0; k < nvr; k++) {                     
211                         size_t len;
212                         fmiString s_dist;
213                         fmiString s_src = value[k];
214
215                         len = strlen((char*)s_src) + 1;
216                         s_dist = comp->functions.allocateMemory(len, sizeof(char));
217                         if (s_dist == NULL) {
218                                 return fmiFatal;
219                         }                       
220                         strcpy((char*)s_dist, (char*)s_src);
221                         if(comp->strings[vr[k]]) {
222                                 comp->functions.freeMemory((void*)comp->strings[vr[k]]);
223                         }
224                         comp->strings[vr[k]] = s_dist;
225                 }
226
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]);
233                                 }
234                         }
235                 }
236                 /******* End of logger test *******/
237                 return fmiOK;
238         }
239 }
240
241 /* FMI 1.0 ME Functions */
242 const char* fmi_get_model_types_platform()
243 {
244         return FMI_PLATFORM_TYPE;
245 }
246
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\\"
249
250 /* static FILE* find_string(FILE* fp, char* str, int len) {
251
252 } */
253
254 fmiComponent fmi_instantiate_model(fmiString instanceName, fmiString GUID, fmiCallbackFunctions functions, fmiBoolean loggingOn)
255 {
256         component_ptr_t comp;
257         int k, p;
258
259         comp = (component_ptr_t)functions.allocateMemory(1, sizeof(component_t));
260         if (comp == NULL) {
261                 return NULL;
262         } else if (strcmp(GUID, FMI_GUID) != 0) {
263                 return NULL;
264         } else {        
265                 sprintf(comp->instanceName, "%s", instanceName);
266                 sprintf(comp->GUID, "%s",GUID);
267                 comp->functions         = functions;
268                 comp->loggingOn         = loggingOn;
269
270                 comp->callEventUpdate = fmiFalse;
271
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;
283
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;
288                         }
289                 }
290
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;
295                         }
296                 }
297
298                 return comp;
299         }
300 }
301
302 void fmi_free_model_instance(fmiComponent c)
303 {
304         int i;
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;
309         }
310         comp->functions.freeMemory(c);
311 }
312
313 fmiStatus fmi_set_time(fmiComponent c, fmiReal fmitime)
314 {
315         component_ptr_t comp = (fmiComponent)c;
316         if (comp == NULL) {
317                 return fmiFatal;
318         } else {
319                 comp->fmitime = fmitime;
320                 return fmiOK;
321         }
322 }
323
324 fmiStatus fmi_set_continuous_states(fmiComponent c, const fmiReal x[], size_t nx)
325 {
326         component_ptr_t comp = (fmiComponent)c;
327         if (comp == NULL) {
328                 return fmiFatal;
329         } else {
330                 size_t k;
331                 for (k = 0; k < nx; k++) {
332                         comp->states[k] = x[k];
333                 }
334                 return fmiOK;
335         }
336 }
337
338 fmiStatus fmi_completed_integrator_step(fmiComponent c, fmiBoolean* callEventUpdate)
339 {
340         component_ptr_t comp = (fmiComponent)c;
341         if (comp == NULL) {
342                 return fmiFatal;
343         } else {
344                 *callEventUpdate = comp->callEventUpdate;
345                 return fmiOK;
346         }
347 }
348
349 fmiStatus fmi_initialize(fmiComponent c, fmiBoolean toleranceControlled, fmiReal relativeTolerance, fmiEventInfo* eventInfo)
350 {
351         component_ptr_t comp = (fmiComponent)c;
352
353         if (comp == NULL) {
354                 return fmiFatal;
355         } else {
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;
362
363                 comp->toleranceControlled = toleranceControlled;
364                 comp->relativeTolerance = relativeTolerance;
365                 
366                 calc_initialize(comp);
367
368                 *eventInfo = comp->eventInfo;
369
370                 return fmiOK;
371         }
372 }
373
374 fmiStatus fmi_get_derivatives(fmiComponent c, fmiReal derivatives[] , size_t nx)
375 {
376         component_ptr_t comp = (fmiComponent)c;
377         if (comp == NULL) {
378                 return fmiFatal;
379         } else {
380                 size_t k;
381
382                 calc_get_derivatives(comp);
383
384                 for (k = 0; k < nx; k++) {
385                         derivatives[k] = comp->states_der[k];
386                 }
387                 return fmiOK;
388         }
389 }
390
391 fmiStatus fmi_get_event_indicators(fmiComponent c, fmiReal eventIndicators[], size_t ni)
392 {
393         component_ptr_t comp = (fmiComponent)c;
394         if (comp == NULL) {
395                 return fmiFatal;
396         } else {
397                 size_t k;
398
399                 calc_get_event_indicators(comp);
400
401                 for (k = 0; k < ni; k++) {
402                         eventIndicators[k] = comp->event_indicators[k];
403                 }
404                 return fmiOK;
405         }
406 }
407
408 fmiStatus fmi_event_update(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo* eventInfo)
409 {
410         component_ptr_t comp = (fmiComponent)c;
411         if (comp == NULL) {
412                 return fmiFatal;
413         } else {
414                 calc_event_update(comp);
415
416                 *eventInfo = comp->eventInfo;
417                 return fmiOK;
418         }
419 }
420
421 fmiStatus fmi_get_continuous_states(fmiComponent c, fmiReal states[], size_t nx)
422 {
423         component_ptr_t comp = (fmiComponent)c;
424         if (comp == NULL) {
425                 return fmiFatal;
426         } else {
427                 size_t k;
428
429                 for (k = 0; k < nx; k++) {
430                         states[k] = comp->states[k];
431                 }
432                 return fmiOK;
433         }
434 }
435
436 fmiStatus fmi_get_nominal_continuousstates(fmiComponent c, fmiReal x_nominal[], size_t nx)
437 {
438         component_ptr_t comp = (fmiComponent)c;
439         if (comp == NULL) {
440                 return fmiFatal;
441         } else {
442                 size_t k;
443                 for (k = 0; k < nx; k++) {
444                         x_nominal[k] = comp->states_nom[k];
445                 }
446                 return fmiOK;
447         }
448 }
449
450 fmiStatus fmi_get_state_value_references(fmiComponent c, fmiValueReference vrx[], size_t nx)
451 {
452         component_ptr_t comp = (fmiComponent)c;
453         if (comp == NULL) {
454                 return fmiFatal;
455         } else {
456                 size_t k;
457                 for (k = 0; k < nx; k++) {
458                         vrx[k] = comp->states_vr[k];
459                 }
460                 return fmiOK;
461         }
462 }
463
464 fmiStatus fmi_terminate(fmiComponent c)
465 {
466         component_ptr_t comp = (fmiComponent)c;
467         if (comp == NULL) {
468                 return fmiFatal;
469         } else {
470                 return fmiOK;
471         }
472 }
473
474 /* FMI 1.0 CS Functions */
475 const char* fmi_get_types_platform()
476 {
477         return FMI_PLATFORM_TYPE;
478 }
479
480 fmiComponent fmi_instantiate_slave(fmiString instanceName, fmiString fmuGUID, fmiString fmuLocation, fmiString mimeType, fmiReal timeout, fmiBoolean visible, fmiBoolean interactive, fmiCallbackFunctions functions, fmiBoolean loggingOn)
481 {
482         component_ptr_t comp;
483
484         comp = fmi_instantiate_model(instanceName, fmuGUID, functions, loggingOn);
485         if (comp == NULL) {
486                 return NULL;
487         } else if (strcmp(fmuGUID, FMI_GUID) != 0) {
488                 return NULL;
489         } else {        
490                 sprintf(comp->fmuLocation, "%s",fmuLocation);
491                 sprintf(comp->mimeType, "%s",mimeType);
492                 comp->timeout           = timeout;
493                 comp->visible           = visible;
494                 comp->interactive       = interactive;
495                 return comp;
496         }
497 }
498
499 fmiStatus fmi_initialize_slave(fmiComponent c, fmiReal tStart, fmiBoolean StopTimeDefined, fmiReal tStop)
500 {
501         component_ptr_t comp    = (fmiComponent)c;
502         fmiReal relativeTolerance;
503         fmiEventInfo eventInfo;
504         fmiBoolean toleranceControlled;
505
506
507         comp->tStart                    = tStart;
508         comp->StopTimeDefined   = StopTimeDefined;
509         comp->tStop                             = tStop;
510
511         toleranceControlled = fmiTrue;
512         relativeTolerance = 1e-4;
513
514         return fmi_initialize((fmiComponent)comp, toleranceControlled, relativeTolerance, &eventInfo);
515 }
516
517 fmiStatus fmi_terminate_slave(fmiComponent c)
518 {
519         return fmi_terminate(c);
520 }
521
522 fmiStatus fmi_reset_slave(fmiComponent c)
523 {
524         return fmiOK;
525 }
526
527 void fmi_free_slave_instance(fmiComponent c)
528 {
529         fmi_free_model_instance(c);
530 }
531
532 fmiStatus fmi_set_real_input_derivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], const fmiReal value[])
533 {
534
535         component_ptr_t comp    = (fmiComponent)c;
536         size_t k;
537
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 */
541                         return fmiFatal;
542                 }
543         }
544
545         return fmiOK;
546 }
547
548 fmiStatus fmi_get_real_output_derivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], fmiReal value[])
549 {
550         component_ptr_t comp    = (fmiComponent)c;
551         size_t k;
552
553         for (k = 0; k < nvr; k++) {
554                 value[k] = comp->output_real[vr[k]][order[k]];
555         }
556
557         return fmiOK;
558 }
559
560 fmiStatus fmi_cancel_step(fmiComponent c)
561 {
562         return fmiOK;
563 }
564
565 fmiStatus fmi_do_step(fmiComponent c, fmiReal currentCommunicationPoint, fmiReal communicationStepSize, fmiBoolean newStep)
566 {
567         component_ptr_t comp    = (fmiComponent)c;
568
569         if (comp == NULL) {
570                 return fmiFatal;
571         } else {
572                 fmiReal tstart = currentCommunicationPoint;
573                 fmiReal tcur;
574                 fmiReal tend = currentCommunicationPoint + communicationStepSize;
575                 fmiReal hcur; 
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;
584                 fmiStatus fmistatus;    
585                 size_t k;
586                 size_t counter = 0;
587
588                 fmi_get_continuous_states(comp, states, N_STATES);
589                 fmi_get_event_indicators(comp, z_pre, N_EVENT_INDICATORS);
590
591                 tcur = tstart;
592                 hcur = hdef;
593                 callEventUpdate = fmiFalse;
594                 eventInfo = comp->eventInfo;
595
596                 while (tcur < tend && counter < 100) {
597                         size_t k;
598                         int zero_crossning_event = 0;
599                         counter++;
600
601                         fmi_set_time(comp, tcur);
602                         fmi_get_event_indicators(comp, z_cur, N_EVENT_INDICATORS);
603
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;
608                                         break;
609                                 }
610                         }
611
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);
618                         }
619
620                         /* Updated next time step */
621                         if (eventInfo.upcomingTimeEvent) {
622                                 if (tcur + hdef < eventInfo.nextEventTime) {
623                                         hcur = hdef;
624                                 } else {
625                                         hcur = eventInfo.nextEventTime - tcur;
626                                 }
627                         } else {
628                                 hcur = hdef;
629                         }
630
631                         { 
632                                 double t_full = tcur + hcur;
633                                 if(t_full > tend) {
634                                         hcur = (tend - tcur);
635                                         tcur = tend;                            
636                                 }
637                                 else
638                                         tcur = t_full;
639                         }
640
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); */
646                         }
647
648                         /* Set states */
649                         fmistatus = fmi_set_continuous_states(comp, states, N_STATES);
650                         /* Step is complete */
651                         fmistatus = fmi_completed_integrator_step(comp, &callEventUpdate);
652
653             if(fmistatus != fmiOK) break;
654                 }
655                 for (k = 0; k < N_STATES; k++) { /* Update states */
656                         comp->reals[k] = comp->states[k];
657                 }
658                 return fmiOK;
659         }
660 }
661
662 fmiStatus fmi_get_status(fmiComponent c, const fmiStatusKind s, fmiStatus*  value)
663 {
664         switch (s) {
665                 case fmiDoStepStatus:
666                         /* Return fmiPending if we are waiting. Otherwise the result from fmiDoStep */
667                         *value = fmiOK;
668                         return fmiOK;
669                 default: /* Not defined for status for this function */
670                         return fmiDiscard;
671         }
672 }
673
674 fmiStatus fmi_get_real_status(fmiComponent c, const fmiStatusKind s, fmiReal*    value)
675 {
676         switch (s) {
677                 case fmiLastSuccessfulTime:
678                         /* Return fmiPending if we are waiting. Otherwise return end time for last call to fmiDoStep */
679                         *value = 0.01;
680                         return fmiOK;
681                 default: /* Not defined for status for this function */
682                         return fmiDiscard;
683         }
684 }
685
686 fmiStatus fmi_get_integer_status(fmiComponent c, const fmiStatusKind s, fmiInteger* value)
687 {
688         switch (s) {
689                 default: /* Not defined for status for this function */
690                         return fmiDiscard;
691         }
692 }
693
694 fmiStatus fmi_get_boolean_status(fmiComponent c, const fmiStatusKind s, fmiBoolean* value)
695 {
696         switch (s) {
697                 default: /* Not defined for status for this function */
698                         return fmiDiscard;
699         }
700 }
701
702 fmiStatus fmi_get_string_status(fmiComponent c, const fmiStatusKind s, fmiString*  value)
703 {
704         switch (s) {
705                 case fmiPendingStatus:
706                         *value = "Did fmiDoStep really return with fmiPending? Then its time to implement this function";
707                         return fmiDiscard;
708                 default: /* Not defined for status for this function */
709                         return fmiDiscard;
710         }
711 }