Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 50.2% 141 / 0 / 281
Functions: 100.0% 9 / 0 / 9
Branches: 29.4% 99 / 0 / 337

OMCompiler/SimulationRuntime/c/simulation/results/simulation_result_rust.cpp
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 "simulation_result_rust.h"
29
30 #include "omc_result.h"
31 #include "util/omc_error.h"
32 #include "util/rtclock.h"
33 #include "simulation/options.h"
34
35 #include <cstring>
36 #include <string>
37 #include <vector>
38
39 extern "C" {
40
41 /* A kept array variable: where its scalars start in the runtime's value array
42 * and how many there are. Rows are filled from these in signal order. */
43 struct block { size_t start; size_t len; };
44
45 struct rust_result_data
46 {
47 omc_result_writer *writer;
48 std::vector<std::string> strings; /* owns every name/description/unit the signals point at */
49 std::vector<omc_result_signal> signals;
50 std::vector<int> columnTypes;
51 std::vector<block> reals, ints, bools, strs;
52 size_t nSensitivities;
53 std::vector<double> row;
54 std::vector<double> params;
55 };
56
57 7 static std::string arrayName(const char *name, const DIMENSION_INFO *dimension, size_t linear, modelica_boolean isStateDerivative)
58 {
59 7 std::string out = name;
60
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
7 if (dimension == NULL || dimension->numberOfDimensions == 0) {
61 return out;
62 }
63
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (isStateDerivative) {
64 out.pop_back(); /* the ")" of der(x): the subscripts go inside it */
65 }
66 size_t rem = linear;
67
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (size_t k = 0; k < dimension->numberOfDimensions; k++) {
68 size_t stride = 1;
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (size_t j = k + 1; j < dimension->numberOfDimensions; j++) {
70 ✗ stride *= (size_t)dimension->dimensions[j].start;
71 }
72
4/10
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
12 out += (k == 0 ? "[" : ",") + std::to_string(rem / stride + 1);
73 6 rem = rem % stride;
74 }
75 out += "]";
76
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (isStateDerivative) {
77 out += ")";
78 }
79 return out;
80 }
81
82 static const char *mmcString(const modelica_string *s)
83 {
84
1/10
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2 if (s == NULL || *s == NULL) {
85 return "";
86 }
87 const char *str = omc_string_data(*s);
88 4 return str ? str : "";
89 }
90
91 /* A String value travels in the row (or params) as its interned id. */
92 static double internString(modelica_string s)
93 {
94 ✗ return omc_result_intern(mmcString(&s));
95 }
96
97 /* Adds the signals of one (array) variable: scalar_length of them. `column` is
98 * the row column of the first scalar for a column signal, -1 for the others. */
99 4 static void addSignals(rust_result_data *d, const char *name, const char *comment, const char *unit, const char *displayUnit,
100 int type, int kind, long column, int negate, int unvarying,
101 const DIMENSION_INFO *dimension, modelica_boolean isStateDerivative,
102 modelica_boolean relativeQuantity = FALSE)
103 {
104
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 size_t n = dimension ? dimension->scalar_length : 1;
105
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 for (size_t i = 0; i < n; i++) {
106 /* Pointers into `strings` are taken only after every push_back (open()). */
107 7 d->strings.push_back(arrayName(name, dimension, i, isStateDerivative));
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 d->strings.push_back(comment ? comment : "");
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 d->strings.push_back(unit ? unit : "");
110
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 time.
14 d->strings.push_back(displayUnit ? displayUnit : "");
111 omc_result_signal s;
112 memset(&s, 0, sizeof(s));
113 7 s.type = type;
114 7 s.discrete = type != OMC_RESULT_TYPE_REAL;
115 7 s.kind = kind;
116
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 time.
7 s.column = kind == OMC_RESULT_KIND_COLUMN ? (unsigned)(column + i) : 0;
117 7 s.negate = negate;
118 7 s.unvarying = unvarying;
119 7 s.relative_quantity = relativeQuantity;
120 7 d->signals.push_back(s);
121 }
122 4 }
123
124 1 void rust_result_init(simulation_result *self, DATA *data, threadData_t *threadData)
125 {
126 1 const MODEL_DATA *mData = data->modelData;
127 1 const SIMULATION_INFO *sInfo = data->simulationInfo;
128 1 rust_result_data *d = new rust_result_data();
129 d->writer = NULL;
130 d->nSensitivities = 0;
131 1 self->storage = d;
132
133 /* Row layout: time, $cpuTime, $solverSteps, kept reals, sensitivities, kept
134 * integers, kept booleans, kept strings (as interned ids). */
135 long column = 0;
136 1 addSignals(d, "time", "Simulation time", "s", "", OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_TIME, column++, 0, 0, NULL, FALSE);
137 1 d->columnTypes.push_back(OMC_RESULT_TYPE_REAL);
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (self->cpuTime) {
139 ✗ addSignals(d, "$cpuTime", "cpu time", "s", "", OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_COLUMN, column++, 0, 0, NULL, FALSE);
140 ✗ d->columnTypes.push_back(OMC_RESULT_TYPE_REAL);
141 }
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (omc_flag[FLAG_SOLVER_STEPS]) {
143 ✗ addSignals(d, "$solverSteps", "number of steps taken by the integrator", "", "", OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_COLUMN, column++, 0, 0, NULL, FALSE);
144 ✗ d->columnTypes.push_back(OMC_RESULT_TYPE_REAL);
145 }
146 /* Row column of each kept scalar variable, by its index in the value arrays;
147 * the aliases look their targets up here. */
148
2/6
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
1 std::vector<long> realColumn(mData->nVariablesReal, -1), intColumn(mData->nVariablesInteger, -1), boolColumn(mData->nVariablesBoolean, -1);
149 /* The discrete Reals are the tail of realVarsData. */
150 1 const long firstDiscreteReal = mData->nVariablesRealArray - mData->nDiscreteRealArray;
151 auto markDiscrete = [d](size_t from) {
152 ✗ for (size_t j = from; j < d->signals.size(); j++) d->signals[j].discrete = 1;
153 };
154
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (int i = 0; i < mData->nVariablesRealArray; i++) {
155 2 const STATIC_REAL_DATA *v = &mData->realVarsData[i];
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (v->filterOutput) continue;
157
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
2 modelica_boolean isStateDerivative = mData->nStatesArray <= i && i < 2 * mData->nStatesArray;
158 2 size_t start = sInfo->realVarsIndex[i];
159
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (size_t k = 0; k < v->dimension.scalar_length; k++) {
160
1/1
✓ Branch 1 taken 4 times.
4 realColumn[start + k] = column + k;
161
1/1
✓ Branch 1 taken 4 times.
4 d->columnTypes.push_back(OMC_RESULT_TYPE_REAL);
162 }
163 size_t first = d->signals.size();
164
1/1
✓ Branch 1 taken 2 times.
2 addSignals(d, v->info.name, v->info.comment, mmcString(&v->attribute.unit), mmcString(&v->attribute.displayUnit),
165 2 OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_COLUMN, column, 0, v->time_unvarying, &v->dimension, isStateDerivative,
166
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 v->attribute.relativeQuantity);
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (i >= firstDiscreteReal) markDiscrete(first);
168
1/1
✓ Branch 1 taken 2 times.
2 d->reals.push_back({start, v->dimension.scalar_length});
169 2 column += v->dimension.scalar_length;
170 }
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (omc_flag[FLAG_IDAS]) {
172 ✗ for (int i = mData->nSensitivityParamVars; i < mData->nSensitivityVars; i++) {
173 ✗ addSignals(d, mData->realSensitivityData[i].info.name, mData->realSensitivityData[i].info.comment, "", "",
174 OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_COLUMN, column++, 0, 0, NULL, FALSE);
175 ✗ d->columnTypes.push_back(OMC_RESULT_TYPE_REAL);
176 ✗ d->nSensitivities++;
177 }
178 }
179
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (int i = 0; i < mData->nVariablesIntegerArray; i++) {
180 1 const STATIC_INTEGER_DATA *v = &mData->integerVarsData[i];
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (v->filterOutput) continue;
182 1 size_t start = sInfo->integerVarsIndex[i];
183
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (size_t k = 0; k < v->dimension.scalar_length; k++) {
184
1/1
✓ Branch 1 taken 2 times.
2 intColumn[start + k] = column + k;
185
1/1
✓ Branch 1 taken 2 times.
2 d->columnTypes.push_back(OMC_RESULT_TYPE_INTEGER);
186 }
187
1/1
✓ Branch 1 taken 1 time.
1 addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_INTEGER, OMC_RESULT_KIND_COLUMN, column, 0, v->time_unvarying, &v->dimension, FALSE);
188
1/1
✓ Branch 1 taken 1 time.
1 d->ints.push_back({start, v->dimension.scalar_length});
189 1 column += v->dimension.scalar_length;
190 }
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nVariablesBooleanArray; i++) {
192 ✗ const STATIC_BOOLEAN_DATA *v = &mData->booleanVarsData[i];
193 ✗ if (v->filterOutput) continue;
194 ✗ size_t start = sInfo->booleanVarsIndex[i];
195 ✗ for (size_t k = 0; k < v->dimension.scalar_length; k++) {
196 ✗ boolColumn[start + k] = column + k;
197 ✗ d->columnTypes.push_back(OMC_RESULT_TYPE_BOOLEAN);
198 }
199 ✗ addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_BOOLEAN, OMC_RESULT_KIND_COLUMN, column, 0, v->time_unvarying, &v->dimension, FALSE);
200 ✗ d->bools.push_back({start, v->dimension.scalar_length});
201 ✗ column += v->dimension.scalar_length;
202 }
203
1/3
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 std::vector<long> stringColumn(mData->nVariablesString, -1);
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nVariablesStringArray; i++) {
205 ✗ const STATIC_STRING_DATA *v = &mData->stringVarsData[i];
206 ✗ if (v->filterOutput) continue;
207 ✗ size_t start = sInfo->stringVarsIndex[i];
208 ✗ for (size_t k = 0; k < v->dimension.scalar_length; k++) {
209 ✗ stringColumn[start + k] = column + k;
210 ✗ d->columnTypes.push_back(OMC_RESULT_TYPE_STRING);
211 }
212 ✗ addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_STRING, OMC_RESULT_KIND_COLUMN, column, 0, v->time_unvarying, &v->dimension, FALSE);
213 ✗ d->strs.push_back({start, v->dimension.scalar_length});
214 ✗ column += v->dimension.scalar_length;
215 }
216
1/3
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 d->row.assign(column, 0.0);
217
218 /* Parameter values are read when the file is opened, after initialization. */
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersRealArray; i++) {
220 ✗ const STATIC_REAL_DATA *v = &mData->realParameterData[i];
221 ✗ if (v->filterOutput) continue;
222 ✗ addSignals(d, v->info.name, v->info.comment, mmcString(&v->attribute.unit), mmcString(&v->attribute.displayUnit),
223 OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_PARAMETER, -1, 0, 0, &v->dimension, FALSE,
224 ✗ v->attribute.relativeQuantity);
225 }
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersIntegerArray; i++) {
227 ✗ const STATIC_INTEGER_DATA *v = &mData->integerParameterData[i];
228 ✗ if (v->filterOutput) continue;
229 ✗ addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_INTEGER, OMC_RESULT_KIND_PARAMETER, -1, 0, 0, &v->dimension, FALSE);
230 }
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersBooleanArray; i++) {
232 ✗ const STATIC_BOOLEAN_DATA *v = &mData->booleanParameterData[i];
233 ✗ if (v->filterOutput) continue;
234 ✗ addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_BOOLEAN, OMC_RESULT_KIND_PARAMETER, -1, 0, 0, &v->dimension, FALSE);
235 }
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersStringArray; i++) {
237 ✗ const STATIC_STRING_DATA *v = &mData->stringParameterData[i];
238 ✗ if (v->filterOutput) continue;
239 ✗ addSignals(d, v->info.name, v->info.comment, "", "", OMC_RESULT_TYPE_STRING, OMC_RESULT_KIND_PARAMETER, -1, 0, 0, &v->dimension, FALSE);
240 }
241
242 /* Aliases share their target's column (or repeat its parameter value). */
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasRealArray; i++) {
244 ✗ const DATA_REAL_ALIAS *a = &mData->realAlias[i];
245 ✗ if (a->filterOutput) continue;
246 ✗ int negate = a->negate ? OMC_RESULT_NEGATE_ARITHMETIC : OMC_RESULT_NEGATE_NONE;
247 ✗ switch (a->aliasType) {
248 ✗ case ALIAS_TYPE_VARIABLE: {
249 ✗ const STATIC_REAL_DATA *v = &mData->realVarsData[a->nameID];
250 ✗ modelica_boolean isStateDerivative = mData->nStatesArray <= a->nameID && a->nameID < 2 * mData->nStatesArray;
251 size_t first = d->signals.size();
252 ✗ addSignals(d, a->info.name, a->info.comment, mmcString(&a->unit), mmcString(&a->displayUnit),
253 ✗ OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_COLUMN, realColumn[sInfo->realVarsIndex[a->nameID]], negate, v->time_unvarying, &v->dimension, isStateDerivative,
254 ✗ a->relativeQuantity);
255 ✗ if (a->nameID >= firstDiscreteReal) markDiscrete(first);
256 break;
257 }
258 ✗ case ALIAS_TYPE_PARAMETER: {
259 ✗ const STATIC_REAL_DATA *v = &mData->realParameterData[a->nameID];
260 ✗ addSignals(d, a->info.name, a->info.comment, mmcString(&a->unit), mmcString(&a->displayUnit),
261 OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_PARAMETER, -1, negate, 0, &v->dimension, FALSE,
262 ✗ a->relativeQuantity);
263 break;
264 }
265 ✗ case ALIAS_TYPE_TIME: {
266 const char *unit = mmcString(&a->unit);
267 ✗ addSignals(d, a->info.name, a->info.comment, unit[0] ? unit : "s", mmcString(&a->displayUnit),
268 OMC_RESULT_TYPE_REAL, OMC_RESULT_KIND_TIME, 0, negate, 0, NULL, FALSE,
269 ✗ a->relativeQuantity);
270 break;
271 }
272 ✗ default:
273 ✗ throwStreamPrint(threadData, "rust_result_init: Unknown alias type for real alias.");
274 }
275 }
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasIntegerArray; i++) {
277 ✗ const DATA_INTEGER_ALIAS *a = &mData->integerAlias[i];
278 ✗ if (a->filterOutput) continue;
279 ✗ int negate = a->negate ? OMC_RESULT_NEGATE_ARITHMETIC : OMC_RESULT_NEGATE_NONE;
280 ✗ switch (a->aliasType) {
281 ✗ case ALIAS_TYPE_VARIABLE: {
282 ✗ const STATIC_INTEGER_DATA *v = &mData->integerVarsData[a->nameID];
283 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_INTEGER, OMC_RESULT_KIND_COLUMN,
284 ✗ intColumn[sInfo->integerVarsIndex[a->nameID]], negate, v->time_unvarying, &v->dimension, FALSE);
285 break;
286 }
287 ✗ case ALIAS_TYPE_PARAMETER:
288 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_INTEGER, OMC_RESULT_KIND_PARAMETER, -1, negate, 0,
289 ✗ &mData->integerParameterData[a->nameID].dimension, FALSE);
290 break;
291 ✗ default:
292 ✗ throwStreamPrint(threadData, "rust_result_init: Unknown alias type for integer alias.");
293 }
294 }
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasBooleanArray; i++) {
296 ✗ const DATA_BOOLEAN_ALIAS *a = &mData->booleanAlias[i];
297 ✗ if (a->filterOutput) continue;
298 ✗ int negate = a->negate ? OMC_RESULT_NEGATE_LOGICAL : OMC_RESULT_NEGATE_NONE;
299 ✗ switch (a->aliasType) {
300 ✗ case ALIAS_TYPE_VARIABLE: {
301 ✗ const STATIC_BOOLEAN_DATA *v = &mData->booleanVarsData[a->nameID];
302 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_BOOLEAN, OMC_RESULT_KIND_COLUMN,
303 ✗ boolColumn[sInfo->booleanVarsIndex[a->nameID]], negate, v->time_unvarying, &v->dimension, FALSE);
304 break;
305 }
306 ✗ case ALIAS_TYPE_PARAMETER:
307 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_BOOLEAN, OMC_RESULT_KIND_PARAMETER, -1, negate, 0,
308 ✗ &mData->booleanParameterData[a->nameID].dimension, FALSE);
309 break;
310 ✗ default:
311 ✗ throwStreamPrint(threadData, "rust_result_init: Unknown alias type for boolean alias.");
312 }
313 }
314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasStringArray; i++) {
315 ✗ const DATA_STRING_ALIAS *a = &mData->stringAlias[i];
316 ✗ if (a->filterOutput) continue;
317 ✗ switch (a->aliasType) {
318 ✗ case ALIAS_TYPE_VARIABLE: {
319 ✗ const STATIC_STRING_DATA *v = &mData->stringVarsData[a->nameID];
320 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_STRING, OMC_RESULT_KIND_COLUMN,
321 ✗ stringColumn[sInfo->stringVarsIndex[a->nameID]], 0, v->time_unvarying, &v->dimension, FALSE);
322 break;
323 }
324 ✗ case ALIAS_TYPE_PARAMETER:
325 ✗ addSignals(d, a->info.name, a->info.comment, "", "", OMC_RESULT_TYPE_STRING, OMC_RESULT_KIND_PARAMETER, -1, 0, 0,
326 ✗ &mData->stringParameterData[a->nameID].dimension, FALSE);
327 break;
328 ✗ default:
329 ✗ throwStreamPrint(threadData, "rust_result_init: Unknown alias type for string alias.");
330 }
331 }
332
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 time.
8 for (size_t i = 0; i < d->signals.size(); i++) {
333 7 d->signals[i].name = d->strings[4 * i].c_str();
334 7 d->signals[i].description = d->strings[4 * i + 1].c_str();
335 7 d->signals[i].unit = d->strings[4 * i + 2].c_str();
336 7 d->signals[i].display_unit = d->strings[4 * i + 3].c_str();
337 }
338 1 }
339
340 4 static void fillRow(rust_result_data *d, simulation_result *self, DATA *data)
341 {
342 4 const SIMULATION_INFO *sInfo = data->simulationInfo;
343 4 const SIMULATION_DATA *local = data->localData[0];
344 size_t cur = 0;
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 d->row[cur++] = local->timeValue;
346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (self->cpuTime) {
347 ✗ rt_accumulate(SIM_TIMER_TOTAL);
348 ✗ d->row[cur++] = rt_accumulated(SIM_TIMER_TOTAL);
349 ✗ rt_tick(SIM_TIMER_TOTAL);
350 }
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (omc_flag[FLAG_SOLVER_STEPS]) {
352 ✗ d->row[cur++] = sInfo->solverSteps;
353 }
354
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (const block &b : d->reals) {
355
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (size_t k = 0; k < b.len; k++) d->row[cur++] = local->realVars[b.start + k];
356 }
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (size_t i = 0; i < d->nSensitivities; i++) {
358 ✗ d->row[cur++] = sInfo->sensitivityMatrix[i];
359 }
360
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (const block &b : d->ints) {
361
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (size_t k = 0; k < b.len; k++) d->row[cur++] = local->integerVars[b.start + k];
362 }
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (const block &b : d->bools) {
364 ✗ for (size_t k = 0; k < b.len; k++) d->row[cur++] = local->booleanVars[b.start + k];
365 }
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (const block &b : d->strs) {
367 ✗ for (size_t k = 0; k < b.len; k++) d->row[cur++] = internString(local->stringVars[b.start + k]);
368 }
369 4 }
370
371 /* The parameter values in signal order (an alias of a parameter repeats it). */
372 1 static void fillParams(rust_result_data *d, DATA *data)
373 {
374 1 const MODEL_DATA *mData = data->modelData;
375 1 const SIMULATION_INFO *sInfo = data->simulationInfo;
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 d->params.clear();
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersRealArray; i++) {
378 ✗ if (mData->realParameterData[i].filterOutput) continue;
379 ✗ for (size_t k = 0; k < mData->realParameterData[i].dimension.scalar_length; k++)
380 ✗ d->params.push_back(sInfo->realParameter[sInfo->realParamsIndex[i] + k]);
381 }
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersIntegerArray; i++) {
383 ✗ if (mData->integerParameterData[i].filterOutput) continue;
384 ✗ for (size_t k = 0; k < mData->integerParameterData[i].dimension.scalar_length; k++)
385 ✗ d->params.push_back(sInfo->integerParameter[sInfo->integerParamsIndex[i] + k]);
386 }
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersBooleanArray; i++) {
388 ✗ if (mData->booleanParameterData[i].filterOutput) continue;
389 ✗ for (size_t k = 0; k < mData->booleanParameterData[i].dimension.scalar_length; k++)
390 ✗ d->params.push_back(sInfo->booleanParameter[sInfo->booleanParamsIndex[i] + k]);
391 }
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nParametersStringArray; i++) {
393 ✗ if (mData->stringParameterData[i].filterOutput) continue;
394 ✗ for (size_t k = 0; k < mData->stringParameterData[i].dimension.scalar_length; k++)
395 ✗ d->params.push_back(internString(sInfo->stringParameter[sInfo->stringParamsIndex[i] + k]));
396 }
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasRealArray; i++) {
398 ✗ const DATA_REAL_ALIAS *a = &mData->realAlias[i];
399 ✗ if (a->filterOutput || a->aliasType != ALIAS_TYPE_PARAMETER) continue;
400 ✗ for (size_t k = 0; k < mData->realParameterData[a->nameID].dimension.scalar_length; k++)
401 ✗ d->params.push_back(sInfo->realParameter[sInfo->realParamsIndex[a->nameID] + k]);
402 }
403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasIntegerArray; i++) {
404 ✗ const DATA_INTEGER_ALIAS *a = &mData->integerAlias[i];
405 ✗ if (a->filterOutput || a->aliasType != ALIAS_TYPE_PARAMETER) continue;
406 ✗ for (size_t k = 0; k < mData->integerParameterData[a->nameID].dimension.scalar_length; k++)
407 ✗ d->params.push_back(sInfo->integerParameter[sInfo->integerParamsIndex[a->nameID] + k]);
408 }
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasBooleanArray; i++) {
410 ✗ const DATA_BOOLEAN_ALIAS *a = &mData->booleanAlias[i];
411 ✗ if (a->filterOutput || a->aliasType != ALIAS_TYPE_PARAMETER) continue;
412 ✗ for (size_t k = 0; k < mData->booleanParameterData[a->nameID].dimension.scalar_length; k++)
413 ✗ d->params.push_back(sInfo->booleanParameter[sInfo->booleanParamsIndex[a->nameID] + k]);
414 }
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for (int i = 0; i < mData->nAliasStringArray; i++) {
416 ✗ const DATA_STRING_ALIAS *a = &mData->stringAlias[i];
417 ✗ if (a->filterOutput || a->aliasType != ALIAS_TYPE_PARAMETER) continue;
418 ✗ for (size_t k = 0; k < mData->stringParameterData[a->nameID].dimension.scalar_length; k++)
419 ✗ d->params.push_back(internString(sInfo->stringParameter[sInfo->stringParamsIndex[a->nameID] + k]));
420 }
421 1 }
422
423 1 static void openWriter(rust_result_data *d, simulation_result *self, DATA *data, threadData_t *threadData)
424 {
425 1 fillParams(d, data);
426 1 fillRow(d, self, data);
427 1 char *error = NULL;
428 4 d->writer = omc_result_writer_open(self->filename, data->simulationInfo->outputFormat,
429 d->signals.data(), d->signals.size(),
430 d->columnTypes.data(), d->columnTypes.size(),
431 d->params.data(), d->params.size(),
432 1 d->row.data(), data->simulationInfo->startTime, data->simulationInfo->stopTime,
433
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 omc_flag[FLAG_SINGLE_PRECISION] ? 1 : 0,
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 omc_flag[FLAG_MAT_SYNC] ? atoi(omc_flagValue[FLAG_MAT_SYNC]) : 0, &error);
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!d->writer) {
436 ✗ std::string msg = error ? error : "unknown error";
437 ✗ omc_result_free_string(error);
438 ✗ throwStreamPrint(threadData, "Error opening result file %s: %s", self->filename, msg.c_str());
439 }
440 1 }
441
442 /* Called once initialization is done: parameters and the time-invariant
443 * variables have their final values, so the file is opened here. */
444 1 void rust_result_writeParameterData(simulation_result *self, DATA *data, threadData_t *threadData)
445 {
446 1 rust_result_data *d = (rust_result_data *)self->storage;
447 1 rt_tick(SIM_TIMER_OUTPUT);
448
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (!d->writer) {
449 1 openWriter(d, self, data, threadData);
450 }
451 1 rt_accumulate(SIM_TIMER_OUTPUT);
452 1 }
453
454 3 void rust_result_emit(simulation_result *self, DATA *data, threadData_t *threadData)
455 {
456 3 rust_result_data *d = (rust_result_data *)self->storage;
457 3 rt_tick(SIM_TIMER_OUTPUT);
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!d->writer) {
459 ✗ openWriter(d, self, data, threadData);
460 }
461 3 fillRow(d, self, data);
462 3 omc_result_writer_emit(d->writer, d->row.data());
463 3 rt_accumulate(SIM_TIMER_OUTPUT);
464 3 }
465
466 1 void rust_result_free(simulation_result *self, DATA *data, threadData_t *threadData)
467 {
468 1 rust_result_data *d = (rust_result_data *)self->storage;
469
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (!d) {
470 return;
471 }
472 1 rt_tick(SIM_TIMER_OUTPUT);
473
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 if (d->writer && !omc_result_writer_close(d->writer)) {
474 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0, "Writing the result file %s failed.", self->filename);
475 }
476 1 delete d;
477 1 self->storage = NULL;
478 1 rt_accumulate(SIM_TIMER_OUTPUT);
479 }
480
481 } /* extern "C" */
482