Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 58.0% 463 / 0 / 798
Functions: 54.7% 29 / 0 / 53
Branches: 29.3% 123 / 0 / 420

OMCompiler/SimulationRuntime/c/simulation/solver/model_help.c
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <float.h>
32 #include <math.h>
33
34 #include "../../openmodelica.h"
35 #include "../../simulation_data.h"
36 #include "../../openmodelica_func.h"
37 #include "../../util/omc_error.h"
38 #include "../../util/varinfo.h"
39 #include "model_help.h"
40 #include "../arrayIndex.h"
41 #include "../options.h"
42 #include "../simulation_info_json.h"
43 #include "../../util/omc_msvc.h" /* for freaking round! */
44 #include "nonlinearSystem.h"
45 #include "linearSystem.h"
46 #include "mixedSystem.h"
47 #include "delay.h"
48 #include "epsilon.h"
49 #include "discrete_changes.h"
50 #include "stateset.h"
51 #include "spatialDistribution.h"
52 #include "../eval_dep.h"
53 #include "../jacobian_util.h"
54
55 /* Private function prototypes */
56 void* syncTimerListAlloc(const void* data);
57 void syncTimerListFree(void* data);
58 void syncTimerListCopy(void* dest, const void* src);
59
60 int maxEventIterations = 20;
61 double linearSparseSolverMaxDensity = DEFAULT_FLAG_LSS_MAX_DENSITY;
62 int linearSparseSolverMinSize = DEFAULT_FLAG_LSS_MIN_SIZE;
63 double nonlinearSparseSolverMaxDensity = DEFAULT_FLAG_NLSS_MAX_DENSITY;
64 int nonlinearSparseSolverMinSize = DEFAULT_FLAG_NLSS_MIN_SIZE;
65 double maxStepFactor = 1e12;
66 double newtonXTol = 1e-12;
67 double newtonFTol = 1e-12;
68 int newtonMaxSteps = DEFAULT_FLAG_NEWTON_MAX_STEPS;
69 int maxJacUpdate[4] = {10,3,1,1};
70 double steadyStateTol = 1e-3;
71 const size_t SIZERINGBUFFER = 3;
72 int compiledInDAEMode = 0;
73 int compiledWithSymSolver = 0;
74 double numericalDifferentiationDeltaXlinearize = 1e-8;
75 double numericalDifferentiationDeltaXsolver = 1e-8;
76 double homAdaptBend = 0.5;
77 double homHEps = 1e-5;
78 int homMaxLambdaSteps = 0;
79 int homMaxNewtonSteps = 20;
80 int homMaxTries = 10;
81 double homTauDecreasingFactor = 10.0;
82 double homTauDecreasingFactorPredictor = 2.0;
83 double homTauIncreasingFactor = 2.0;
84 double homTauIncreasingThreshold = 10.0;
85 double homTauMax = 10.0;
86 double homTauMin = 1e-4;
87 double homTauStart = 0.2;
88 int homBacktraceStrategy = 1;
89
90 static double tolZC;
91
92 /*!
93 * @brief Update discrete system with event iteration.
94 *
95 * Evaluate `functionDAE` until no discrete changes occur.
96 * If `data->simulationInfo->sampleActivated` is active deactivate samples after
97 * first event iteration and update next sample time for that sample event.
98 *
99 * @param data Data object.
100 * @param threadData thread data for error handling.
101 */
102 2 void updateDiscreteSystem(DATA *data, threadData_t *threadData)
103 {
104 int numEventIterations = 0;
105 modelica_boolean discreteChanged = FALSE;
106 modelica_boolean relationChanged = FALSE;
107 2 data->simulationInfo->needToIterate = FALSE;
108 2 data->simulationInfo->discreteStateChanged = FALSE;
109
110 2 data->simulationInfo->callStatistics.updateDiscreteSystem++;
111
112 2 data->callback->function_updateRelations(data, threadData, 0);
113 2 updateRelationsPre(data);
114 2 storeRelations(data);
115
116 2 data->callback->functionDAE(data, threadData);
117
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (OMC_ERROR_RAISED()) {
118 return;
119 }
120
121 2 relationChanged = checkRelations(data);
122 2 discreteChanged = checkForDiscreteChanges(data, threadData);
123
124 /* Deactivate possible sample events after first event iteration */
125
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(data->simulationInfo->sampleActivated)
126 {
127 ✗ for(int i = 0; i < data->modelData->nSamples; i++)
128 {
129 ✗ if(data->simulationInfo->samples[i])
130 {
131 ✗ data->simulationInfo->samples[i] = 0;
132 ✗ data->simulationInfo->nextSampleTimes[i] += data->modelData->samplesInfo[i].interval;
133 }
134 }
135 }
136
137 /* Update discrete system until nothing changes any more */
138
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 while(discreteChanged || data->simulationInfo->needToIterate || relationChanged)
139 {
140 ✗ data->simulationInfo->discreteStateChanged = TRUE;
141 ✗ storePreValues(data);
142 ✗ updateRelationsPre(data);
143
144 ✗ printRelations(data, OMC_LOG_EVENTS_V);
145 ✗ printZeroCrossings(data, OMC_LOG_EVENTS_V);
146
147 ✗ data->callback->functionDAE(data, threadData);
148 ✗ if (OMC_ERROR_RAISED()) {
149 return;
150 }
151
152 ✗ numEventIterations++;
153 ✗ if(numEventIterations > maxEventIterations) {
154 ✗ throwStreamPrint(threadData, "Simulation terminated due to too many, i.e. %d, event iterations.\nThis could either indicate an inconsistent system or an undersized limit of event iterations.\nThe limit of event iterations can be specified using the runtime flag '–%s=<value>'.", maxEventIterations, FLAG_NAME[FLAG_MAX_EVENT_ITERATIONS]);
155 }
156
157 ✗ relationChanged = checkRelations(data);
158 ✗ discreteChanged = checkForDiscreteChanges(data, threadData);
159 }
160 2 storeRelations(data);
161 }
162
163 /*! \fn saveZeroCrossings
164 *
165 * Function saves all zero-crossing values
166 *
167 * \param [ref] [data]
168 */
169 2 void saveZeroCrossings(DATA* data, threadData_t *threadData)
170 {
171 long i = 0;
172
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for(i=0;i<data->modelData->nZeroCrossings;i++)
174 ✗ data->simulationInfo->zeroCrossingsPre[i] = data->simulationInfo->zeroCrossings[i];
175
176 2 data->callback->function_ZeroCrossings(data, threadData, data->simulationInfo->zeroCrossings);
177 2 }
178
179 /*! \fn copyStartValuestoInitValues
180 *
181 * Function to copy all start values to initial values
182 *
183 * \param [ref] [data]
184 */
185 1 void copyStartValuestoInitValues(DATA *data)
186 {
187 /* just copy all start values to initial */
188 1 setAllParamsToStart(data->simulationInfo, data->modelData);
189 1 setAllVarsToStart(data->localData[0], data->simulationInfo, data->modelData);
190 1 storePreValues(data);
191 1 overwriteOldSimulationData(data);
192 1 }
193
194 /**
195 * @brief Print real variables `first` to `last`-1, one line per scalar element.
196 */
197 3 static void printRealVars(DATA *data, int ringSegment, int stream, long first, long last)
198 {
199 long i;
200 size_t k, idx;
201 3 SIMULATION_INFO *sInfo = data->simulationInfo;
202 3 SIMULATION_DATA *sData = data->localData[ringSegment];
203 char name[2048];
204
205
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 for(i=first; i<last; ++i) {
206 2 STATIC_REAL_DATA *var = &data->modelData->realVarsData[i];
207
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (k = 0; k < var->dimension.scalar_length; ++k) {
208 4 idx = sInfo->realVarsIndex[i] + k;
209 4 printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
210 4 infoStreamPrint(stream, 0, "%zu: %s = %g (pre: %g)", idx+1, name, sData->realVars[idx], sInfo->realVarsPre[idx]);
211 }
212 }
213 3 }
214
215 /*! \fn printAllVars
216 *
217 * prints all variable values
218 *
219 * \param [in] [data]
220 * \param [in] [ringSegment]
221 * \param [in] [stream]
222 *
223 * \author wbraun
224 */
225 1 void printAllVars(DATA *data, int ringSegment, int stream)
226 {
227 long i;
228 size_t k, idx;
229 1 MODEL_DATA *mData = data->modelData;
230 1 SIMULATION_INFO *sInfo = data->simulationInfo;
231 1 SIMULATION_DATA *sData = data->localData[ringSegment];
232 char name[2048];
233
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!OMC_ACTIVE_STREAM(stream)) return;
235
236 1 infoStreamPrint(stream, 1, "Print values for buffer segment %d regarding point in time : %g", ringSegment, sData->timeValue);
237
238 1 infoStreamPrint(stream, 1, "states variables");
239 1 printRealVars(data, ringSegment, stream, 0, mData->nStatesArray);
240 1 messageClose(stream);
241
242 1 infoStreamPrint(stream, 1, "derivatives variables");
243 1 printRealVars(data, ringSegment, stream, mData->nStatesArray, 2*mData->nStatesArray);
244 1 messageClose(stream);
245
246 1 infoStreamPrint(stream, 1, "other real values");
247 1 printRealVars(data, ringSegment, stream, 2*mData->nStatesArray, mData->nVariablesRealArray);
248 1 messageClose(stream);
249
250 1 infoStreamPrint(stream, 1, "integer variables");
251
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for(i=0; i<mData->nVariablesIntegerArray; ++i) {
252 1 STATIC_INTEGER_DATA *var = &mData->integerVarsData[i];
253
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (k = 0; k < var->dimension.scalar_length; ++k) {
254 2 idx = sInfo->integerVarsIndex[i] + k;
255 2 printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
256 2 infoStreamPrint(stream, 0, "%zu: %s = " OMC_INT_FORMAT " (pre: " OMC_INT_FORMAT ")", idx+1, name, sData->integerVars[idx], sInfo->integerVarsPre[idx]);
257 }
258 }
259 1 messageClose(stream);
260
261 1 infoStreamPrint(stream, 1, "boolean variables");
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<mData->nVariablesBooleanArray; ++i) {
263 ✗ STATIC_BOOLEAN_DATA *var = &mData->booleanVarsData[i];
264 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
265 ✗ idx = sInfo->booleanVarsIndex[i] + k;
266 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
267 ✗ infoStreamPrint(stream, 0, "%zu: %s = %s (pre: %s)", idx+1, name, sData->booleanVars[idx] ? "true" : "false", sInfo->booleanVarsPre[idx] ? "true" : "false");
268 }
269 }
270 1 messageClose(stream);
271
272 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
273 1 infoStreamPrint(stream, 1, "string variables");
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<mData->nVariablesStringArray; ++i) {
275 ✗ STATIC_STRING_DATA *var = &mData->stringVarsData[i];
276 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
277 ✗ idx = sInfo->stringVarsIndex[i] + k;
278 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
279 ✗ infoStreamPrint(stream, 0, "%zu: %s = %s (pre: %s)", idx+1, name,
280 ✗ omc_string_data(sData->stringVars[idx]),
281 ✗ omc_string_data(sInfo->stringVarsPre[idx]));
282 }
283 }
284 1 messageClose(stream);
285 #endif
286 1 messageClose(stream);
287 }
288
289 /*! \fn printParameters
290 *
291 * prints all parameter values
292 *
293 * \param [in] [data]
294 * \param [in] [stream]
295 *
296 * \author wbraun
297 */
298 ✗ void printParameters(DATA *data, int stream)
299 {
300 long i;
301 size_t k, idx;
302 ✗ MODEL_DATA *mData = data->modelData;
303 ✗ SIMULATION_INFO *sInfo = data->simulationInfo;
304
305 char name[2048];
306
307 ✗ if (!OMC_ACTIVE_STREAM(stream)) {
308 ✗ return;
309 }
310
311 ✗ infoStreamPrint(stream, 1, "parameter values");
312
313 ✗ if (0 < mData->nParametersRealArray)
314 {
315 ✗ infoStreamPrint(stream, 1, "real parameters");
316 ✗ for(i=0; i<mData->nParametersRealArray; ++i) {
317 ✗ STATIC_REAL_DATA *var = &mData->realParameterData[i];
318 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
319 ✗ idx = sInfo->realParamsIndex[i] + k;
320 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
321 ✗ infoStreamPrint(stream, 0, "[%zu] parameter Real %s(start=%g, fixed=%s) = %g", idx+1, name,
322 ✗ real_get(var->attribute.start, attributeElementIndex(&var->attribute.start, k)),
323 ✗ var->attribute.fixed ? "true" : "false",
324 ✗ sInfo->realParameter[idx]);
325 }
326 }
327 ✗ messageClose(stream);
328 }
329
330 ✗ if (0 < mData->nParametersIntegerArray)
331 {
332 ✗ infoStreamPrint(stream, 1, "integer parameters");
333 ✗ for(i=0; i<mData->nParametersIntegerArray; ++i) {
334 ✗ STATIC_INTEGER_DATA *var = &mData->integerParameterData[i];
335 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
336 ✗ idx = sInfo->integerParamsIndex[i] + k;
337 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
338 ✗ infoStreamPrint(stream, 0, "[%zu] parameter Integer %s(start=" OMC_INT_FORMAT ", fixed=%s) = " OMC_INT_FORMAT, idx+1, name,
339 ✗ integer_get(var->attribute.start, attributeElementIndex(&var->attribute.start, k)),
340 ✗ var->attribute.fixed ? "true" : "false",
341 ✗ sInfo->integerParameter[idx]);
342 }
343 }
344 ✗ messageClose(stream);
345 }
346
347 ✗ if (0 < mData->nParametersBooleanArray)
348 {
349 ✗ infoStreamPrint(stream, 1, "boolean parameters");
350 ✗ for(i=0; i<mData->nParametersBooleanArray; ++i) {
351 ✗ STATIC_BOOLEAN_DATA *var = &mData->booleanParameterData[i];
352 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
353 ✗ idx = sInfo->booleanParamsIndex[i] + k;
354 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
355 ✗ infoStreamPrint(stream, 0, "[%zu] parameter Boolean %s(start=%s, fixed=%s) = %s", idx+1, name,
356 ✗ boolean_get(var->attribute.start, attributeElementIndex(&var->attribute.start, k)) ? "true" : "false",
357 ✗ var->attribute.fixed ? "true" : "false",
358 ✗ sInfo->booleanParameter[idx] ? "true" : "false");
359 }
360 }
361 ✗ messageClose(stream);
362 }
363
364 ✗ if (0 < mData->nParametersStringArray)
365 {
366 ✗ infoStreamPrint(stream, 1, "string parameters");
367 ✗ for(i=0; i<mData->nParametersStringArray; ++i) {
368 ✗ STATIC_STRING_DATA *var = &mData->stringParameterData[i];
369 ✗ for (k = 0; k < var->dimension.scalar_length; ++k) {
370 ✗ modelica_string start = string_get(var->attribute.start, attributeElementIndex(&var->attribute.start, k));
371 ✗ idx = sInfo->stringParamsIndex[i] + k;
372 ✗ printArrayElementName(name, sizeof(name), var->info.name, &var->dimension, k, FALSE);
373 ✗ infoStreamPrint(stream, 0, "[%zu] parameter String %s(start=\"%s\") = \"%s\"", idx+1, name,
374 start ? omc_string_data(start) : "",
375 ✗ omc_string_data(sInfo->stringParameter[idx]));
376 }
377 }
378 ✗ messageClose(stream);
379 }
380
381 ✗ messageClose(stream);
382 }
383
384 /**
385 * @brief Prints sparse structure.
386 *
387 * Use to print e.g. sparse Jacobian matrix.
388 * Only prints if stream is active and sparse pattern is non NULL and of size > 0.
389 *
390 * @param sparsePattern Matrix to print.
391 * @param sizeRows Number of rows of matrix.
392 * @param sizeCols Number of columns of matrix.
393 * @param stream Steam to print to.
394 * @param name Name of matrix.
395 */
396 1 void printSparseStructure(SPARSE_PATTERN *sparsePattern, int sizeRows, int sizeCols, int stream, const char* name)
397 {
398 /* Variables */
399 unsigned int row, col, i, j;
400 char *buffer;
401
402
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (!OMC_ACTIVE_STREAM(stream))
403 {
404 return;
405 }
406
407 /* Catch empty sparsePattern */
408
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if (sparsePattern == NULL || sizeRows <= 0 || sizeCols <= 0)
409 {
410 ✗ infoStreamPrint(stream, 0, "No sparse structure available for \"%s\".", name);
411 ✗ return;
412 }
413
414 1 buffer = (char*)omc_alloc_interface.malloc(sizeof(char)* 2*sizeCols + 4);
415
416 1 infoStreamPrint(stream, 1, "Sparse structure of %s [size: %ux%u]", name, sizeRows, sizeCols);
417 1 infoStreamPrint(stream, 0, "%u non-zero elements", sparsePattern->nnz);
418
419 1 infoStreamPrint(stream, 1, "Transposed sparse structure (rows: states)");
420 i=0;
421
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for(row=0; row < sizeRows; row++)
422 {
423 j=0;
424
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 for(col=0; i < sparsePattern->leadindex[row+1]; col++)
425 {
426
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 if(sparsePattern->index[i] == col)
427 {
428 2 buffer[j++] = '*';
429 2 ++i;
430 }
431 else
432 {
433 1 buffer[j++] = ' ';
434 }
435 3 buffer[j++] = ' ';
436 }
437 2 buffer[j] = '\0';
438 2 infoStreamPrint(stream, 0, "%s", buffer);
439 }
440 1 messageClose(stream);
441 1 messageClose(stream);
442 }
443
444 /**
445 * @brief Check if sparsity pattern can describe regular matrix.
446 *
447 * @param sparsePattern Sparsity pattern.
448 * @param nlsSize size of non-linear loop / size of square matrix.
449 * @param stream Stream for logging.
450 * @return modelica_boolean False if sparsity pattern can't describe regular matrix, true otherwise.
451 */
452 ✗ modelica_boolean sparsitySanityCheck(SPARSE_PATTERN *sparsePattern, int nlsSize, int stream)
453 {
454 int i;
455 char *colCheck;
456
457 ✗ if (sparsePattern == NULL || nlsSize <= 0)
458 {
459 ✗ warningStreamPrint(stream, 0, "No sparse structure available.");
460 ✗ return FALSE;
461 }
462
463 ✗ if (sparsePattern->nnz < nlsSize) {
464 ✗ warningStreamPrint(stream, 0, "Sparsity pattern of %dx%d has ony %d non-zero elements.", nlsSize,nlsSize, sparsePattern->nnz);
465 ✗ return FALSE;
466 }
467
468 /* Use sizeCols (actual allocated columns) for leadindex bounds to avoid OOB when
469 * the Jacobian has fewer seed directions than NLS unknowns (nSeeds < nlsSize). */
470 {
471 ✗ unsigned int nCheckCols = sparsePattern->sizeCols < (unsigned int)nlsSize
472 ? sparsePattern->sizeCols : (unsigned int)nlsSize;
473 ✗ for(i=1; i < (int)nCheckCols; i++)
474 {
475 ✗ if(sparsePattern->leadindex[i] == sparsePattern->leadindex[i-1]) {
476 ✗ warningStreamPrint(stream, 0, "Sparsity pattern row %d has no non-zero elements.", i);
477 ✗ return FALSE;
478 }
479 }
480 }
481
482 /* check cols (or rows?) */
483 ✗ colCheck = (char*) calloc(nlsSize, sizeof(char));
484
485 ✗ for(i=0; i < (int)sparsePattern->leadindex[sparsePattern->sizeCols]; i++)
486 {
487 /* Row index may exceed nlsSize when the Jacobian has auxiliary equations
488 * beyond the NLS residuals (sizeRows > nCols). Skip those rows to avoid
489 * out-of-bounds writes into colCheck[nlsSize]. */
490 ✗ if (sparsePattern->index[i] >= (unsigned int)nlsSize) continue;
491 ✗ colCheck[sparsePattern->index[i]] = TRUE;
492 }
493
494 ✗ for(i=0; i < nlsSize; i++)
495 {
496 ✗ if(!colCheck[i]) {
497 ✗ warningStreamPrint(stream, 0, "Sparsity pattern column %d has no non-zero elements.", i);
498 ✗ free(colCheck);
499 ✗ return FALSE;
500 }
501 }
502
503 ✗ free(colCheck);
504 ✗ return TRUE;
505 }
506
507 /*! \fn printRelations
508 *
509 * print all relations
510 *
511 * \param [in] [data]
512 * \param [in] [stream]
513 */
514 1 void printRelations(DATA *data, int stream)
515 {
516 long i;
517
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!OMC_ACTIVE_STREAM(stream))
519 {
520 return;
521 }
522
523 ✗ infoStreamPrint(stream, 1, "status of relations at time=%.12g", data->localData[0]->timeValue);
524 ✗ for(i=0; i<data->modelData->nRelations; i++)
525 {
526 ✗ infoStreamPrint(stream, 0, "[%ld] (pre: %s) %s = %s", i+1, data->simulationInfo->relationsPre[i] ? " true" : "false", data->simulationInfo->relations[i] ? " true" : "false", data->callback->relationDescription(i));
527 }
528 ✗ messageClose(stream);
529 }
530
531 /*! \fn printZeroCrossings
532 *
533 * print all zero crossings
534 *
535 * \param [in] [data]
536 * \param [in] [stream]
537 */
538 1 void printZeroCrossings(DATA *data, int stream)
539 {
540 long i;
541
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!OMC_ACTIVE_STREAM(stream))
543 {
544 return;
545 }
546
547 ✗ infoStreamPrint(stream, 1, "status of zero crossings at time=%.12g", data->localData[0]->timeValue);
548 ✗ for(i=0; i<data->modelData->nZeroCrossings; i++)
549 {
550 int *eq_indexes;
551 ✗ const char *exp_str = data->callback->zeroCrossingDescription(i,&eq_indexes);
552 ✗ infoStreamPrintWithEquationIndexes(stream, omc_dummyFileInfo, 0, eq_indexes, "[%ld] (pre: %2.g) %2.g = %s", i+1, data->simulationInfo->zeroCrossingsPre[i], data->simulationInfo->zeroCrossings[i], exp_str);
553 }
554 ✗ messageClose(stream);
555 }
556
557 /*! \fn overwriteOldSimulationData
558 *
559 * Stores variables (states, derivatives and algebraic) to be used
560 * by e.g. numerical solvers to extrapolate values as start values.
561 *
562 * This function overwrites all old value with the current.
563 * This function is called after events.
564 *
565 * \param [ref] [data]
566 *
567 * \author lochel
568 */
569 4 void overwriteOldSimulationData(DATA *data)
570 {
571 long i;
572
573
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
12 for(i=1; i<ringBufferLength(data->simulationData); ++i)
574 {
575 8 data->localData[i]->timeValue = data->localData[i-1]->timeValue;
576 8 memcpy(data->localData[i]->realVars, data->localData[i-1]->realVars, sizeof(modelica_real)*data->modelData->nVariablesReal);
577 8 memcpy(data->localData[i]->integerVars, data->localData[i-1]->integerVars, sizeof(modelica_integer)*data->modelData->nVariablesInteger);
578 8 memcpy(data->localData[i]->booleanVars, data->localData[i-1]->booleanVars, sizeof(modelica_boolean)*data->modelData->nVariablesBoolean);
579 8 omc_string_slots_store(data->localData[i]->stringVars, data->localData[i-1]->stringVars, data->modelData->nVariablesString);
580 }
581 4 }
582
583 /*! \fn continueSimulationData
584 *
585 * Makes the current slot of the ring buffer continue from the previous step.
586 *
587 * `rotateRingBuffer` moves `localData[0]` onto the slot that held the values of
588 * `SIZERINGBUFFER` steps ago, and the equations only overwrite what they compute,
589 * so a variable read before the equation that computes it - a dynamic-tearing
590 * constraint check, a nonlinear system's old value - would see that stale slot.
591 *
592 * Call directly after `rotateRingBuffer` + `lookupRingBuffer`.
593 *
594 * \param [ref] [data]
595 */
596 1 void continueSimulationData(DATA *data)
597 {
598
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if(ringBufferLength(data->simulationData) < 2)
599 return;
600
601 1 data->localData[0]->timeValue = data->localData[1]->timeValue;
602 1 memcpy(data->localData[0]->realVars, data->localData[1]->realVars, sizeof(modelica_real)*data->modelData->nVariablesReal);
603 1 memcpy(data->localData[0]->integerVars, data->localData[1]->integerVars, sizeof(modelica_integer)*data->modelData->nVariablesInteger);
604 1 memcpy(data->localData[0]->booleanVars, data->localData[1]->booleanVars, sizeof(modelica_boolean)*data->modelData->nVariablesBoolean);
605 1 omc_string_slots_store(data->localData[0]->stringVars, data->localData[1]->stringVars, data->modelData->nVariablesString);
606 }
607
608 /*! \fn copyRingBufferSimulationData
609 *
610 * Copy RingBuffer simulation data from DATA to a new ring buffer.
611 *
612 * This function is used to initialize the ring buffer of dassl after events.
613 *
614 * \param [in] [data]
615 * \param [out] [destData]
616 * \param [out] [destRing]
617 *
618 *
619 * \author wbraun
620 */
621 ✗ void copyRingBufferSimulationData(DATA *data, threadData_t *threadData, SIMULATION_DATA **destData, RINGBUFFER* destRing)
622 {
623 long i;
624
625 ✗ assertStreamPrint(threadData, ringBufferLength(data->simulationData) == ringBufferLength(destRing), "copy ring buffer failed, because of different sizes.");
626
627 ✗ for(i=0; i<ringBufferLength(data->simulationData); ++i)
628 {
629 ✗ destData[i]->timeValue = data->localData[i]->timeValue;
630 ✗ memcpy(destData[i]->realVars, data->localData[i]->realVars, sizeof(modelica_real)*data->modelData->nVariablesReal);
631 ✗ memcpy(destData[i]->integerVars, data->localData[i]->integerVars, sizeof(modelica_integer)*data->modelData->nVariablesInteger);
632 ✗ memcpy(destData[i]->booleanVars, data->localData[i]->booleanVars, sizeof(modelica_boolean)*data->modelData->nVariablesBoolean);
633 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
634 ✗ omc_string_slots_store(destData[i]->stringVars, data->localData[i]->stringVars, data->modelData->nVariablesString);
635 #endif
636 }
637 ✗ }
638
639 /*
640 * print information about ring buffer simulation data
641 */
642 ✗ void printRingBufferSimulationData(RINGBUFFER *rb, DATA* data)
643 {
644 ✗ for (int i = 0; i < ringBufferLength(rb); i++)
645 {
646 ✗ messageClose(OMC_LOG_STDOUT); // FIXME what does this belong to?
647 ✗ SIMULATION_DATA *sdata = (SIMULATION_DATA *)getRingData(rb, i);
648 ✗ infoStreamPrint(OMC_LOG_STDOUT, 1, "Time: %g ", sdata->timeValue);
649
650 ✗ infoStreamPrint(OMC_LOG_STDOUT, 1, "RingBuffer Real Variable");
651 ✗ for (int j = 0; j < data->modelData->nVariablesReal; ++j)
652 {
653 ✗ infoStreamPrint(OMC_LOG_STDOUT, 0, "%d: %s = %g ", j+1, data->modelData->realVarsData[j].info.name, sdata->realVars[j]);
654 }
655 ✗ messageClose(OMC_LOG_STDOUT);
656
657 ✗ infoStreamPrint(OMC_LOG_STDOUT, 1, "RingBuffer Integer Variable");
658 ✗ for (int j = 0; j < data->modelData->nVariablesInteger; ++j)
659 {
660 ✗ infoStreamPrint(OMC_LOG_STDOUT, 0, "%d: %s = " OMC_INT_FORMAT " ", j+1, data->modelData->integerVarsData[j].info.name, sdata->integerVars[j]);
661 }
662 ✗ messageClose(OMC_LOG_STDOUT);
663
664 ✗ infoStreamPrint(OMC_LOG_STDOUT, 1, "RingBuffer Boolean Variable");
665 ✗ for(int j = 0; j < data->modelData->nVariablesBoolean; ++j)
666 {
667 ✗ infoStreamPrint(OMC_LOG_STDOUT, 0, "%d: %s = %s ", j+1, data->modelData->booleanVarsData[j].info.name, sdata->booleanVars[j] ? "true" : "false");
668 }
669 ✗ messageClose(OMC_LOG_STDOUT);
670 }
671 ✗ }
672
673 /* \fn restoreExtrapolationDataOld
674 *
675 * Restores variables (states, derivatives and algebraic).
676 *
677 * This function overwrites all variable with old values.
678 * This function is called while the initialization to be ab lvalue required as left operand of assignmentle
679 * initialize all ZeroCrossing relations.
680 *
681 * \param [ref] [data]
682 *
683 * \author wbraun
684 */
685 ✗ void restoreExtrapolationDataOld(DATA *data)
686 {
687 long i;
688
689 ✗ for(i=1; i<ringBufferLength(data->simulationData); ++i)
690 {
691 ✗ data->localData[i-1]->timeValue = data->localData[i]->timeValue;
692 ✗ memcpy(data->localData[i-1]->realVars, data->localData[i]->realVars, sizeof(modelica_real)*data->modelData->nVariablesReal);
693 ✗ memcpy(data->localData[i-1]->integerVars, data->localData[i]->integerVars, sizeof(modelica_integer)*data->modelData->nVariablesInteger);
694 ✗ memcpy(data->localData[i-1]->booleanVars, data->localData[i]->booleanVars, sizeof(modelica_boolean)*data->modelData->nVariablesBoolean);
695 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
696 ✗ omc_string_slots_store(data->localData[i-1]->stringVars, data->localData[i]->stringVars, data->modelData->nVariablesString);
697 #endif
698 }
699 ✗ }
700
701 /* A start attribute with a single element (`each` start value) holds the
702 start value of every element of the array variable. */
703 4 static void copyRealStart(const real_array start, modelica_real *dest, size_t scalar_length)
704 {
705 size_t k;
706
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (base_array_nr_of_elements(start) == 1) {
707
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
12 for (k = 0; k < scalar_length; k++) dest[k] = real_get(start, 0);
708 } else {
709 ✗ copy_real_array_data_mem(start, dest);
710 }
711 4 }
712
713 2 static void copyIntegerStart(const integer_array start, modelica_integer *dest, size_t scalar_length)
714 {
715 size_t k;
716
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (base_array_nr_of_elements(start) == 1) {
717
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
6 for (k = 0; k < scalar_length; k++) dest[k] = integer_get(start, 0);
718 } else {
719 ✗ copy_integer_array_data_mem(start, dest);
720 }
721 2 }
722
723 ✗ static void copyBooleanStart(const boolean_array start, modelica_boolean *dest, size_t scalar_length)
724 {
725 size_t k;
726 ✗ if (base_array_nr_of_elements(start) == 1) {
727 ✗ for (k = 0; k < scalar_length; k++) dest[k] = boolean_get(start, 0);
728 } else {
729 ✗ copy_boolean_array_data_mem(start, dest);
730 }
731 ✗ }
732
733 ✗ static void copyStringStart(const string_array start, modelica_string *dest, size_t scalar_length)
734 {
735 size_t k;
736 ✗ if (base_array_nr_of_elements(start) == 1) {
737 ✗ for (k = 0; k < scalar_length; k++) omc_string_store(dest + k, string_get(start, 0));
738 } else {
739 ✗ copy_string_array_data_mem(start, dest);
740 }
741 ✗ }
742
743 /**
744 * @brief Set all variables to their start attribute.
745 *
746 * @param simulationData Simulation data with variable start values to update.
747 * @param simulationInfo Simulation info with array variable mapping to scalar
748 * simulation data.
749 * @param modelData Model data with start attributes.
750 */
751 2 void setAllVarsToStart(SIMULATION_DATA *simulationData, const SIMULATION_INFO *simulationInfo, const MODEL_DATA *modelData)
752 {
753 long array_idx;
754
755
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (array_idx = 0; array_idx < modelData->nVariablesRealArray; ++array_idx)
756 {
757 4 copyRealStart(
758 modelData->realVarsData[array_idx].attribute.start,
759 4 &simulationData->realVars[simulationInfo->realVarsIndex[array_idx]],
760 4 modelData->realVarsData[array_idx].dimension.scalar_length);
761 }
762
763
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (array_idx = 0; array_idx < modelData->nVariablesIntegerArray; ++array_idx)
764 {
765 2 copyIntegerStart(
766 modelData->integerVarsData[array_idx].attribute.start,
767 2 &simulationData->integerVars[simulationInfo->integerVarsIndex[array_idx]],
768 2 modelData->integerVarsData[array_idx].dimension.scalar_length);
769 }
770
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nVariablesBooleanArray; ++array_idx)
772 {
773 ✗ copyBooleanStart(
774 modelData->booleanVarsData[array_idx].attribute.start,
775 ✗ &simulationData->booleanVars[simulationInfo->booleanVarsIndex[array_idx]],
776 ✗ modelData->booleanVarsData[array_idx].dimension.scalar_length);
777 }
778
779 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING > 0
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nVariablesStringArray; ++array_idx)
781 {
782 ✗ copyStringStart(
783 modelData->stringVarsData[array_idx].attribute.start,
784 ✗ &simulationData->stringVars[simulationInfo->stringVarsIndex[array_idx]],
785 ✗ modelData->stringVarsData[array_idx].dimension.scalar_length);
786 }
787 #endif
788 2 }
789
790 /**
791 * @brief Set all parameters to their start attribute.
792 *
793 * @param simulationInfo Simulation info with parameter start values to update
794 * and array variable mapping to scalar representation.
795 * @param modelData Model data with start attributes.
796 */
797 2 void setAllParamsToStart(SIMULATION_INFO *simulationInfo, const MODEL_DATA *modelData)
798 {
799 long array_idx;
800
801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nParametersRealArray; ++array_idx)
802 {
803 ✗ copyRealStart(
804 modelData->realParameterData[array_idx].attribute.start,
805 ✗ &simulationInfo->realParameter[simulationInfo->realParamsIndex[array_idx]],
806 ✗ modelData->realParameterData[array_idx].dimension.scalar_length);
807 }
808
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nParametersIntegerArray; ++array_idx)
810 {
811 ✗ copyIntegerStart(
812 modelData->integerParameterData[array_idx].attribute.start,
813 ✗ &simulationInfo->integerParameter[simulationInfo->integerParamsIndex[array_idx]],
814 ✗ modelData->integerParameterData[array_idx].dimension.scalar_length);
815 }
816
817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nParametersBooleanArray; ++array_idx)
818 {
819 ✗ copyBooleanStart(
820 modelData->booleanParameterData[array_idx].attribute.start,
821 ✗ &simulationInfo->booleanParameter[simulationInfo->booleanParamsIndex[array_idx]],
822 ✗ modelData->booleanParameterData[array_idx].dimension.scalar_length);
823 }
824
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (array_idx = 0; array_idx < modelData->nParametersStringArray; ++array_idx)
826 {
827 ✗ copyStringStart(
828 modelData->stringParameterData[array_idx].attribute.start,
829 ✗ &simulationInfo->stringParameter[simulationInfo->stringParamsIndex[array_idx]],
830 ✗ modelData->stringParameterData[array_idx].dimension.scalar_length);
831 }
832 2 }
833
834 /*! \fn storeOldValues
835 *
836 * This function copies states and time into their old-values for event handling.
837 *
838 * \param [ref] [data]
839 *
840 * \author wbraun
841 */
842 2 void storeOldValues(DATA *data)
843 {
844 2 SIMULATION_DATA *sData = data->localData[0];
845 2 MODEL_DATA *mData = data->modelData;
846 2 SIMULATION_INFO *sInfo = data->simulationInfo;
847
848 2 sInfo->timeValueOld = sData->timeValue;
849 2 memcpy(sInfo->realVarsOld, sData->realVars, sizeof(modelica_real)*mData->nVariablesReal);
850 2 memcpy(sInfo->integerVarsOld, sData->integerVars, sizeof(modelica_integer)*mData->nVariablesInteger);
851 2 memcpy(sInfo->booleanVarsOld, sData->booleanVars, sizeof(modelica_boolean)*mData->nVariablesBoolean);
852 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
853 2 omc_string_slots_store(sInfo->stringVarsOld, sData->stringVars, mData->nVariablesString);
854 #endif
855 2 }
856
857 /*! \fn restoreOldValues
858 *
859 * This function copies old-values to current localData
860 *
861 * \param [ref] [data]
862 *
863 * \author wbraun
864 */
865 ✗ void restoreOldValues(DATA *data)
866 {
867 ✗ SIMULATION_DATA *sData = data->localData[0];
868 ✗ MODEL_DATA *mData = data->modelData;
869 ✗ SIMULATION_INFO *sInfo = data->simulationInfo;
870
871 ✗ sData->timeValue = sInfo->timeValueOld;
872 ✗ memcpy(sData->realVars, sInfo->realVarsOld, sizeof(modelica_real)*mData->nVariablesReal);
873 ✗ memcpy(sData->integerVars, sInfo->integerVarsOld, sizeof(modelica_integer)*mData->nVariablesInteger);
874 ✗ memcpy(sData->booleanVars, sInfo->booleanVarsOld, sizeof(modelica_boolean)*mData->nVariablesBoolean);
875 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
876 ✗ omc_string_slots_store(sData->stringVars, sInfo->stringVarsOld, mData->nVariablesString);
877 #endif
878 ✗ }
879
880 /*! \fn storePreValues
881 *
882 * This function copies all the values into their pre-values.
883 *
884 * \param [ref] [data]
885 *
886 * \author lochel
887 */
888 5 void storePreValues(DATA *data)
889 {
890 5 SIMULATION_DATA *sData = data->localData[0];
891 5 MODEL_DATA *mData = data->modelData;
892 5 SIMULATION_INFO *sInfo = data->simulationInfo;
893
894 5 memcpy(sInfo->realVarsPre, sData->realVars, sizeof(modelica_real)*mData->nVariablesReal);
895 5 memcpy(sInfo->integerVarsPre, sData->integerVars, sizeof(modelica_integer)*mData->nVariablesInteger);
896 5 memcpy(sInfo->booleanVarsPre, sData->booleanVars, sizeof(modelica_boolean)*mData->nVariablesBoolean);
897 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
898 5 omc_string_slots_store(sInfo->stringVarsPre, sData->stringVars, mData->nVariablesString);
899 #endif
900 5 }
901
902 /*! \fn checkRelations
903 *
904 * This function check if at least one backupRelation has changed
905 *
906 * \param [ref] [data]
907 *
908 * \author wbraun
909 */
910 2 modelica_boolean checkRelations(DATA *data)
911 {
912 int i;
913
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for(i=0; i<data->modelData->nRelations; ++i)
915 ✗ if(data->simulationInfo->relationsPre[i] != data->simulationInfo->relations[i])
916 return 1;
917
918 return 0;
919 }
920
921 /*! \fn updateRelationsPre
922 *
923 * This function stores a copy of relations into relationsPre.
924 *
925 * \param [ref] [data]
926 *
927 * \author lochel
928 */
929 2 void updateRelationsPre(DATA *data)
930 {
931 2 memcpy(data->simulationInfo->relationsPre, data->simulationInfo->relations, sizeof(modelica_boolean)*data->modelData->nRelations);
932 2 }
933
934 /*! \fn storeRelations
935 *
936 * This function stores a copy of relationPre. This is needed for the event
937 * iteration.
938 *
939 * \param [out] [data]
940 *
941 * \author lochel
942 */
943 5 void storeRelations(DATA* data)
944 {
945 5 memcpy(data->simulationInfo->storedRelations, data->simulationInfo->relations, sizeof(modelica_boolean)*data->modelData->nRelations);
946 5 }
947
948 /**
949 * @brief Get time of next sample event if one is defined.
950 *
951 * Function returns 0 if a time is defined and -1 otherwise.
952 *
953 * @param data Data
954 * @param nextSampleEvent On output time of next sample event.
955 * @return int 1 if a sample event is defined, 0 otherwise
956 */
957 ✗ int getNextSampleTimeFMU(DATA *data, double *nextSampleEvent)
958 {
959 ✗ if(0 < data->modelData->nSamples || data->simulationInfo->nextSampleEvent < DBL_MAX)
960 {
961 ✗ infoStreamPrint(OMC_LOG_EVENTS, 0, "Next event time = %f", data->simulationInfo->nextSampleEvent);
962 ✗ *nextSampleEvent = data->simulationInfo->nextSampleEvent;
963 ✗ return 1 /* TRUE */;
964 }
965
966 return 0 /* FALSE */;
967 }
968
969 /*! \fn updateNextSampleEvent
970 *
971 * Sets nextSampleEvent to the earliest of the next sample times and the next
972 * time a relation on time switches.
973 */
974 1 void updateNextSampleEvent(DATA *data, threadData_t *threadData)
975 {
976 long i;
977 double next = DBL_MAX;
978
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<data->modelData->nSamples; ++i) {
980 ✗ next = fmin(next, data->simulationInfo->nextSampleTimes[i]);
981 }
982
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (data->callback->function_nextTimeEvent) {
983 1 next = fmin(next, data->callback->function_nextTimeEvent(data, threadData));
984 }
985 1 data->simulationInfo->nextSampleEvent = next;
986 1 }
987
988 /**
989 * @brief Allocates static model data.
990 *
991 * Allocate memory for model data of variables, parameters, sensitivity
992 * parameters and alias variables.
993 * Won't allocate memory for dynamic memory inside struct.
994 *
995 * Free with `freeModelDataVars`.
996 *
997 * @param modelData Pointer to model data.
998 * @param allocAlias If true allocate memory for `modelData->realAlias`, ... , `modelData->stringAlias`.
999 * Alias variables aren't used in FMI C runtime.
1000 * @param threadData Thread data for error handling, can be `NULL`.
1001 *
1002 */
1003 1 void allocModelDataVars(MODEL_DATA* modelData, modelica_boolean allocAlias, threadData_t* threadData)
1004 {
1005 // Variables
1006 1 modelData->realVarsData = (STATIC_REAL_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nVariablesRealArray * sizeof(STATIC_REAL_DATA));
1007
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 assertStreamPrint(threadData, modelData->nVariablesRealArray == 0 || modelData->realVarsData != NULL, "Out of memory");
1008
1009 1 modelData->integerVarsData = (STATIC_INTEGER_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nVariablesIntegerArray * sizeof(STATIC_INTEGER_DATA));
1010
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 assertStreamPrint(threadData, modelData->nVariablesIntegerArray == 0 || modelData->integerVarsData != NULL, "Out of memory");
1011
1012 1 modelData->booleanVarsData = (STATIC_BOOLEAN_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nVariablesBooleanArray * sizeof(STATIC_BOOLEAN_DATA));
1013
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nVariablesBooleanArray == 0 || modelData->booleanVarsData != NULL, "Out of memory");
1014
1015 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1016 1 modelData->stringVarsData = (STATIC_STRING_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nVariablesStringArray * sizeof(STATIC_STRING_DATA));
1017
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nVariablesStringArray == 0 || modelData->stringVarsData != NULL, "Out of memory");
1018 #endif
1019
1020 // Parameter
1021 1 modelData->realParameterData = (STATIC_REAL_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nParametersRealArray * sizeof(STATIC_REAL_DATA));
1022
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nParametersRealArray == 0 || modelData->realParameterData != NULL, "Out of memory");
1023
1024 1 modelData->integerParameterData = (STATIC_INTEGER_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nParametersIntegerArray * sizeof(STATIC_INTEGER_DATA));
1025
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nParametersIntegerArray == 0 || modelData->integerParameterData != NULL, "Out of memory");
1026
1027 1 modelData->booleanParameterData = (STATIC_BOOLEAN_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nParametersBooleanArray * sizeof(STATIC_BOOLEAN_DATA));
1028
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nParametersBooleanArray == 0 || modelData->booleanParameterData != NULL, "Out of memory");
1029
1030 1 modelData->stringParameterData = (STATIC_STRING_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nParametersStringArray * sizeof(STATIC_STRING_DATA));
1031
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nParametersStringArray == 0 || modelData->stringParameterData != NULL, "Out of memory");
1032
1033 // Sensitivity
1034 1 modelData->realSensitivityData = (STATIC_REAL_DATA*) omc_alloc_interface.malloc_uncollectable(modelData->nSensitivityVars * sizeof(STATIC_REAL_DATA));
1035
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nSensitivityVars == 0 || modelData->realSensitivityData != NULL, "Out of memory");
1036
1037 // Alias Variables
1038 // TODO: alias variables aren't used at all for FMUs.
1039
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (allocAlias) {
1040 1 modelData->realAlias = (DATA_REAL_ALIAS*) omc_alloc_interface.malloc_uncollectable(modelData->nAliasRealArray * sizeof(DATA_REAL_ALIAS));
1041
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nAliasRealArray == 0 || modelData->realAlias != NULL, "Out of memory");
1042
1043 1 modelData->integerAlias = (DATA_INTEGER_ALIAS*) omc_alloc_interface.malloc_uncollectable(modelData->nAliasIntegerArray * sizeof(DATA_INTEGER_ALIAS));
1044
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nAliasIntegerArray == 0 || modelData->integerAlias != NULL, "Out of memory");
1045
1046 1 modelData->booleanAlias = (DATA_BOOLEAN_ALIAS*) omc_alloc_interface.malloc_uncollectable(modelData->nAliasBooleanArray * sizeof(DATA_BOOLEAN_ALIAS));
1047
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nAliasBooleanArray == 0 || modelData->booleanAlias != NULL, "Out of memory");
1048
1049 1 modelData->stringAlias = (DATA_STRING_ALIAS*) omc_alloc_interface.malloc_uncollectable(modelData->nAliasStringArray * sizeof(DATA_STRING_ALIAS));
1050
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, modelData->nAliasStringArray == 0 || modelData->stringAlias != NULL, "Out of memory");
1051 }
1052 else {
1053 ✗ modelData->realAlias = NULL;
1054 ✗ modelData->integerAlias = NULL;
1055 ✗ modelData->booleanAlias = NULL;
1056 ✗ modelData->stringAlias = NULL;
1057 }
1058 1 }
1059
1060 /**
1061 * @brief Free var info and var data.
1062 *
1063 * VAR_INFO strings get allocated in `read_var_info`.
1064 *
1065 * @param modelData Pointer to model data.
1066 */
1067 1 void freeModelDataVars(MODEL_DATA* modelData)
1068 {
1069 unsigned int i;
1070
1071 // Variables
1072
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for(i=0; i < modelData->nVariablesRealArray; i++) {
1073 2 freeVarInfo(&modelData->realVarsData[i].info);
1074 }
1075
1076
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for(i=0; i < modelData->nVariablesIntegerArray; i++) {
1077 1 freeVarInfo(&modelData->integerVarsData[i].info);
1078 }
1079
1080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nVariablesBooleanArray; i++) {
1081 ✗ freeVarInfo(&modelData->booleanVarsData[i].info);
1082 }
1083
1084 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nVariablesStringArray; i++) {
1086 ✗ freeVarInfo(&modelData->stringVarsData[i].info);
1087 }
1088 #endif
1089
1090 // Parameters
1091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nParametersRealArray; i++) {
1092 ✗ freeVarInfo(&modelData->realParameterData[i].info);
1093 }
1094
1095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nParametersIntegerArray; i++) {
1096 ✗ freeVarInfo(&modelData->integerParameterData[i].info);
1097 }
1098
1099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nParametersBooleanArray; i++) {
1100 ✗ freeVarInfo(&modelData->booleanParameterData[i].info);
1101 }
1102
1103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nParametersStringArray; i++) {
1104 ✗ freeVarInfo(&modelData->stringParameterData[i].info);
1105 }
1106
1107 // Sensitivity
1108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i < modelData->nSensitivityVars; i++) {
1109 ✗ freeVarInfo(&modelData->realSensitivityData[i].info);
1110 }
1111
1112 // Alias Variables
1113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (modelData->realAlias != NULL) {
1114 ✗ for(i=0; i < modelData->nAliasRealArray; i++) {
1115 ✗ freeVarInfo(&modelData->realAlias[i].info);
1116 }
1117 }
1118
1119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (modelData->integerAlias != NULL) {
1120 ✗ for(i=0; i < modelData->nAliasIntegerArray; i++) {
1121 ✗ freeVarInfo(&modelData->integerAlias[i].info);
1122 }
1123 }
1124
1125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (modelData->booleanAlias != NULL) {
1126 ✗ for(i=0; i < modelData->nAliasBooleanArray; i++) {
1127 ✗ freeVarInfo(&modelData->booleanAlias[i].info);
1128 }
1129 }
1130
1131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (modelData->stringAlias != NULL) {
1132 ✗ for(i=0; i < modelData->nAliasStringArray; i++) {
1133 ✗ freeVarInfo(&modelData->stringAlias[i].info);
1134 }
1135 }
1136
1137 1 freeModelDataVarArrays(modelData);
1138 1 }
1139
1140 /**
1141 * @brief Free the var data arrays allocated by `allocModelDataVars`.
1142 *
1143 * Leaves the VAR_INFO strings alone. Use this instead of `freeModelDataVars`
1144 * when the strings were not allocated by `read_var_info`, e.g. for FMUs, where
1145 * `read_input_fmu` points them at string literals in the generated code.
1146 *
1147 * @param modelData Pointer to model data.
1148 */
1149 /* The per-variable start/min/max/nominal arrays and unit strings hang off the
1150 var-data blocks, so they have to go before the blocks themselves. */
1151 3 static void freeRealVarAttributes(STATIC_REAL_DATA *vars, long n)
1152 {
1153 long i;
1154
1155
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 if (!vars) {
1156 return;
1157 }
1158
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (i = 0; i < n; i++) {
1159 2 omc_array_release(&vars[i].attribute.start);
1160 2 omc_array_release(&vars[i].attribute.min);
1161 2 omc_array_release(&vars[i].attribute.max);
1162 2 omc_array_release(&vars[i].attribute.nominal);
1163 omc_string_move(&vars[i].attribute.unit, NULL);
1164 omc_string_move(&vars[i].attribute.displayUnit, NULL);
1165 }
1166 }
1167
1168 2 static void freeIntegerVarAttributes(STATIC_INTEGER_DATA *vars, long n)
1169 {
1170 long i;
1171
1172
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 if (!vars) {
1173 return;
1174 }
1175
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (i = 0; i < n; i++) {
1176 1 omc_array_release(&vars[i].attribute.start);
1177 1 omc_array_release(&vars[i].attribute.min);
1178 1 omc_array_release(&vars[i].attribute.max);
1179 }
1180 }
1181
1182 static void freeBooleanVarAttributes(STATIC_BOOLEAN_DATA *vars, long n)
1183 {
1184 long i;
1185
1186 2 if (!vars) {
1187 return;
1188 }
1189 ✗ for (i = 0; i < n; i++) {
1190 ✗ omc_array_release(&vars[i].attribute.start);
1191 }
1192 }
1193
1194 static void freeStringVarAttributes(STATIC_STRING_DATA *vars, long n)
1195 {
1196 long i;
1197
1198 2 if (!vars) {
1199 return;
1200 }
1201 ✗ for (i = 0; i < n; i++) {
1202 ✗ omc_string_array_release(&vars[i].attribute.start);
1203 }
1204 }
1205
1206 /* An alias carries a unit of its own. */
1207 4 static void freeAliasAttributes(DATA_ALIAS *alias, long n)
1208 {
1209 long i;
1210
1211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!alias) {
1212 return;
1213 }
1214 ✗ for (i = 0; i < n; i++) {
1215 ✗ omc_string_move(&alias[i].unit, NULL);
1216 omc_string_move(&alias[i].displayUnit, NULL);
1217 }
1218 }
1219
1220 1 void freeModelDataVarArrays(MODEL_DATA* modelData)
1221 {
1222 1 freeRealVarAttributes(modelData->realVarsData, modelData->nVariablesRealArray);
1223 1 freeRealVarAttributes(modelData->realParameterData, modelData->nParametersRealArray);
1224 1 freeRealVarAttributes(modelData->realSensitivityData, modelData->nSensitivityVars);
1225 1 freeIntegerVarAttributes(modelData->integerVarsData, modelData->nVariablesIntegerArray);
1226 1 freeIntegerVarAttributes(modelData->integerParameterData, modelData->nParametersIntegerArray);
1227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 freeBooleanVarAttributes(modelData->booleanVarsData, modelData->nVariablesBooleanArray);
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 freeBooleanVarAttributes(modelData->booleanParameterData, modelData->nParametersBooleanArray);
1229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 freeStringVarAttributes(modelData->stringVarsData, modelData->nVariablesStringArray);
1230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 freeStringVarAttributes(modelData->stringParameterData, modelData->nParametersStringArray);
1231 1 freeAliasAttributes(modelData->realAlias, modelData->nAliasRealArray);
1232 1 freeAliasAttributes(modelData->integerAlias, modelData->nAliasIntegerArray);
1233 1 freeAliasAttributes(modelData->booleanAlias, modelData->nAliasBooleanArray);
1234 1 freeAliasAttributes(modelData->stringAlias, modelData->nAliasStringArray);
1235
1236 // Variables
1237 1 omc_alloc_interface.free_uncollectable(modelData->realVarsData);
1238 1 omc_alloc_interface.free_uncollectable(modelData->integerVarsData);
1239 1 omc_alloc_interface.free_uncollectable(modelData->booleanVarsData);
1240 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1241 1 omc_alloc_interface.free_uncollectable(modelData->stringVarsData);
1242 #endif
1243
1244 // Parameters
1245 1 omc_alloc_interface.free_uncollectable(modelData->realParameterData);
1246 1 omc_alloc_interface.free_uncollectable(modelData->integerParameterData);
1247 1 omc_alloc_interface.free_uncollectable(modelData->booleanParameterData);
1248 1 omc_alloc_interface.free_uncollectable(modelData->stringParameterData);
1249
1250 // Sensitivity
1251 1 omc_alloc_interface.free_uncollectable(modelData->realSensitivityData);
1252
1253 // Alias Variables (not allocated for FMUs, see `allocModelDataVars`)
1254 1 omc_alloc_interface.free_uncollectable(modelData->realAlias);
1255 1 omc_alloc_interface.free_uncollectable(modelData->integerAlias);
1256 1 omc_alloc_interface.free_uncollectable(modelData->booleanAlias);
1257 1 omc_alloc_interface.free_uncollectable(modelData->stringAlias);
1258 1 }
1259
1260 /**
1261 * @brief Allocate memory for scalar attributes.
1262 *
1263 * Only allocate arrays of length 1 for the scalar case.
1264 * Used for scalar only FMI case.
1265 *
1266 * Memory is freed with `freeModelDataVars`.
1267 *
1268 * @param modelData Pointer to model data.
1269 */
1270 ✗ void scalarAllocArrayAttributes(MODEL_DATA* modelData) {
1271 size_t i;
1272
1273 // Variables
1274 ✗ for(i = 0; i < modelData->nVariablesRealArray; i++) {
1275 ✗ simple_alloc_1d_real_array(&modelData->realVarsData[i].attribute.start, 1);
1276 ✗ simple_alloc_1d_real_array(&modelData->realVarsData[i].attribute.nominal, 1);
1277 ✗ simple_alloc_1d_real_array(&modelData->realVarsData[i].attribute.min, 1);
1278 ✗ simple_alloc_1d_real_array(&modelData->realVarsData[i].attribute.max, 1);
1279 }
1280
1281 ✗ for(i = 0; i < modelData->nVariablesIntegerArray; i++) {
1282 ✗ simple_alloc_1d_integer_array(&modelData->integerVarsData[i].attribute.start, 1);
1283 ✗ simple_alloc_1d_integer_array(&modelData->integerVarsData[i].attribute.min, 1);
1284 ✗ simple_alloc_1d_integer_array(&modelData->integerVarsData[i].attribute.max, 1);
1285 }
1286 ✗ for(i = 0; i < modelData->nVariablesBooleanArray; i++) {
1287 ✗ simple_alloc_1d_boolean_array(&modelData->booleanVarsData[i].attribute.start, 1);
1288 }
1289 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1290 ✗ for(i = 0; i < modelData->nVariablesStringArray; i++) {
1291 ✗ simple_alloc_1d_string_array(&modelData->stringVarsData[i].attribute.start, 1);
1292 }
1293 #endif
1294
1295 // Parameter
1296 ✗ for(i = 0; i < modelData->nParametersRealArray; i++) {
1297 ✗ simple_alloc_1d_real_array(&modelData->realParameterData[i].attribute.start, 1);
1298 ✗ simple_alloc_1d_real_array(&modelData->realParameterData[i].attribute.nominal, 1);
1299 ✗ simple_alloc_1d_real_array(&modelData->realParameterData[i].attribute.min, 1);
1300 ✗ simple_alloc_1d_real_array(&modelData->realParameterData[i].attribute.max, 1);
1301 }
1302 ✗ for(i = 0; i < modelData->nParametersIntegerArray; i++) {
1303 ✗ simple_alloc_1d_integer_array(&modelData->integerParameterData[i].attribute.start, 1);
1304 ✗ simple_alloc_1d_integer_array(&modelData->integerParameterData[i].attribute.min, 1);
1305 ✗ simple_alloc_1d_integer_array(&modelData->integerParameterData[i].attribute.max, 1);
1306 }
1307 ✗ for(i = 0; i < modelData->nParametersBooleanArray; i++) {
1308 ✗ simple_alloc_1d_boolean_array(&modelData->booleanParameterData[i].attribute.start, 1);
1309 }
1310 ✗ for(i = 0; i < modelData->nParametersStringArray; i++) {
1311 ✗ simple_alloc_1d_string_array(&modelData->stringParameterData[i].attribute.start, 1);
1312 }
1313 ✗ }
1314
1315 /*!
1316 * @brief Initialize `data` struct.
1317 *
1318 * Simulation data:
1319 *
1320 * - Allocate ring buffer.
1321 *
1322 * Model data:
1323 *
1324 * - Allocate variable and parameter arrays.
1325 *
1326 * Simulation info:
1327 *
1328 * - Allocate clocks.
1329 * - Allocate zero crossings.
1330 * - Buffer for pre variables.
1331 * - Buffer for linear and non-linear solvers.
1332 *
1333 * @param data Partially initialized struct `DATA` to initialize.
1334 * Uses information about number of variables from `data->modelData`.
1335 * @param threadData Used for error handling.
1336 */
1337 1 void initializeDataStruc(DATA *data, threadData_t *threadData)
1338 {
1339 1 SIMULATION_DATA tmpSimData = {0};
1340 size_t i = 0;
1341
1342 /* RingBuffer */
1343 1 data->simulationData = 0;
1344 1 data->simulationData = allocRingBuffer(SIZERINGBUFFER, sizeof(SIMULATION_DATA));
1345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!data->simulationData) {
1346 ✗ throwStreamPrint(threadData, "Your memory is not strong enough for our ringbuffer!");
1347 }
1348
1349 /* Index map for array variables */
1350 1 allocateArrayIndexMaps(data->modelData, data->simulationInfo, threadData);
1351 1 computeVarIndices(data->simulationInfo, data->modelData);
1352
1353 1 data->modelData->nStates = data->simulationInfo->realVarsIndex[data->modelData->nStatesArray];
1354 1 data->modelData->nVariablesReal = data->simulationInfo->realVarsIndex[data->modelData->nVariablesRealArray];
1355 1 data->modelData->nVariablesInteger = data->simulationInfo->integerVarsIndex[data->modelData->nVariablesIntegerArray];
1356 1 data->modelData->nVariablesBoolean = data->simulationInfo->booleanVarsIndex[data->modelData->nVariablesBooleanArray];
1357 1 data->modelData->nVariablesString = data->simulationInfo->stringVarsIndex[data->modelData->nVariablesStringArray];
1358
1359 1 data->modelData->nParametersReal = data->simulationInfo->realParamsIndex[data->modelData->nParametersRealArray];
1360 1 data->modelData->nParametersInteger = data->simulationInfo->integerParamsIndex[data->modelData->nParametersIntegerArray];
1361 1 data->modelData->nParametersBoolean = data->simulationInfo->booleanParamsIndex[data->modelData->nParametersBooleanArray];
1362 1 data->modelData->nParametersString = data->simulationInfo->stringParamsIndex[data->modelData->nParametersStringArray];
1363
1364 1 data->modelData->nAliasReal = data->simulationInfo->realAliasIndex[data->modelData->nAliasRealArray];
1365 1 data->modelData->nAliasInteger = data->simulationInfo->integerAliasIndex[data->modelData->nAliasIntegerArray];
1366 1 data->modelData->nAliasBoolean = data->simulationInfo->booleanAliasIndex[data->modelData->nAliasBooleanArray];
1367 1 data->modelData->nAliasString = data->simulationInfo->stringAliasIndex[data->modelData->nAliasStringArray];
1368
1369 /* Reverse map for scalarized variables */
1370 1 allocateArrayReverseIndexMaps(data->modelData, data->simulationInfo, threadData);
1371 1 computeVarReverseIndices(data->simulationInfo, data->modelData);
1372
1373 /* init DAG and eval selection for functionODE */
1374 1 data->modelData->dag = NULL;
1375 1 data->simulationInfo->evalSelection = NULL;
1376
1377 /* prepare RingBuffer */
1378
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for (i = 0; i < SIZERINGBUFFER; i++) {
1379 /* set time value */
1380 /*
1381 * fix issue #11855, always take the startTime provided in modeldescription.xml
1382 * to handle models that have startTime > 0 (e.g) startTime = 0.2
1383 */
1384 3 tmpSimData.timeValue = data->simulationInfo->startTime;
1385 /* buffer for all variable values */
1386 3 tmpSimData.realVars = (modelica_real*) calloc(data->modelData->nVariablesReal, sizeof(modelica_real));
1387
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 assertStreamPrint(threadData, 0 == data->modelData->nVariablesReal || 0 != tmpSimData.realVars, "out of memory");
1388 3 tmpSimData.integerVars = (modelica_integer*) calloc(data->modelData->nVariablesInteger, sizeof(modelica_integer));
1389
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 assertStreamPrint(threadData, 0 == data->modelData->nVariablesInteger || 0 != tmpSimData.integerVars, "out of memory");
1390 3 tmpSimData.booleanVars = (modelica_boolean*) calloc(data->modelData->nVariablesBoolean, sizeof(modelica_boolean));
1391
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 assertStreamPrint(threadData, 0 == data->modelData->nVariablesBoolean || 0 != tmpSimData.booleanVars, "out of memory");
1392 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1393 3 tmpSimData.stringVars = (modelica_string*) omc_alloc_interface.malloc_uncollectable(data->modelData->nVariablesString * sizeof(modelica_string));
1394
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 assertStreamPrint(threadData, 0 == data->modelData->nVariablesString || 0 != tmpSimData.stringVars, "out of memory");
1395 #endif
1396 3 appendRingData(data->simulationData, &tmpSimData);
1397 }
1398 1 data->localData = (SIMULATION_DATA**) omc_alloc_interface.malloc_uncollectable(SIZERINGBUFFER * sizeof(SIMULATION_DATA));
1399 memset(data->localData, 0, SIZERINGBUFFER * sizeof(SIMULATION_DATA));
1400 1 lookupRingBuffer(data->simulationData, (void**) data->localData);
1401
1402 /* modelData vars, parameter and alias arrays are already allocated in read_input_xml */
1403
1404 1 data->modelData->samplesInfo = (SAMPLE_INFO*) omc_alloc_interface.malloc_uncollectable(data->modelData->nSamples * sizeof(SAMPLE_INFO));
1405 1 data->simulationInfo->nextSampleEvent = data->simulationInfo->startTime;
1406 1 data->simulationInfo->nextSampleTimes = (double*) calloc(data->modelData->nSamples, sizeof(double));
1407 1 data->simulationInfo->samples = (modelica_boolean*) calloc(data->modelData->nSamples, sizeof(modelica_boolean));
1408
1409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nBaseClocks > 0) {
1410 ✗ data->simulationInfo->baseClocks = (BASECLOCK_DATA*) calloc(data->modelData->nBaseClocks, sizeof(BASECLOCK_DATA));
1411 ✗ data->simulationInfo->intvlTimers = allocList(syncTimerListAlloc, syncTimerListFree, syncTimerListCopy);
1412 } else {
1413 1 data->simulationInfo->baseClocks = NULL;
1414 1 data->simulationInfo->intvlTimers = NULL;
1415 }
1416
1417 1 data->simulationInfo->spatialDistributionData = allocSpatialDistribution(data->modelData->nSpatialDistributions);
1418
1419 /* set default solvers for algebraic loops */
1420 #if !defined(OMC_MINIMAL_RUNTIME)
1421 1 data->simulationInfo->nlsMethod = NLS_MIXED;
1422 #else
1423 ✗ data->simulationInfo->nlsMethod = NLS_HOMOTOPY;
1424 #endif
1425 1 data->simulationInfo->nlsLinearSolver = NLS_LS_DEFAULT;
1426 1 data->simulationInfo->lsMethod = LS_DEFAULT;
1427 1 data->simulationInfo->lssMethod = LSS_DEFAULT;
1428 1 data->simulationInfo->mixedMethod = MIXED_SEARCH;
1429 1 data->simulationInfo->newtonStrategy = NEWTON_DAMPED2;
1430 1 data->simulationInfo->nlsCsvInfomation = 0;
1431 1 data->simulationInfo->currentContext = CONTEXT_ALGEBRAIC;
1432 1 data->simulationInfo->jacobianEvals = data->modelData->nStates;
1433
1434 1 data->simulationInfo->zeroCrossings = (modelica_real*) calloc(data->modelData->nZeroCrossings, sizeof(modelica_real));
1435 1 data->simulationInfo->zeroCrossingsPre = (modelica_real*) calloc(data->modelData->nZeroCrossings, sizeof(modelica_real));
1436 1 data->simulationInfo->zeroCrossingsBackup = (modelica_real*) calloc(data->modelData->nZeroCrossings, sizeof(modelica_real));
1437 1 data->simulationInfo->relations = (modelica_boolean*) calloc(data->modelData->nRelations, sizeof(modelica_boolean));
1438 1 data->simulationInfo->relationsPre = (modelica_boolean*) calloc(data->modelData->nRelations, sizeof(modelica_boolean));
1439 1 data->simulationInfo->storedRelations = (modelica_boolean*) calloc(data->modelData->nRelations, sizeof(modelica_boolean));
1440 1 data->simulationInfo->mathEventsValuePre = (modelica_real*) malloc(data->modelData->nMathEvents*sizeof(modelica_real));
1441 1 data->simulationInfo->zeroCrossingIndex = (long*) malloc(data->modelData->nZeroCrossings*sizeof(long));
1442 /* initialize zeroCrossingsIndex with corresponding index is used by events lists */
1443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<data->modelData->nZeroCrossings; i++)
1444 ✗ data->simulationInfo->zeroCrossingIndex[i] = (long)i;
1445 1 data->simulationInfo->states_left = (modelica_real*) malloc(data->modelData->nStates * sizeof(modelica_real));
1446 1 data->simulationInfo->states_right = (modelica_real*) malloc(data->modelData->nStates * sizeof(modelica_real));
1447
1448 /* buffer for old values */
1449 1 data->simulationInfo->realVarsOld = (modelica_real*) calloc(data->modelData->nVariablesReal, sizeof(modelica_real));
1450 1 data->simulationInfo->integerVarsOld = (modelica_integer*) calloc(data->modelData->nVariablesInteger, sizeof(modelica_integer));
1451 1 data->simulationInfo->booleanVarsOld = (modelica_boolean*) calloc(data->modelData->nVariablesBoolean, sizeof(modelica_boolean));
1452 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1453 1 data->simulationInfo->stringVarsOld = (modelica_string*) omc_alloc_interface.malloc_uncollectable(data->modelData->nVariablesString * sizeof(modelica_string));
1454 #endif
1455 /* buffer for all variable pre values */
1456 1 data->simulationInfo->realVarsPre = (modelica_real*) calloc(data->modelData->nVariablesReal, sizeof(modelica_real));
1457 1 data->simulationInfo->integerVarsPre = (modelica_integer*) calloc(data->modelData->nVariablesInteger, sizeof(modelica_integer));
1458 1 data->simulationInfo->booleanVarsPre = (modelica_boolean*) calloc(data->modelData->nVariablesBoolean, sizeof(modelica_boolean));
1459 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1460 1 data->simulationInfo->stringVarsPre = (modelica_string*) omc_alloc_interface.malloc_uncollectable(data->modelData->nVariablesString * sizeof(modelica_string));
1461 #endif
1462 /* buffer for all parameters values */
1463 1 data->simulationInfo->realParameter = (modelica_real*) calloc(data->modelData->nParametersReal, sizeof(modelica_real));
1464 1 data->simulationInfo->integerParameter = (modelica_integer*) calloc(data->modelData->nParametersInteger, sizeof(modelica_integer));
1465 1 data->simulationInfo->booleanParameter = (modelica_boolean*) calloc(data->modelData->nParametersBoolean, sizeof(modelica_boolean));
1466 1 data->simulationInfo->stringParameter = (modelica_string*) omc_alloc_interface.malloc_uncollectable(data->modelData->nParametersString * sizeof(modelica_string));
1467 /* buffer for inputs and outputs values */
1468 1 data->simulationInfo->inputVars = (modelica_real*) calloc(data->modelData->nInputVars, sizeof(modelica_real));
1469 1 data->simulationInfo->outputVars = (modelica_real*) calloc(data->modelData->nOutputVars, sizeof(modelica_real));
1470 1 data->simulationInfo->setcVars = (modelica_real*) calloc(data->modelData->nSetcVars, sizeof(modelica_real));
1471 1 data->simulationInfo->datainputVars = (modelica_real*) calloc(data->modelData->ndataReconVars, sizeof(modelica_real));
1472 1 data->simulationInfo->setbVars = (modelica_real*) calloc(data->modelData->nSetbVars, sizeof(modelica_real));
1473
1474 #if !defined(OMC_NUM_MIXED_SYSTEMS) || OMC_NUM_MIXED_SYSTEMS>0
1475 /* buffer for mixed systems */
1476 #if !defined(OMC_NUM_MIXED_SYSTEMS)
1477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nMixedSystems)
1478 #endif
1479 {
1480 ✗ data->simulationInfo->mixedSystemData = (MIXED_SYSTEM_DATA*) omc_alloc_interface.malloc_uncollectable(data->modelData->nMixedSystems*sizeof(MIXED_SYSTEM_DATA));
1481 ✗ data->callback->initialMixedSystem(data->modelData->nMixedSystems, data->simulationInfo->mixedSystemData);
1482 }
1483 #endif
1484
1485 #if !defined(OMC_NUM_LINEAR_SYSTEMS) || OMC_NUM_LINEAR_SYSTEMS>0
1486 /* buffer for linear systems */
1487 #if !defined(OMC_NUM_LINEAR_SYSTEMS)
1488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nLinearSystems)
1489 #endif
1490 {
1491 ✗ data->simulationInfo->linearSystemData = (LINEAR_SYSTEM_DATA*) omc_alloc_interface.malloc_uncollectable(data->modelData->nLinearSystems*sizeof(LINEAR_SYSTEM_DATA));
1492 ✗ data->callback->initialLinearSystem(data->modelData->nLinearSystems, data->simulationInfo->linearSystemData);
1493 }
1494 #endif
1495
1496 #if !defined(OMC_NUM_NONLINEAR_SYSTEMS) || OMC_NUM_NONLINEAR_SYSTEMS>0
1497 /* buffer for non-linear systems */
1498 #if !defined(OMC_NUM_NONLINEAR_SYSTEMS)
1499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nNonLinearSystems)
1500 #endif
1501 {
1502 ✗ data->simulationInfo->nonlinearSystemData = (NONLINEAR_SYSTEM_DATA*) omc_alloc_interface.malloc_uncollectable(data->modelData->nNonLinearSystems*sizeof(NONLINEAR_SYSTEM_DATA));
1503 ✗ data->callback->initialNonLinearSystem(data->modelData->nNonLinearSystems, data->simulationInfo->nonlinearSystemData);
1504 }
1505 #endif
1506
1507 #if !defined(OMC_NO_STATESELECTION)
1508 /* buffer for state sets */
1509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nStateSets) {
1510 ✗ data->simulationInfo->stateSetData = (STATE_SET_DATA*) omc_alloc_interface.malloc_uncollectable(data->modelData->nStateSets*sizeof(STATE_SET_DATA));
1511 ✗ data->callback->initializeStateSets(data->modelData->nStateSets, data->simulationInfo->stateSetData, data);
1512 }
1513 #endif
1514
1515 /* buffer for daeMode */
1516 1 data->simulationInfo->daeModeData = (DAEMODE_DATA*) omc_alloc_interface.malloc_uncollectable(sizeof(DAEMODE_DATA));
1517 1 data->callback->initializeDAEmodeData(data, data->simulationInfo->daeModeData);
1518
1519 /* buffer for inline Data */
1520 1 data->simulationInfo->inlineData = (INLINE_DATA*) omc_alloc_interface.malloc_uncollectable(sizeof(INLINE_DATA));
1521 1 data->simulationInfo->inlineData->algVars = (modelica_real*) calloc(data->modelData->nStates, sizeof(modelica_real));
1522 1 data->simulationInfo->inlineData->algOldVars = (modelica_real*) calloc(data->modelData->nStates, sizeof(modelica_real));
1523
1524 /* buffer for analytical jacobians */
1525 1 data->simulationInfo->analyticJacobians = (JACOBIAN*) omc_alloc_interface.malloc_uncollectable(data->modelData->nJacobians*sizeof(JACOBIAN));
1526 /* zero out, so that `availability == JACOBIAN_UNKNOWN` marks an uninitialized Jacobian */
1527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 memset(data->simulationInfo->analyticJacobians, 0, data->modelData->nJacobians*sizeof(JACOBIAN));
1528 1 data->simulationInfo->odeJacobian = NULL;
1529
1530 1 data->modelData->modelDataXml.functionNames = NULL;
1531 1 data->modelData->modelDataXml.equationInfo = NULL;
1532
1533 /* buffer for external objects */
1534 data->simulationInfo->extObjs = NULL;
1535 1 data->simulationInfo->extObjs = (void**) calloc(data->modelData->nExtObjs, sizeof(void*));
1536
1537
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, 0 == data->modelData->nExtObjs || 0 != data->simulationInfo->extObjs, "error allocating external objects");
1538
1539 #if !defined(OMC_MINIMAL_LOGGING)
1540 /* initial chattering info */
1541 1 data->simulationInfo->chatteringInfo.numEventLimit = 1000;
1542 1 data->simulationInfo->chatteringInfo.lastTimes = (modelica_real*) calloc(data->simulationInfo->chatteringInfo.numEventLimit, sizeof(double));
1543 1 data->simulationInfo->chatteringInfo.currentIndex = 0;
1544 1 data->simulationInfo->chatteringInfo.stateEventsInARow = 0;
1545 1 data->simulationInfo->chatteringInfo.messageEmitted = 0;
1546 #endif
1547
1548 /* initial call statistics */
1549 1 data->simulationInfo->callStatistics.functionODE = 0;
1550 1 data->simulationInfo->callStatistics.functionEvalDAE = 0;
1551 1 data->simulationInfo->callStatistics.updateDiscreteSystem = 0;
1552 1 data->simulationInfo->callStatistics.functionZeroCrossingsEquations = 0;
1553 1 data->simulationInfo->callStatistics.functionZeroCrossings = 0;
1554 1 data->simulationInfo->callStatistics.functionAlgebraics = 0;
1555
1556 1 data->simulationInfo->lambda = 1.0;
1557
1558 /* initial build calls terminal, initial */
1559 1 data->simulationInfo->terminal = 0;
1560 1 data->simulationInfo->initial = 0;
1561 1 data->simulationInfo->sampleActivated = 0;
1562
1563 /* switches used to evaluate the system */
1564 1 data->simulationInfo->solveContinuous = 0;
1565 1 data->simulationInfo->noThrowDivZero = 0;
1566 1 data->simulationInfo->noThrowAsserts = 0;
1567 1 data->simulationInfo->needToReThrow = 0;
1568 1 data->simulationInfo->discreteStateChanged = 0;
1569 1 data->simulationInfo->discreteCall = 0;
1570
1571 /* initialize model error code */
1572 1 data->simulationInfo->simulationSuccess = 0;
1573
1574 /* initial delay */
1575 #if !defined(OMC_NDELAY_EXPRESSIONS) || OMC_NDELAY_EXPRESSIONS>0
1576 1 data->simulationInfo->delayStructure = (RINGBUFFER**)malloc(data->modelData->nDelayExpressions * sizeof(RINGBUFFER*));
1577
1/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 assertStreamPrint(threadData, 0 == data->modelData->nDelayExpressions || 0 != data->simulationInfo->delayStructure, "out of memory");
1578
1579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<data->modelData->nDelayExpressions; i++)
1580 {
1581 // TODO: Calculate how big ringbuffer should be for each delay expression
1582 // can be estimated by lower bound delayMax/stepSize
1583 ✗ data->simulationInfo->delayStructure[i] = allocRingBuffer(1024, sizeof(TIME_AND_VALUE));
1584 }
1585 #endif
1586
1587 #if !defined(OMC_NO_STATESELECTION)
1588 /* allocate memory for state selection */
1589 1 initializeStateSetJacobians(data, threadData);
1590 #endif
1591 1 }
1592
1593 /*! \fn deInitializeDataStruc
1594 *
1595 * function de-initialize DATA structure
1596 *
1597 * \param [ref] [data]
1598 *
1599 */
1600 1 void deInitializeDataStruc(DATA *data)
1601 {
1602 size_t i = 0;
1603
1604 /* prepare RingBuffer */
1605
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for(i=0; i<SIZERINGBUFFER; i++)
1606 {
1607 3 SIMULATION_DATA* tmpSimData = (SIMULATION_DATA*) data->localData[i];
1608 /* free buffer for all variable values */
1609 3 free(tmpSimData->realVars);
1610 3 free(tmpSimData->integerVars);
1611 3 free(tmpSimData->booleanVars);
1612 3 omc_string_slots_release(tmpSimData->stringVars, data->modelData->nVariablesString);
1613 3 omc_alloc_interface.free_uncollectable(tmpSimData->stringVars);
1614 }
1615 1 omc_alloc_interface.free_uncollectable(data->localData);
1616 1 freeRingBuffer(data->simulationData);
1617
1618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->callback->read_input_fmu) {
1619 /* FMU: `read_input_fmu` points the VAR_INFO strings at literals in the generated code,
1620 * but the arrays were still allocated by `allocModelDataVars` in `fmi2Instantiate`. */
1621 ✗ freeModelDataVarArrays(data->modelData);
1622 } else {
1623 1 freeModelDataVars(data->modelData);
1624 }
1625
1626 1 omc_alloc_interface.free_uncollectable(data->modelData->samplesInfo);
1627 1 free(data->simulationInfo->nextSampleTimes);
1628 1 free(data->simulationInfo->samples);
1629
1630 1 free(data->simulationInfo->baseClocks);
1631 1 freeList(data->simulationInfo->intvlTimers);
1632 1 data->simulationInfo->intvlTimers = NULL;
1633
1634 1 freeSpatialDistribution(data->simulationInfo->spatialDistributionData, data->modelData->nSpatialDistributions);
1635 1 free(data->simulationInfo->spatialDistributionData);
1636
1637 /* free simulationInfo arrays */
1638 1 free(data->simulationInfo->zeroCrossings);
1639 1 free(data->simulationInfo->zeroCrossingsPre);
1640 1 free(data->simulationInfo->zeroCrossingsBackup);
1641 1 free(data->simulationInfo->relations);
1642 1 free(data->simulationInfo->relationsPre);
1643 1 free(data->simulationInfo->storedRelations);
1644 1 free(data->simulationInfo->mathEventsValuePre);
1645 1 free(data->simulationInfo->zeroCrossingIndex);
1646 1 free(data->simulationInfo->states_left);
1647 1 free(data->simulationInfo->states_right);
1648
1649 1 freeArrayIndexMaps(data->simulationInfo);
1650 1 freeArrayReverseIndexMaps(data->simulationInfo);
1651
1652 /* free buffer for adaptive eval */
1653 1 freeEvalDAG(data->modelData->dag);
1654
1655 /* free buffer for old state variables */
1656 1 free(data->simulationInfo->realVarsOld);
1657 1 free(data->simulationInfo->integerVarsOld);
1658 1 free(data->simulationInfo->booleanVarsOld);
1659 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1660 1 omc_string_slots_release(data->simulationInfo->stringVarsOld, data->modelData->nVariablesString);
1661 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->stringVarsOld);
1662 #endif
1663
1664 /* free buffer for all variable pre values */
1665 1 free(data->simulationInfo->realVarsPre);
1666 1 free(data->simulationInfo->integerVarsPre);
1667 1 free(data->simulationInfo->booleanVarsPre);
1668 #if !defined(OMC_NVAR_STRING) || OMC_NVAR_STRING>0
1669 1 omc_string_slots_release(data->simulationInfo->stringVarsPre, data->modelData->nVariablesString);
1670 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->stringVarsPre);
1671 #endif
1672
1673 /* free buffer for all parameters values */
1674 1 free(data->simulationInfo->realParameter);
1675 1 free(data->simulationInfo->integerParameter);
1676 1 free(data->simulationInfo->booleanParameter);
1677 1 omc_string_slots_release(data->simulationInfo->stringParameter, data->modelData->nParametersString);
1678 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->stringParameter);
1679
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nMixedSystems) {
1681 /* free buffer of mixed systems */
1682 ✗ omc_alloc_interface.free_uncollectable(data->simulationInfo->mixedSystemData);
1683 }
1684
1685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nLinearSystems) {
1686 /* free buffer of linear systems */
1687 ✗ omc_alloc_interface.free_uncollectable(data->simulationInfo->linearSystemData);
1688 }
1689
1690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nNonLinearSystems)
1691 {
1692 /* free buffer of non-linear systems */
1693 ✗ omc_alloc_interface.free_uncollectable(data->simulationInfo->nonlinearSystemData);
1694 }
1695
1696 /* free buffer jacobians */
1697
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
6 for (i = 0; i < data->modelData->nJacobians; i++) {
1698 5 freeJacobian(&data->simulationInfo->analyticJacobians[i]);
1699 }
1700 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->analyticJacobians);
1701
1702 /* free buffer for state sets */
1703 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->daeModeData);
1704
1705 /* buffer for inline Data */
1706 1 free(data->simulationInfo->inlineData->algVars);
1707 1 free(data->simulationInfo->inlineData->algOldVars);
1708 1 omc_alloc_interface.free_uncollectable(data->simulationInfo->inlineData);
1709
1710 /* free inputs and output */
1711 1 free(data->simulationInfo->inputVars);
1712 1 free(data->simulationInfo->outputVars);
1713 1 free(data->simulationInfo->setcVars);
1714 1 free(data->simulationInfo->datainputVars);
1715 1 free(data->simulationInfo->setbVars);
1716
1717 /* free external objects buffer */
1718 1 free(data->simulationInfo->extObjs);
1719
1720 /* free chattering info */
1721 1 free(data->simulationInfo->chatteringInfo.lastTimes);
1722
1723 /* free delay structure */
1724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for(i=0; i<data->modelData->nDelayExpressions; i++)
1725 ✗ freeRingBuffer(data->simulationInfo->delayStructure[i]);
1726
1727 #if !defined(OMC_NDELAY_EXPRESSIONS) || OMC_NDELAY_EXPRESSIONS>0
1728 1 free(data->simulationInfo->delayStructure);
1729 #endif
1730
1731 #if !defined(OMC_NO_STATESELECTION)
1732 /* free stateset data */
1733 1 freeStateSetData(data);
1734 #endif
1735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (data->modelData->nStateSets) {
1736 /* free buffer for state sets */
1737 ✗ omc_alloc_interface.free_uncollectable(data->simulationInfo->stateSetData);
1738 }
1739
1740 /* free parameter sensitivities */
1741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (omc_flag[FLAG_IDAS])
1742 {
1743 ✗ free(data->simulationInfo->sensitivityParList);
1744 ✗ free(data->simulationInfo->sensitivityMatrix);
1745 }
1746
1747 /* Free model info xml data */
1748 1 modelInfoDeinit(&(data->modelData->modelDataXml));
1749
1750 /* GC_strdup'd from the init XML and the command line. */
1751 1 omc_rc_release((void*) data->simulationInfo->solverMethod);
1752 1 omc_rc_release((void*) data->simulationInfo->outputFormat);
1753 1 omc_rc_release((void*) data->simulationInfo->variableFilter);
1754 1 omc_rc_release((void*) data->simulationInfo->OPENMODELICAHOME);
1755 1 omc_rc_release((void*) data->modelData->resultFileName);
1756 1 data->simulationInfo->solverMethod = NULL;
1757 1 data->simulationInfo->outputFormat = NULL;
1758 1 data->simulationInfo->variableFilter = NULL;
1759 1 data->simulationInfo->OPENMODELICAHOME = NULL;
1760 1 data->modelData->resultFileName = NULL;
1761 1 }
1762
1763 /* relation functions used in zero crossing detection
1764 * Less is for case LESS and GREATEREQ
1765 * Greater is for case LESSEQ and GREATER
1766 * On the band edge the direction decides, so a band of width zero keeps the
1767 * current value.
1768 */
1769
1770 1 void setZCtol(double relativeTol)
1771 {
1772 /* lochel: force tolZC > 0 */
1773 1 tolZC = TOL_HYSTERESIS_ZEROCROSSINGS * fmax(relativeTol, MINIMAL_STEP_SIZE);
1774 1 infoStreamPrint(OMC_LOG_EVENTS_V, 0, "Set tolerance for zero-crossing hysteresis to: %e", tolZC);
1775 1 }
1776
1777 /* TODO: fix this */
1778 ✗ modelica_boolean LessZC(double a, double b, double a_nominal, double b_nominal, modelica_boolean direction)
1779 {
1780 ✗ double eps = tolZC * (fmax(fabs(a), fabs(b)) + fmax(fabs(a_nominal), fabs(b_nominal)));
1781 ✗ return direction ? (a - b <= eps) : (a - b < -eps);
1782 }
1783
1784 ✗ modelica_boolean LessEqZC(double a, double b, double a_nominal, double b_nominal, modelica_boolean direction)
1785 {
1786 ✗ return !GreaterZC(a, b, a_nominal, b_nominal, !direction);
1787 }
1788
1789 /* TODO: fix this */
1790 ✗ modelica_boolean GreaterZC(double a, double b, double a_nominal, double b_nominal, modelica_boolean direction)
1791 {
1792 ✗ double eps = tolZC * (fmax(fabs(a), fabs(b)) + fmax(fabs(a_nominal), fabs(b_nominal)));
1793 ✗ return direction ? (a - b >= -eps) : (a - b > eps);
1794 }
1795
1796 ✗ modelica_boolean GreaterEqZC(double a, double b, double a_nominal, double b_nominal, modelica_boolean direction)
1797 {
1798 ✗ return !LessZC(a, b, a_nominal, b_nominal, !direction);
1799 }
1800
1801
1802 /*! \fn _event_integer
1803 *
1804 * \param [in] [x]
1805 * \param [in] [index]
1806 * \param [ref] [data]
1807 *
1808 * Returns the largest integer not greater than x.
1809 */
1810 ✗ modelica_integer _event_integer(modelica_real x, modelica_integer index, DATA *data)
1811 {
1812 modelica_real value;
1813 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1814 {
1815 ✗ data->simulationInfo->mathEventsValuePre[index] = (modelica_integer)floor(x);
1816 }
1817
1818 ✗ value = data->simulationInfo->mathEventsValuePre[index];
1819
1820 ✗ return value;
1821 }
1822
1823 /*! \fn _event_floor
1824 *
1825 * \param [in] [x]
1826 * \param [in] [index]
1827 * \param [ref] [data]
1828 *
1829 * Returns the largest integer not greater than x.
1830 * Result and argument shall have type Real.
1831 */
1832 ✗ modelica_real _event_floor(modelica_real x, modelica_integer index, DATA *data)
1833 {
1834 modelica_real value;
1835 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1836 {
1837 ✗ data->simulationInfo->mathEventsValuePre[index] = x;
1838 }
1839
1840 ✗ value = data->simulationInfo->mathEventsValuePre[index];
1841
1842 ✗ return (modelica_real)floor(value);
1843 }
1844
1845 /*! \fn _event_ceil
1846 *
1847 * \param [in] [x]
1848 * \param [in] [index]
1849 * \param [ref] [data]
1850 *
1851 * Returns the smallest integer not less than x.
1852 * Result and argument shall have type Real.
1853 */
1854 ✗ modelica_real _event_ceil(modelica_real x, modelica_integer index, DATA *data)
1855 {
1856 modelica_real value;
1857 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1858 {
1859 ✗ data->simulationInfo->mathEventsValuePre[index] = x;
1860 }
1861
1862 ✗ value = data->simulationInfo->mathEventsValuePre[index];
1863
1864 ✗ return (modelica_real)ceil(value);
1865 }
1866
1867 /*! \fn _event_mod_integer
1868 *
1869 * \param [in] [x1]
1870 * \param [in] [x2]
1871 * \param [in] [index]
1872 * \param [ref] [data]
1873 */
1874 ✗ modelica_integer _event_mod_integer(modelica_integer x1, modelica_integer x2, modelica_integer index, DATA *data, threadData_t *threadData)
1875 {
1876 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1877 {
1878 ✗ data->simulationInfo->mathEventsValuePre[index] = (modelica_real)x1;
1879 ✗ data->simulationInfo->mathEventsValuePre[index+1] = (modelica_real)x2;
1880 }
1881 ✗ modelica_integer tmp = x1 % x2;
1882 ✗ return ((x2 > 0 && tmp < 0) || (x2 < 0 && tmp > 0)) ? (tmp + x2) : tmp;
1883 }
1884
1885 /*! \fn _event_mod_real
1886 *
1887 * \param [in] [x1]
1888 * \param [in] [x2]
1889 * \param [in] [index]
1890 * \param [ref] [data]
1891 */
1892 ✗ modelica_real _event_mod_real(modelica_real x1, modelica_real x2, modelica_integer index, DATA *data, threadData_t *threadData)
1893 {
1894 modelica_real value;
1895
1896 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1897 {
1898 ✗ data->simulationInfo->mathEventsValuePre[index] = x1;
1899 ✗ data->simulationInfo->mathEventsValuePre[index+1] = x2;
1900 }
1901
1902 ✗ value = _event_floor(x1 / x2, index+2, data);
1903
1904 ✗ return x1 - value * x2;
1905 }
1906
1907 /*! \fn _event_div_integer
1908 *
1909 * \param [in] [x1]
1910 * \param [in] [x2]
1911 * \param [in] [index]
1912 * \param [ref] [data]
1913 *
1914 * Returns the algebraic quotient x/y with any fractional part discarded.
1915 */
1916 ✗ modelica_integer _event_div_integer(modelica_integer x1, modelica_integer x2, modelica_integer index, DATA *data, threadData_t *threadData)
1917 {
1918 modelica_integer value1, value2;
1919 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1920 {
1921 ✗ data->simulationInfo->mathEventsValuePre[index] = (modelica_real)x1;
1922 ✗ data->simulationInfo->mathEventsValuePre[index+1] = (modelica_real)x2;
1923 }
1924
1925 ✗ value1 = (modelica_integer)data->simulationInfo->mathEventsValuePre[index];
1926 ✗ value2 = (modelica_integer)data->simulationInfo->mathEventsValuePre[index+1];
1927
1928 ✗ assertStreamPrint(threadData, value2 != 0, "event_div_integer failed at time %f because x2 is zero!", data->localData[0]->timeValue);
1929 ✗ return modelica_div_integer(value1, value2).quot;
1930 }
1931
1932 /*! \fn _event_div_real
1933 *
1934 * \param [in] [x1]
1935 * \param [in] [x2]
1936 * \param [in] [index]
1937 * \param [ref] [data]
1938 *
1939 * Returns the algebraic quotient x/y with any fractional part discarded.
1940 */
1941 ✗ modelica_real _event_div_real(modelica_real x1, modelica_real x2, modelica_integer index, DATA *data, threadData_t *threadData)
1942 {
1943 modelica_real value1, value2;
1944 ✗ if(data->simulationInfo->discreteCall && !data->simulationInfo->solveContinuous)
1945 {
1946 ✗ data->simulationInfo->mathEventsValuePre[index] = x1;
1947 ✗ data->simulationInfo->mathEventsValuePre[index+1] = x2;
1948 }
1949
1950 ✗ value1 = data->simulationInfo->mathEventsValuePre[index];
1951 ✗ value2 = data->simulationInfo->mathEventsValuePre[index+1];
1952
1953 #if defined(_MSC_VER)
1954 {
1955 modelica_real rtmp = value1/value2;
1956 modelica_integer tmp = (modelica_integer)(rtmp);
1957 return (modelica_real)tmp;
1958 }
1959 #else
1960 ✗ return trunc(value1/value2);
1961 #endif
1962 }
1963
1964
1965 /**
1966 * @brief Allocate memory for syncTimerList elements.
1967 *
1968 * @param data Unused.
1969 * @return void* Allocated memory for LIST_NODE data.
1970 */
1971 ✗ void* syncTimerListAlloc(const void* data) {
1972 ✗ void* newElem = malloc(sizeof(SYNC_TIMER));
1973 ✗ assertStreamPrint(NULL, newElem != NULL, "syncTimerListAlloc: Out of memory");
1974 ✗ return newElem;
1975 }
1976
1977 /**
1978 * @brief Free memory allocated with syncTimerListAlloc.
1979 *
1980 * @param data Void pointer, representing SYNC_TIMER.
1981 */
1982 ✗ void syncTimerListFree(void* data) {
1983 ✗ free(data);
1984 ✗ }
1985
1986 /**
1987 * @brief Copy data of syncTimerList elements.
1988 *
1989 * @param dest Void pointer of destination data, representing SYNC_TIMER.
1990 * @param src Void pointer of source data, representing SYNC_TIMER.
1991 */
1992 ✗ void syncTimerListCopy(void* dest, const void* src) {
1993 memcpy(dest, src, sizeof(SYNC_TIMER));
1994 ✗ }
1995
1996
1997 int measure_time_flag=0;
1998