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 |