casadi_fmu.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 // software and associated documentation files (the "Software"), to deal in the Software
8 // without restriction, including without limitation the rights to use, copy, modify,
9 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
16 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 //
19 
20 typedef struct {
21  // Name of instance
22  const char* instance_name;
23  // Value for all variables
24  double v[SZ_MEM];
25  // Value for derivatives
26  double d[SZ_MEM];
27  // Has any variable been set since last call
29  // Did continuous states change?
31  // Buffers for evaluation generated code
32  double t;
33  double p[N_P];
34  double x[N_X];
35  double z[N_Z];
36  double xdot[N_X];
37  double alg[N_Z];
38  double u[N_U];
39  double y[N_Y];
40  double zero[N_ZERO];
41  // Event trigger?
42  int zeroind;
43  // Which events can trigger
44  int triggerable[N_ZERO];
45  // Buffers for derivative calculations
46  double dp[N_P];
47  double dx[N_X];
48  double dz[N_Z];
49  double dxdot[N_X];
50  double dalg[N_Z];
51  double du[N_U];
52  double dy[N_Y];
53  double dzero[N_ZERO];
54  // Work vectors for evaluation
55  const double* arg[SZ_ARG];
56  double* res[SZ_RES];
57  casadi_int iw[SZ_IW];
58  double w[SZ_W];
60 
61 int evaluate(casadi_fmi_memory* m) {
62  // Local variables
63  size_t i;
64  int mem, flag;
65  // Copy states, inputs and parameters to input buffers
66  for (i = 0; i < N_X; ++i) m->x[i] = m->v[x_vr[i]];
67  for (i = 0; i < N_Z; ++i) m->z[i] = m->v[z_vr[i]];
68  for (i = 0; i < N_P; ++i) m->p[i] = m->v[p_vr[i]];
69  for (i = 0; i < N_U; ++i) m->u[i] = m->v[u_vr[i]];
70 
71  // Map inputs to evaluation buffer
72  i = 0;
73  m->arg[i++] = &m->t;
74  m->arg[i++] = m->x;
75  m->arg[i++] = m->z;
76  m->arg[i++] = m->p;
77  m->arg[i++] = m->u;
78 
79  // Map outputs to evaluation buffer
80  i = 0;
81  m->res[i++] = m->xdot;
82  m->res[i++] = m->alg;
83  m->res[i++] = m->y;
84  m->res[i++] = m->zero;
85 
86  // Evaluate
87  mem = MODELNAME_checkout();
88  flag = MODELNAME(m->arg, m->res, m->iw, m->w, mem);
89  MODELNAME_release(mem);
90 
91  // Copy from output buffers
92  for (i = 0; i < N_X; ++i) m->v[xdot_vr[i]] = m->xdot[i];
93  for (i = 0; i < N_Z; ++i) m->v[alg_vr[i]] = m->alg[i];
94  for (i = 0; i < N_Y; ++i) m->v[y_vr[i]] = m->y[i];
95  for (i = 0; i < N_ZERO; ++i) m->v[zero_vr[i]] = m->zero[i];
96 
97  return flag;
98 }
99 
100 int evaluate_forward(casadi_fmi_memory* m) {
101  // Local variables
102  size_t i;
103  int mem, flag;
104  // Copy seeds for states, inputs and parameters to input buffers
105  for (i = 0; i < N_X; ++i) m->dx[i] = m->d[x_vr[i]];
106  for (i = 0; i < N_Z; ++i) m->dz[i] = m->d[z_vr[i]];
107  for (i = 0; i < N_P; ++i) m->dp[i] = m->d[p_vr[i]];
108  for (i = 0; i < N_U; ++i) m->du[i] = m->d[u_vr[i]];
109 
110  // Map nondifferentiated inputs to evaluation buffer
111  i = 0;
112  m->arg[i++] = 0; // t
113  m->arg[i++] = m->x;
114  m->arg[i++] = m->z;
115  m->arg[i++] = m->p;
116  m->arg[i++] = m->u;
117 
118  // Map nondifferentiated outputs to evaluation buffer
119  m->arg[i++] = m->xdot;
120  m->arg[i++] = m->alg;
121  m->arg[i++] = m->y;
122  m->arg[i++] = m->zero;
123 
124  // Map forward seeds
125  m->arg[i++] = 0;
126  m->arg[i++] = m->dx;
127  m->arg[i++] = m->dz;
128  m->arg[i++] = m->dp;
129  m->arg[i++] = m->du;
130 
131  // Map forward sensitivities
132  i = 0;
133  m->res[i++] = m->dxdot;
134  m->res[i++] = m->dalg;
135  m->res[i++] = m->dy;
136  m->res[i++] = m->dzero;
137 
138  // Evaluate
139  mem = fwd1_MODELNAME_checkout();
140  flag = fwd1_MODELNAME(m->arg, m->res, m->iw, m->w, mem);
141  fwd1_MODELNAME_release(mem);
142 
143  // Copy from output buffers
144  for (i = 0; i < N_X; ++i) m->d[xdot_vr[i]] = m->dxdot[i];
145  for (i = 0; i < N_Z; ++i) m->d[alg_vr[i]] = m->dalg[i];
146  for (i = 0; i < N_Y; ++i) m->d[y_vr[i]] = m->dy[i];
147  for (i = 0; i < N_ZERO; ++i) m->d[zero_vr[i]] = m->dzero[i];
148 
149  // Return evaluation flag
150  return flag;
151 }
152 
153 int evaluate_adjoint(casadi_fmi_memory* m) {
154  // Local variables
155  size_t i;
156  int mem, flag;
157  // Copy seeds for output buffers
158  for (i = 0; i < N_X; ++i) m->dxdot[i] = m->d[xdot_vr[i]];
159  for (i = 0; i < N_Z; ++i) m->dalg[i] = m->d[alg_vr[i]];
160  for (i = 0; i < N_Y; ++i) m->dy[i] = m->d[y_vr[i]];
161  for (i = 0; i < N_ZERO; ++i) m->dzero[i] = m->d[zero_vr[i]];
162 
163  // Clear sensitivities
164  for (i = 0; i < N_X; ++i) m->dx[i] = 0;
165  for (i = 0; i < N_Z; ++i) m->dz[i] = 0;
166  for (i = 0; i < N_P; ++i) m->dp[i] = 0;
167  for (i = 0; i < N_U; ++i) m->du[i] = 0;
168 
169  // Map nondifferentiated inputs to evaluation buffer
170  i = 0;
171  m->arg[i++] = 0; // t
172  m->arg[i++] = m->x;
173  m->arg[i++] = m->z;
174  m->arg[i++] = m->p;
175  m->arg[i++] = m->u;
176 
177  // Map nondifferentiated outputs to evaluation buffer
178  m->arg[i++] = m->xdot;
179  m->arg[i++] = m->alg;
180  m->arg[i++] = m->y;
181  m->arg[i++] = m->zero;
182 
183  // Map adjoint seeds
184  m->arg[i++] = m->dxdot;
185  m->arg[i++] = m->dalg;
186  m->arg[i++] = m->dy;
187  m->arg[i++] = m->dzero;
188 
189  // Map adjoint sensitivities
190  i = 0;
191  m->res[i++] = 0; // t
192  m->res[i++] = m->dx;
193  m->res[i++] = m->dz;
194  m->res[i++] = m->dp;
195  m->res[i++] = m->du;
196 
197  // Evaluate
198  mem = adj1_MODELNAME_checkout();
199  flag = adj1_MODELNAME(m->arg, m->res, m->iw, m->w, mem);
200  adj1_MODELNAME_release(mem);
201 
202  // Copy from input buffers
203  for (i = 0; i < N_X; ++i) m->d[x_vr[i]] = m->dx[i];
204  for (i = 0; i < N_Z; ++i) m->d[z_vr[i]] = m->dz[i];
205  for (i = 0; i < N_P; ++i) m->d[p_vr[i]] = m->dp[i];
206  for (i = 0; i < N_U; ++i) m->d[u_vr[i]] = m->du[i];
207 
208  // Return evaluation flag
209  return flag;
210 }
211 
212 #if N_ZERO > 0
213 
214 int evaluate_transition(casadi_fmi_memory* m) {
215  // Local variables
216  size_t i;
217  int mem, flag;
218  double zeroind;
219 
220  // Cast event index to double
221  zeroind = (double)m->zeroind;
222 
223  // Copy states, inputs and parameters to input buffers
224  for (i = 0; i < N_X; ++i) m->x[i] = m->v[x_vr[i]];
225  for (i = 0; i < N_Z; ++i) m->z[i] = m->v[z_vr[i]];
226  for (i = 0; i < N_P; ++i) m->p[i] = m->v[p_vr[i]];
227  for (i = 0; i < N_U; ++i) m->u[i] = m->v[u_vr[i]];
228 
229  // Map inputs to evaluation buffer
230  i = 0;
231  m->arg[i++] = &zeroind; // index
232  m->arg[i++] = &m->t; // t
233  m->arg[i++] = m->x; // x
234  m->arg[i++] = m->z; // z
235  m->arg[i++] = m->p; // p
236  m->arg[i++] = m->u; // u
237 
238  // Map outputs to evaluation buffer
239  i = 0;
240  m->res[i++] = m->xdot; // post_x
241  m->res[i++] = m->alg; // post_z
242 
243  // Evaluate
244  mem = transition_MODELNAME_checkout();
245  flag = transition_MODELNAME(m->arg, m->res, m->iw, m->w, mem);
246  transition_MODELNAME_release(mem);
247 
248  // Copy from output buffers
249  for (i = 0; i < N_X; ++i) m->v[x_vr[i]] = m->xdot[i];
250  for (i = 0; i < N_Z; ++i) m->v[z_vr[i]] = m->alg[i];
251 
252  return flag;
253 }
254 #endif // N_ZERO > 0
255 
256 FMI3_Export fmi3Status fmi3Reset(fmi3Instance instance) {
257  // Local variables
258  size_t i;
260  // Cast to memory struct
261  m = (casadi_fmi_memory*)instance;
262  // Initialize variables
263  for (i = 0; i < SZ_MEM; ++i) m->v[i] = start[i];
264  // Reset derivative buffer
265  for (i = 0; i < SZ_MEM; ++i) m->d[i] = 0;
266  // Not evaluated
267  m->up_to_date = 0;
268  // Zero index is negative: No event
269  m->zeroind = -1;
271  // Do not permit events to be triggered unless they have been strictly positive
272  for (i = 0; i < N_ZERO; ++i) m->triggerable[i] = 0;
273  // Always successful return
274  return fmi3OK;
275 }
276 
277 FMI3_Export fmi3Instance fmi3InstantiateModelExchange(
278  fmi3String instanceName,
279  fmi3String instantiationToken,
280  fmi3String resourcePath,
281  fmi3Boolean visible,
282  fmi3Boolean loggingOn,
283  fmi3InstanceEnvironment instanceEnvironment,
284  fmi3LogMessageCallback logMessage) {
285  // Local variables
287  // Unused variables
288  (void)resourcePath; // unused
289  (void)visible; // unused
290  (void)loggingOn; // unused
291  (void)instanceEnvironment; // unused
292  (void)logMessage; // unused
293  // Allocate memory structure
294  m = (casadi_fmi_memory*)malloc(sizeof(casadi_fmi_memory));
295  // If allocation was successful
296  if (m) {
297  // Increase counters for codegen
298  MODELNAME_incref();
299 #if N_ZERO > 0
300  transition_MODELNAME_incref();
301 #endif // N_ZERO > 0
302  // Copy meta data
303  m->instance_name = instanceName;
304  // Call reset function (return flag does not need to be checked)
305  (void)fmi3Reset(m);
306  }
307  // Return pointer to instance, or null
308  return m;
309 }
310 
311 FMI3_Export fmi3Instance fmi3InstantiateCoSimulation(fmi3String instanceName,
312  fmi3String instantiationToken,
313  fmi3String resourcePath,
314  fmi3Boolean visible,
315  fmi3Boolean loggingOn,
316  fmi3Boolean eventModeUsed,
317  fmi3Boolean earlyReturnAllowed,
318  const fmi3ValueReference requiredIntermediateVariables[],
319  size_t nRequiredIntermediateVariables,
320  fmi3InstanceEnvironment instanceEnvironment,
321  fmi3LogMessageCallback logMessage,
322  fmi3IntermediateUpdateCallback intermediateUpdate) {
323  // Not implemented
324  return 0;
325 }
326 
327 FMI3_Export fmi3Instance fmi3InstantiateScheduledExecution(fmi3String instanceName,
328  fmi3String instantiationToken,
329  fmi3String resourcePath,
330  fmi3Boolean visible,
331  fmi3Boolean loggingOn,
332  fmi3InstanceEnvironment instanceEnvironment,
333  fmi3LogMessageCallback logMessage,
334  fmi3ClockUpdateCallback clockUpdate,
335  fmi3LockPreemptionCallback lockPreemption,
336  fmi3UnlockPreemptionCallback unlockPreemption) {
337  // Not implemented
338  return 0;
339 }
340 
341 FMI3_Export fmi3Status fmi3GetNumberOfVariableDependencies(fmi3Instance instance,
342  fmi3ValueReference valueReference,
343  size_t* nDependencies) {
344  // Not implemented
345  return fmi3Fatal;
346 }
347 
348 FMI3_Export fmi3Status fmi3GetVariableDependencies(fmi3Instance instance,
349  fmi3ValueReference dependent,
350  size_t elementIndicesOfDependent[],
351  fmi3ValueReference independents[],
352  size_t elementIndicesOfIndependents[],
353  fmi3DependencyKind dependencyKinds[],
354  size_t nDependencies) {
355  // Not implemented
356  return fmi3Fatal;
357 }
358 
359 FMI3_Export fmi3Status fmi3GetFMUState(fmi3Instance instance,
360  fmi3FMUState* FMUState) {
361  // Not implemented
362  return fmi3Fatal;
363 }
364 
365 FMI3_Export fmi3Status fmi3SetFMUState(fmi3Instance instance,
366  fmi3FMUState FMUState) {
367  // Not implemented
368  return fmi3Fatal;
369 }
370 
371 FMI3_Export fmi3Status fmi3FreeFMUState(fmi3Instance instance,
372  fmi3FMUState* FMUState) {
373  // Not implemented
374  return fmi3Fatal;
375 }
376 
377 FMI3_Export fmi3Status fmi3SerializedFMUStateSize(fmi3Instance instance,
378  fmi3FMUState FMUState,
379  size_t* size) {
380  // Not implemented
381  return fmi3Fatal;
382 }
383 
384 FMI3_Export fmi3Status fmi3SerializeFMUState(fmi3Instance instance,
385  fmi3FMUState FMUState,
386  fmi3Byte serializedState[],
387  size_t size) {
388  // Not implemented
389  return fmi3Fatal;
390 
391  }
392 FMI3_Export fmi3Status fmi3DeserializeFMUState(fmi3Instance instance,
393  const fmi3Byte serializedState[],
394  size_t size,
395  fmi3FMUState* FMUState) {
396  // Not implemented
397  return fmi3Fatal;
398 }
399 
400 FMI3_Export void fmi3FreeInstance(fmi3Instance instance) {
401  if (instance) {
402  // Free memory structure
403  free(instance);
404  // Decrease counters for codegen
405  MODELNAME_decref();
406 #if N_ZERO > 0
407  transition_MODELNAME_decref();
408 #endif // N_ZERO > 0
409  }
410 }
411 
412 FMI3_Export fmi3Status fmi3SetFloat64(
413  fmi3Instance instance,
414  const fmi3ValueReference valueReferences[],
415  size_t nValueReferences,
416  const fmi3Float64 values[],
417  size_t nValues) {
418  // Local variables
420  size_t i, j, var_off, var_sz, val_ind;
421  fmi3ValueReference vr;
422  // Cast to memory struct
423  m = (casadi_fmi_memory*)instance;
424  // Not evaluated
425  m->up_to_date = 0;
426  // Position in values vector
427  val_ind = 0;
428  // Loop over provided variables
429  for (i = 0; i < nValueReferences; ++i) {
430  // Get variable
431  vr = valueReferences[i];
432  // Get offset, size of variable
433  var_off = var_offset[vr];
434  var_sz = var_offset[vr + 1] - var_off;
435  // Copy elements
436  for (j = 0; j < var_sz; ++j) m->v[var_off + j] = values[val_ind++];
437  }
438  // Consistency check
439  if (val_ind != nValues) return fmi3Fatal;
440  // Successful return
441  return fmi3OK;
442 }
443 
444 FMI3_Export fmi3Status fmi3GetFloat64(
445  fmi3Instance instance,
446  const fmi3ValueReference valueReferences[],
447  size_t nValueReferences,
448  fmi3Float64 values[],
449  size_t nValues) {
450  // Local variables
452  size_t i, j, var_off, var_sz, val_ind;
453  fmi3ValueReference vr;
454  // Cast to memory struct
455  m = (casadi_fmi_memory*)instance;
456  // Evaluate, if necessary
457  if (!m->up_to_date) {
458  // Evaluate state derivatives and outputs
459  if (evaluate(m)) return fmi3Error;
460  // Now evaluated
461  m->up_to_date = 1;
462  }
463  // Position in values vector
464  val_ind = 0;
465  // Loop over provided variables
466  for (i = 0; i < nValueReferences; ++i) {
467  // Get variable
468  vr = valueReferences[i];
469  // Get offset, size of variable
470  var_off = var_offset[vr];
471  var_sz = var_offset[vr + 1] - var_off;
472  // Copy elements
473  for (j = 0; j < var_sz; ++j) values[val_ind++] = m->v[var_off + j];
474  }
475  // Consistency check
476  if (val_ind != nValues) return fmi3Fatal;
477  // Successful return
478  return fmi3OK;
479 }
480 
481 FMI3_Export fmi3Status fmi3EnterInitializationMode(
482  fmi3Instance instance,
483  fmi3Boolean toleranceDefined,
484  fmi3Float64 tolerance,
485  fmi3Float64 startTime,
486  fmi3Boolean stopTimeDefined,
487  fmi3Float64 stopTime) {
488  // Local variables
490  // Unused variables
491  (void)toleranceDefined; // unused
492  (void)tolerance; // unused
493  (void)stopTimeDefined; // unused
494  (void)stopTime; // unused
495  // Cast to memory struct
496  m = (casadi_fmi_memory*)instance;
497  // Initialize time
498  m->t = startTime;
499  // Always successful return
500  return fmi3OK;
501 }
502 
503 FMI3_Export fmi3Status fmi3ExitInitializationMode(fmi3Instance instance) {
504  // Unused variables
505  (void)instance; // unused
506  // Always successful return
507  return fmi3OK;
508 }
509 
510 FMI3_Export fmi3Status fmi3EnterContinuousTimeMode(fmi3Instance instance) {
511  // Unused variables
512  (void)instance; // unused
513  // Always successful return
514  return fmi3OK;
515 }
516 
517 FMI3_Export fmi3Status fmi3SetTime(fmi3Instance instance, fmi3Float64 time) {
518  // Local variables
520  // Cast to memory struct
521  m = (casadi_fmi_memory*)instance;
522  // Initialize time
523  m->t = time;
524  // Always successful return
525  return fmi3OK;
526 }
527 
528 FMI3_Export fmi3Status fmi3SetContinuousStates(
529  fmi3Instance instance,
530  const fmi3Float64 continuousStates[],
531  size_t nContinuousStates) {
532  return fmi3SetFloat64(instance, x_vr, N_X, continuousStates, nContinuousStates);
533 }
534 
535 FMI3_Export fmi3Status fmi3GetContinuousStates(
536  fmi3Instance instance,
537  fmi3Float64 continuousStates[],
538  size_t nContinuousStates) {
539  return fmi3GetFloat64(instance, x_vr, N_X, continuousStates, nContinuousStates);
540 }
541 
542 fmi3Status fmi3GetDirectionalDerivative(
543  fmi3Instance instance,
544  const fmi3ValueReference unknowns[],
545  size_t nUnknowns,
546  const fmi3ValueReference knowns[],
547  size_t nKnowns,
548  const fmi3Float64 seed[],
549  size_t nSeed,
550  fmi3Float64 sensitivity[],
551  size_t nSensitivity) {
552  // Local variables
554  size_t i, j, var_off, var_sz, val_ind;
555  fmi3ValueReference vr;
556  int flag;
557  // Cast to memory struct
558  m = (casadi_fmi_memory*)instance;
559  // Evaluate, if necessary
560  if (!m->up_to_date) {
561  // Evaluate state derivatives and outputs
562  if (evaluate(m)) return fmi3Error;
563  // Now evaluated
564  m->up_to_date = 1;
565  }
566  // Pass derivative seeds
567  val_ind = 0;
568  for (i = 0; i < nKnowns; ++i) {
569  // Get variable
570  vr = knowns[i];
571  // Get offset, size of variable
572  var_off = var_offset[vr];
573  var_sz = var_offset[vr + 1] - var_off;
574  // Copy elements
575  for (j = 0; j < var_sz; ++j) m->d[var_off + j] = seed[val_ind++];
576  }
577  // Consistency check
578  if (val_ind != nSeed) return fmi3Fatal;
579  // Evaluate forward directional derivatives
580  flag = evaluate_forward(m);
581  // Collect sensitivities
582  val_ind = 0;
583  for (i = 0; i < nUnknowns; ++i) {
584  // Get variable
585  vr = unknowns[i];
586  // Get offset, size of variable
587  var_off = var_offset[vr];
588  var_sz = var_offset[vr + 1] - var_off;
589  // Copy elements, clear d
590  for (j = 0; j < var_sz; ++j) {
591  sensitivity[val_ind++] = m->d[var_off + j];
592  m->d[var_off + j] = 0;
593  }
594  }
595  // Consistency check
596  if (val_ind != nSensitivity) return fmi3Fatal;
597  // Clear derivative seeds
598  val_ind = 0;
599  for (i = 0; i < nKnowns; ++i) {
600  // Get variable
601  vr = knowns[i];
602  // Get offset, size of variable
603  var_off = var_offset[vr];
604  var_sz = var_offset[vr + 1] - var_off;
605  // Clear elements
606  for (j = 0; j < var_sz; ++j) m->d[var_off + j] = 0;
607  }
608  // Check for evaluation error
609  if (flag) return fmi3Error;
610  // Successful return
611  return fmi3OK;
612 }
613 
614 fmi3Status fmi3GetAdjointDerivative(
615  fmi3Instance instance,
616  const fmi3ValueReference unknowns[],
617  size_t nUnknowns,
618  const fmi3ValueReference knowns[],
619  size_t nKnowns,
620  const fmi3Float64 seed[],
621  size_t nSeed,
622  fmi3Float64 sensitivity[],
623  size_t nSensitivity) {
624  // Local variables
626  size_t i, j, var_off, var_sz, val_ind;
627  fmi3ValueReference vr;
628  int flag;
629  // Cast to memory struct
630  m = (casadi_fmi_memory*)instance;
631  // Evaluate, if necessary
632  if (!m->up_to_date) {
633  // Evaluate state derivatives and outputs
634  if (evaluate(m)) return fmi3Error;
635  // Now evaluated
636  m->up_to_date = 1;
637  }
638  // Pass derivative seeds
639  val_ind = 0;
640  for (i = 0; i < nUnknowns; ++i) {
641  // Get variable
642  vr = unknowns[i];
643  // Get offset, size of variable
644  var_off = var_offset[vr];
645  var_sz = var_offset[vr + 1] - var_off;
646  // Copy elements
647  for (j = 0; j < var_sz; ++j) m->d[var_off + j] = seed[val_ind++];
648  }
649  // Consistency check
650  if (val_ind != nSeed) return fmi3Fatal;
651  // Evaluate adjoint directional derivatives
652  flag = evaluate_adjoint(m);
653  // Collect sensitivities
654  val_ind = 0;
655  for (i = 0; i < nKnowns; ++i) {
656  // Get variable
657  vr = knowns[i];
658  // Get offset, size of variable
659  var_off = var_offset[vr];
660  var_sz = var_offset[vr + 1] - var_off;
661  // Copy elements, clear d
662  for (j = 0; j < var_sz; ++j) {
663  sensitivity[val_ind++] = m->d[var_off + j];
664  m->d[var_off + j] = 0;
665  }
666  }
667  // Consistency check
668  if (val_ind != nSensitivity) return fmi3Fatal;
669  // Clear derivative seeds
670  val_ind = 0;
671  for (i = 0; i < nUnknowns; ++i) {
672  // Get variable
673  vr = unknowns[i];
674  // Get offset, size of variable
675  var_off = var_offset[vr];
676  var_sz = var_offset[vr + 1] - var_off;
677  // Clear elements
678  for (j = 0; j < var_sz; ++j) m->d[var_off + j] = 0;
679  }
680  // Check for evaluation error
681  if (flag) return fmi3Error;
682  // Successful return
683  return fmi3OK;
684 }
685 
686 FMI3_Export const char* fmi3GetVersion(void) {
687  return "3.0";
688 }
689 
690 FMI3_Export fmi3Status fmi3SetDebugLogging(
691  fmi3Instance instance,
692  fmi3Boolean loggingOn,
693  size_t nCategories,
694  const fmi3String categories[]) {
695  // Not implemented: Ignore for now
696  return fmi3OK;
697 }
698 
699 FMI3_Export fmi3Status fmi3Terminate(fmi3Instance instance) {
700  // No cleanup should be needed
701  return fmi3OK;
702 }
703 
704 FMI3_Export fmi3Status fmi3GetFloat32(
705  fmi3Instance instance,
706  const fmi3ValueReference valueReferences[],
707  size_t nValueReferences,
708  fmi3Float32 values[],
709  size_t nValues) {
710  // Type not implemented
711  return fmi3Fatal;
712 }
713 
714 FMI3_Export fmi3Status fmi3GetInt8(
715  fmi3Instance instance,
716  const fmi3ValueReference valueReferences[],
717  size_t nValueReferences,
718  fmi3Int8 values[],
719  size_t nValues) {
720  // Type not implemented
721  return fmi3Fatal;
722 }
723 
724 FMI3_Export fmi3Status fmi3GetUInt8(
725  fmi3Instance instance,
726  const fmi3ValueReference valueReferences[],
727  size_t nValueReferences,
728  fmi3UInt8 values[],
729  size_t nValues) {
730  // Type not implemented
731  return fmi3Fatal;
732 }
733 
734 FMI3_Export fmi3Status fmi3GetInt16(
735  fmi3Instance instance,
736  const fmi3ValueReference valueReferences[],
737  size_t nValueReferences,
738  fmi3Int16 values[],
739  size_t nValues) {
740  // Type not implemented
741  return fmi3Fatal;
742 }
743 
744 FMI3_Export fmi3Status fmi3GetUInt16(
745  fmi3Instance instance,
746  const fmi3ValueReference valueReferences[],
747  size_t nValueReferences,
748  fmi3UInt16 values[],
749  size_t nValues) {
750  // Type not implemented
751  return fmi3Fatal;
752 }
753 
754 FMI3_Export fmi3Status fmi3GetInt32(
755  fmi3Instance instance,
756  const fmi3ValueReference valueReferences[],
757  size_t nValueReferences,
758  fmi3Int32 values[],
759  size_t nValues) {
760  // Type not implemented
761  return fmi3Fatal;
762 }
763 
764 FMI3_Export fmi3Status fmi3GetUInt32(
765  fmi3Instance instance,
766  const fmi3ValueReference valueReferences[],
767  size_t nValueReferences,
768  fmi3UInt32 values[],
769  size_t nValues) {
770  // Type not implemented
771  return fmi3Fatal;
772 }
773 
774 FMI3_Export fmi3Status fmi3GetInt64(
775  fmi3Instance instance,
776  const fmi3ValueReference valueReferences[],
777  size_t nValueReferences,
778  fmi3Int64 values[],
779  size_t nValues) {
780  // Type not implemented
781  return fmi3Fatal;
782 }
783 
784 FMI3_Export fmi3Status fmi3GetUInt64(
785  fmi3Instance instance,
786  const fmi3ValueReference valueReferences[],
787  size_t nValueReferences,
788  fmi3UInt64 values[],
789  size_t nValues) {
790  // Type not implemented
791  return fmi3Fatal;
792 }
793 
794 FMI3_Export fmi3Status fmi3GetBoolean(
795  fmi3Instance instance,
796  const fmi3ValueReference valueReferences[],
797  size_t nValueReferences,
798  fmi3Boolean values[],
799  size_t nValues) {
800  // Type not implemented
801  return fmi3Fatal;
802 }
803 
804 FMI3_Export fmi3Status fmi3GetString(
805  fmi3Instance instance,
806  const fmi3ValueReference valueReferences[],
807  size_t nValueReferences,
808  fmi3String values[],
809  size_t nValues) {
810  // Type not implemented
811  return fmi3Fatal;
812 }
813 
814 FMI3_Export fmi3Status fmi3GetBinary(
815  fmi3Instance instance,
816  const fmi3ValueReference valueReferences[],
817  size_t nValueReferences,
818  size_t valueSizes[],
819  fmi3Binary values[],
820  size_t nValues) {
821  // Type not implemented
822  return fmi3Fatal;
823 }
824 
825 FMI3_Export fmi3Status fmi3GetClock(
826  fmi3Instance instance,
827  const fmi3ValueReference valueReferences[],
828  size_t nValueReferences,
829  fmi3Clock values[]) {
830  // Type not implemented
831  return fmi3Fatal;
832 }
833 
834 FMI3_Export fmi3Status fmi3SetFloat32(fmi3Instance instance,
835  const fmi3ValueReference valueReferences[],
836  size_t nValueReferences,
837  const fmi3Float32 values[],
838  size_t nValues) {
839  // Type not implemented
840  return fmi3Fatal;
841 }
842 
843 FMI3_Export fmi3Status fmi3SetInt8(fmi3Instance instance,
844  const fmi3ValueReference valueReferences[],
845  size_t nValueReferences,
846  const fmi3Int8 values[],
847  size_t nValues) {
848  // Type not implemented
849  return fmi3Fatal;
850 }
851 
852 FMI3_Export fmi3Status fmi3SetUInt8(fmi3Instance instance,
853  const fmi3ValueReference valueReferences[],
854  size_t nValueReferences,
855  const fmi3UInt8 values[],
856  size_t nValues) {
857  // Type not implemented
858  return fmi3Fatal;
859 }
860 
861 FMI3_Export fmi3Status fmi3SetInt16(fmi3Instance instance,
862  const fmi3ValueReference valueReferences[],
863  size_t nValueReferences,
864  const fmi3Int16 values[],
865  size_t nValues) {
866  // Type not implemented
867  return fmi3Fatal;
868 }
869 
870 FMI3_Export fmi3Status fmi3SetUInt16(fmi3Instance instance,
871  const fmi3ValueReference valueReferences[],
872  size_t nValueReferences,
873  const fmi3UInt16 values[],
874  size_t nValues) {
875  // Type not implemented
876  return fmi3Fatal;
877 }
878 
879 FMI3_Export fmi3Status fmi3SetInt32(fmi3Instance instance,
880  const fmi3ValueReference valueReferences[],
881  size_t nValueReferences,
882  const fmi3Int32 values[],
883  size_t nValues) {
884  // Type not implemented
885  return fmi3Fatal;
886 }
887 
888 FMI3_Export fmi3Status fmi3SetUInt32(fmi3Instance instance,
889  const fmi3ValueReference valueReferences[],
890  size_t nValueReferences,
891  const fmi3UInt32 values[],
892  size_t nValues) {
893  // Type not implemented
894  return fmi3Fatal;
895 }
896 
897 FMI3_Export fmi3Status fmi3SetInt64(fmi3Instance instance,
898  const fmi3ValueReference valueReferences[],
899  size_t nValueReferences,
900  const fmi3Int64 values[],
901  size_t nValues) {
902  // Type not implemented
903  return fmi3Fatal;
904 }
905 
906 FMI3_Export fmi3Status fmi3SetUInt64(fmi3Instance instance,
907  const fmi3ValueReference valueReferences[],
908  size_t nValueReferences,
909  const fmi3UInt64 values[],
910  size_t nValues) {
911  // Type not implemented
912  return fmi3Fatal;
913 }
914 
915 FMI3_Export fmi3Status fmi3SetBoolean(fmi3Instance instance,
916  const fmi3ValueReference valueReferences[],
917  size_t nValueReferences,
918  const fmi3Boolean values[],
919  size_t nValues) {
920  // Type not implemented
921  return fmi3Fatal;
922 }
923 
924 FMI3_Export fmi3Status fmi3SetString(fmi3Instance instance,
925  const fmi3ValueReference valueReferences[],
926  size_t nValueReferences,
927  const fmi3String values[],
928  size_t nValues) {
929  // Type not implemented
930  return fmi3Fatal;
931 }
932 
933 FMI3_Export fmi3Status fmi3SetBinary(fmi3Instance instance,
934  const fmi3ValueReference valueReferences[],
935  size_t nValueReferences,
936  const size_t valueSizes[],
937  const fmi3Binary values[],
938  size_t nValues) {
939  // Type not implemented
940  return fmi3Fatal;
941 }
942 
943 FMI3_Export fmi3Status fmi3SetClock(fmi3Instance instance,
944  const fmi3ValueReference valueReferences[],
945  size_t nValueReferences,
946  const fmi3Clock values[]) {
947  // Type not implemented
948  return fmi3Fatal;
949 }
950 
951 FMI3_Export fmi3Status fmi3SetIntervalDecimal(fmi3Instance instance,
952  const fmi3ValueReference valueReferences[],
953  size_t nValueReferences,
954  const fmi3Float64 intervals[]) {
955  // Clocks not implemented
956  return fmi3Fatal;
957 }
958 
959 FMI3_Export fmi3Status fmi3GetIntervalDecimal(fmi3Instance instance,
960  const fmi3ValueReference valueReferences[],
961  size_t nValueReferences,
962  fmi3Float64 intervals[],
963  fmi3IntervalQualifier qualifiers[]) {
964  // Clocks not implemented
965  return fmi3Fatal;
966 }
967 
968 FMI3_Export fmi3Status fmi3GetShiftDecimal(fmi3Instance instance,
969  const fmi3ValueReference valueReferences[],
970  size_t nValueReferences,
971  fmi3Float64 shifts[]) {
972  // Clocks not implemented
973  return fmi3Fatal;
974 }
975 
976 FMI3_Export fmi3Status fmi3SetShiftDecimal(fmi3Instance instance,
977  const fmi3ValueReference valueReferences[],
978  size_t nValueReferences,
979  const fmi3Float64 shifts[]) {
980  // Clocks not implemented
981  return fmi3Fatal;
982 }
983 
984 FMI3_Export fmi3Status fmi3GetNumberOfContinuousStates(fmi3Instance instance,
985  size_t* nContinuousStates) {
986  if (nContinuousStates) *nContinuousStates = N_X;
987  return fmi3OK;
988 }
989 
990 FMI3_Export fmi3Status fmi3GetNumberOfEventIndicators(fmi3Instance instance,
991  size_t* nEventIndicators) {
992  if (nEventIndicators) *nEventIndicators = N_ZERO;
993  return fmi3OK;
994 }
995 
996 FMI3_Export fmi3Status fmi3GetContinuousStateDerivatives(fmi3Instance instance,
997  fmi3Float64 derivatives[], size_t nContinuousStates) {
998  (void)nContinuousStates; // unused
999  return fmi3GetFloat64(instance, xdot_vr, N_X, derivatives, N_X);
1000 }
1001 
1002 FMI3_Export fmi3Status fmi3GetNominalsOfContinuousStates(fmi3Instance instance,
1003  fmi3Float64 nominals[], size_t nContinuousStates) {
1004  // Not implemented: Assume 1 for now
1005  size_t i;
1006  for (i = 0; i < nContinuousStates; ++i) nominals[i] = 1;
1007  return fmi3OK;
1008 }
1009 
1010 FMI3_Export fmi3Status fmi3GetEventIndicators(fmi3Instance instance,
1011  fmi3Float64 eventIndicators[],
1012  size_t nEventIndicators) {
1013 #if N_ZERO > 0
1014  // Local variables
1015  fmi3Status flag;
1016  size_t i;
1017  casadi_fmi_memory* m;
1018  fmi3Float64 most_negative;
1019  // Unused variables
1020  (void)nEventIndicators; // unused
1021  // Cast to memory struct
1022  m = (casadi_fmi_memory*)instance;
1023  // Evaluate zero crossing functions
1024  flag = fmi3GetFloat64(instance, zero_vr, N_ZERO, eventIndicators, N_ZERO);
1025  // Find the most negative, if any, for use in events handling
1026  most_negative = 0;
1027  for (i = 0; i < N_ZERO; ++i) {
1028  if (m->triggerable[i]) {
1029  // Event has been strictly positive already, check if most negative
1030  if (eventIndicators[i] < most_negative) {
1031  most_negative = eventIndicators[i];
1032  m->zeroind = i;
1033  }
1034  } else if (eventIndicators[i] > 1e-6) {
1035  // Event has become strictly positive and is allowed to trigger events
1036  m->triggerable[i] = 1;
1037  }
1038  }
1039  // Return evaluation flag
1040  return flag;
1041 #else
1042  // No zero crossings
1043  return fmi3Fatal;
1044 #endif
1045 }
1046 
1047 FMI3_Export fmi3Status fmi3CompletedIntegratorStep(fmi3Instance instance,
1048  fmi3Boolean noSetFMUStatePriorToCurrentPoint,
1049  fmi3Boolean* enterEventMode,
1050  fmi3Boolean* terminateSimulation) {
1051  // We should not need this as there are no internal iterations
1052  return fmi3OK;
1053 }
1054 
1055 FMI3_Export fmi3Status fmi3EnterEventMode(fmi3Instance instance) {
1056 #if N_ZERO > 0
1057  // Local variables
1058  casadi_fmi_memory* m;
1059  size_t i;
1060  // Cast to memory struct
1061  m = (casadi_fmi_memory*)instance;
1062  // Quick return if no zero crossing
1063  if (m->zeroind < 0) return fmi3OK;
1064  // Call event transition function
1065  if (evaluate_transition(m)) return fmi3Error;
1066  // Mark as not evaluated
1067  m->up_to_date = 0;
1068  // Possible jump in continuous states
1070  // Reset zero crossing index
1071  m->zeroind = -1;
1072  for (i = 0; i < N_ZERO; ++i) m->triggerable[i] = 0;
1073  #endif // N_ZERO > 0
1074  // Successful return
1075  return fmi3OK;
1076 }
1077 
1078 FMI3_Export fmi3Status fmi3UpdateDiscreteStates(fmi3Instance instance,
1079  fmi3Boolean* discreteStatesNeedUpdate,
1080  fmi3Boolean* terminateSimulation,
1081  fmi3Boolean* nominalsOfContinuousStatesChanged,
1082  fmi3Boolean* valuesOfContinuousStatesChanged,
1083  fmi3Boolean* nextEventTimeDefined,
1084  fmi3Float64* nextEventTime) {
1085  // Local variables
1086  casadi_fmi_memory* m;
1087  // Cast to memory struct
1088  m = (casadi_fmi_memory*)instance;
1089  // Discrete variables not yet supported
1090  *discreteStatesNeedUpdate = fmi3False;
1091  *terminateSimulation = fmi3False;
1092  *nominalsOfContinuousStatesChanged = fmi3False;
1093  *valuesOfContinuousStatesChanged = m->continuous_states_changed ? fmi3True : fmi3False;
1094  *nextEventTimeDefined = fmi3False;
1095  // Reset marker
1097  // Successful return
1098  return fmi3OK;
1099 }
1100 
1101 FMI3_Export fmi3Status fmi3EnterConfigurationMode(fmi3Instance instance) {
1102  // Not implemented
1103  return fmi3Fatal;
1104 }
1105 
1106 FMI3_Export fmi3Status fmi3ExitConfigurationMode(fmi3Instance instance) {
1107  // Not implemented
1108  return fmi3Fatal;
1109 }
1110 
1111 FMI3_Export fmi3Status fmi3GetIntervalFraction(fmi3Instance instance,
1112  const fmi3ValueReference valueReferences[],
1113  size_t nValueReferences,
1114  fmi3UInt64 counters[],
1115  fmi3UInt64 resolutions[],
1116  fmi3IntervalQualifier qualifiers[]) {
1117  // Not implemented
1118  return fmi3Fatal;
1119 }
1120 
1121 FMI3_Export fmi3Status fmi3GetShiftFraction(fmi3Instance instance,
1122  const fmi3ValueReference valueReferences[],
1123  size_t nValueReferences,
1124  fmi3UInt64 counters[],
1125  fmi3UInt64 resolutions[]) {
1126  // Not implemented
1127  return fmi3Fatal;
1128 }
1129 
1130 FMI3_Export fmi3Status fmi3SetIntervalFraction(fmi3Instance instance,
1131  const fmi3ValueReference valueReferences[],
1132  size_t nValueReferences,
1133  const fmi3UInt64 counters[],
1134  const fmi3UInt64 resolutions[]) {
1135  // Not implemented
1136  return fmi3Fatal;
1137 }
1138 
1139 FMI3_Export fmi3Status fmi3SetShiftFraction(fmi3Instance instance,
1140  const fmi3ValueReference valueReferences[],
1141  size_t nValueReferences,
1142  const fmi3UInt64 counters[],
1143  const fmi3UInt64 resolutions[]) {
1144  // Not implemented
1145  return fmi3Fatal;
1146 }
1147 
1148 FMI3_Export fmi3Status fmi3EvaluateDiscreteStates(fmi3Instance instance) {
1149  // Not implemented
1150  return fmi3Fatal;
1151 }
1152 
1153 FMI3_Export fmi3Status fmi3EnterStepMode(fmi3Instance instance) {
1154  // Not implemented
1155  return fmi3Fatal;
1156 }
1157 
1158 FMI3_Export fmi3Status fmi3GetOutputDerivatives(fmi3Instance instance,
1159  const fmi3ValueReference valueReferences[],
1160  size_t nValueReferences,
1161  const fmi3Int32 orders[],
1162  fmi3Float64 values[],
1163  size_t nValues) {
1164  // Not implemented
1165  return fmi3Fatal;
1166 }
1167 
1168 FMI3_Export fmi3Status fmi3DoStep(fmi3Instance instance,
1169  fmi3Float64 currentCommunicationPoint,
1170  fmi3Float64 communicationStepSize,
1171  fmi3Boolean noSetFMUStatePriorToCurrentPoint,
1172  fmi3Boolean* eventHandlingNeeded,
1173  fmi3Boolean* terminateSimulation,
1174  fmi3Boolean* earlyReturn,
1175  fmi3Float64* lastSuccessfulTime) {
1176  // Not implemented
1177  return fmi3Fatal;
1178 }
1179 
1180 FMI3_Export fmi3Status fmi3ActivateModelPartition(fmi3Instance instance,
1181  fmi3ValueReference clockReference,
1182  fmi3Float64 activationTime) {
1183  // Not implemented
1184  return fmi3Fatal;
1185 }
double d[SZ_MEM]
Definition: casadi_fmu.hpp:26
double dzero[N_ZERO]
Definition: casadi_fmu.hpp:53
double z[N_Z]
Definition: casadi_fmu.hpp:35
double dz[N_Z]
Definition: casadi_fmu.hpp:48
double p[N_P]
Definition: casadi_fmu.hpp:33
double du[N_U]
Definition: casadi_fmu.hpp:51
double u[N_U]
Definition: casadi_fmu.hpp:38
casadi_int iw[SZ_IW]
Definition: casadi_fmu.hpp:57
double x[N_X]
Definition: casadi_fmu.hpp:34
const char * instance_name
Definition: casadi_fmu.hpp:22
double dx[N_X]
Definition: casadi_fmu.hpp:47
double alg[N_Z]
Definition: casadi_fmu.hpp:37
double w[SZ_W]
Definition: casadi_fmu.hpp:58
double v[SZ_MEM]
Definition: casadi_fmu.hpp:24
double * res[SZ_RES]
Definition: casadi_fmu.hpp:56
int triggerable[N_ZERO]
Definition: casadi_fmu.hpp:44
double dy[N_Y]
Definition: casadi_fmu.hpp:52
double zero[N_ZERO]
Definition: casadi_fmu.hpp:40
int continuous_states_changed
Definition: casadi_fmu.hpp:30
double dp[N_P]
Definition: casadi_fmu.hpp:46
double dalg[N_Z]
Definition: casadi_fmu.hpp:50
double xdot[N_X]
Definition: casadi_fmu.hpp:36
double y[N_Y]
Definition: casadi_fmu.hpp:39
const double * arg[SZ_ARG]
Definition: casadi_fmu.hpp:55
double dxdot[N_X]
Definition: casadi_fmu.hpp:49