Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 29.3% 17 / 0 / 58
Functions: 100.0% 1 / 0 / 1
Branches: 21.7% 13 / 0 / 60

OMCompiler/SimulationRuntime/c/simulation/solver/discrete_changes.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 #include "discrete_changes.h"
29 #include "../arrayIndex.h"
30
31 /**
32 * @brief Check for changes in discrete variables since the previous step.
33 *
34 * This routine compares the current values of discrete variables with their
35 * previous stored values. Variables whose names begin with "$cse" (common
36 * subexpression temporaries) are ignored.
37 *
38 * When verbose event logging (`OMC_LOG_EVENTS_V`) is enabled the function will
39 * print an entry for each changed variable.
40 *
41 * @param data Pointer to simulation `DATA` structure containing
42 * model metadata and current/previous variable values.
43 * @param threadData Thread-local data, unused by this function
44 * @return modelica_boolean Returns `TRUE` if any discrete variable changed,
45 * otherwise `FALSE`.
46 */
47 2 modelica_boolean checkForDiscreteChanges(DATA *data, threadData_t *threadData)
48 {
49 2 MODEL_DATA *modelData = data->modelData;
50 2 SIMULATION_INFO *simulationInfo = data->simulationInfo;
51
52 /* No discrete variables */
53
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (modelData->nDiscreteRealArray == 0 &&
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 modelData->nVariablesIntegerArray == 0 &&
55 ✗ modelData->nVariablesBooleanArray == 0 &&
56 ✗ modelData->nVariablesStringArray == 0)
57 {
58 return FALSE;
59 }
60
61 modelica_boolean needToIterate = FALSE;
62 char* index_buffer;
63 size_t buffer_size = 2000;
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
65 {
66 ✗ infoStreamPrint(OMC_LOG_EVENTS_V, 1, "check for discrete changes at time=%.12g",
67 ✗ data->localData[0]->timeValue);
68 ✗ index_buffer = (char*) malloc(buffer_size*sizeof(char));
69 }
70
71 /* Real discrete variables */
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (long arrayIdx = modelData->nVariablesRealArray - modelData->nDiscreteRealArray; arrayIdx < modelData->nVariablesRealArray; arrayIdx++)
73 {
74 ✗ if (strncmp(modelData->realVarsData[arrayIdx].info.name, "$cse", 4))
75 {
76 ✗ for (size_t i = 0; i < modelData->realVarsData[arrayIdx].dimension.scalar_length; i++)
77 {
78 ✗ size_t scalarIdx = simulationInfo->realVarsIndex[arrayIdx] + i;
79 ✗ modelica_real v1 = simulationInfo->realVarsPre[scalarIdx];
80 ✗ modelica_real v2 = data->localData[0]->realVars[scalarIdx];
81 ✗ if (v1 != v2)
82 {
83 needToIterate = TRUE;
84 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
85 {
86 ✗ printMultiDimArrayIndex(&modelData->realVarsData[arrayIdx].dimension, scalarIdx, index_buffer, buffer_size);
87 ✗ infoStreamPrint(OMC_LOG_EVENTS_V, 0, "discrete var changed: %s%s from %g to %g",
88 ✗ modelData->realVarsData[arrayIdx].info.name, index_buffer, v1, v2);
89 }
90 else
91 {
92 return needToIterate;
93 }
94 }
95 }
96 }
97 }
98
99
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (long arrayIdx = 0; arrayIdx < modelData->nVariablesIntegerArray; arrayIdx++)
100 {
101
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (strncmp(modelData->integerVarsData[arrayIdx].info.name, "$cse", 4))
102 {
103
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (size_t i = 0; i < modelData->integerVarsData[arrayIdx].dimension.scalar_length; i++)
104 {
105 4 size_t scalarIdx = simulationInfo->integerVarsIndex[arrayIdx] + i;
106 4 modelica_integer v1 = simulationInfo->integerVarsPre[scalarIdx];
107 4 modelica_integer v2 = data->localData[0]->integerVars[scalarIdx];
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (v1 != v2)
109 {
110 needToIterate = TRUE;
111 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
112 {
113 ✗ printMultiDimArrayIndex(&modelData->integerVarsData[arrayIdx].dimension, scalarIdx, index_buffer, buffer_size);
114 ✗ infoStreamPrint(OMC_LOG_EVENTS_V, 0, "discrete var changed: %s%s from %ld to %ld",
115 ✗ modelData->integerVarsData[arrayIdx].info.name, index_buffer, (long)v1, (long)v2);
116 }
117 else
118 {
119 return needToIterate;
120 }
121 }
122 }
123 }
124 }
125
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (long arrayIdx = 0; arrayIdx < modelData->nVariablesBooleanArray; arrayIdx++)
127 {
128 ✗ if (strncmp(modelData->booleanVarsData[arrayIdx].info.name, "$cse", 4))
129 {
130 ✗ for (size_t i = 0; i < modelData->booleanVarsData[arrayIdx].dimension.scalar_length; i++)
131 {
132 ✗ size_t scalarIdx = simulationInfo->booleanVarsIndex[arrayIdx] + i;
133 ✗ modelica_boolean v1 = simulationInfo->booleanVarsPre[scalarIdx];
134 ✗ modelica_boolean v2 = data->localData[0]->booleanVars[scalarIdx];
135 ✗ if (v1 != v2)
136 {
137 needToIterate = TRUE;
138 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
139 {
140 ✗ printMultiDimArrayIndex(&modelData->booleanVarsData[arrayIdx].dimension, scalarIdx, index_buffer, buffer_size);
141 ✗ infoStreamPrint(OMC_LOG_EVENTS_V, 0, "discrete var changed: %s%s from %s to %s",
142 ✗ modelData->booleanVarsData[arrayIdx].info.name, index_buffer, v1 ? "true" : "false", v2 ? "true" : "false");
143 }
144 else
145 {
146 return needToIterate;
147 }
148 }
149 }
150 }
151 }
152
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (long arrayIdx = 0; arrayIdx < modelData->nVariablesStringArray; arrayIdx++)
154 {
155 ✗ if (strncmp(modelData->stringVarsData[arrayIdx].info.name, "$cse", 4))
156 {
157 ✗ for (size_t i = 0; i < modelData->stringVarsData[arrayIdx].dimension.scalar_length; i++)
158 {
159 ✗ size_t scalarIdx = simulationInfo->stringVarsIndex[arrayIdx] + i;
160 ✗ modelica_string v1 = simulationInfo->stringVarsPre[scalarIdx];
161 ✗ modelica_string v2 = data->localData[0]->stringVars[scalarIdx];
162 ✗ if (!stringEqual(v1, v2))
163 {
164 needToIterate = TRUE;
165 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
166 {
167 ✗ printMultiDimArrayIndex(&modelData->stringVarsData[arrayIdx].dimension, scalarIdx, index_buffer, buffer_size);
168 ✗ infoStreamPrint(OMC_LOG_EVENTS_V, 0, "discrete var changed: %s from %s to %s",
169 ✗ modelData->stringVarsData[arrayIdx].info.name, omc_string_data(v1), omc_string_data(v2));
170 }
171 else
172 {
173 return needToIterate;
174 }
175 }
176 }
177 }
178 }
179
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (OMC_ACTIVE_STREAM(OMC_LOG_EVENTS_V))
181 {
182 ✗ messageClose(OMC_LOG_EVENTS_V);
183 ✗ free(index_buffer);
184 }
185
186 return needToIterate;
187 }
188