Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 92
Functions: 0.0% 0 / 0 / 8
Branches: 0.0% 0 / 0 / 72

OMCompiler/SimulationRuntime/c/simulation/solver/gbode_conf.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 /*! \file gbode_conf.c
29 */
30
31 #include <string.h>
32
33 #include "../../util/omc_error.h"
34 #include "../../simulation/options.h"
35
36 #include "gbode_conf.h"
37
38 /**
39 * @brief Dump available flag options to stdout.
40 *
41 * @param flagName Name of flag
42 * @param flagValue Given value of flag.
43 * @param argsArr Pointer to flag argument names.
44 * @param maxArgs Size of maxArgs.
45 */
46 ✗ static void dumpOptions(const char* flagName, const char* flagValue, const char** argsArr, unsigned int maxArgs)
47 {
48 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0, "Unknown flag value \"%s\" for flag %s.", flagValue, flagName);
49 ✗ infoStreamPrint(OMC_LOG_STDOUT, 1, "Valid arguments are:");
50 ✗ for (int i=0; i<maxArgs; i++) {
51 ✗ infoStreamPrint(OMC_LOG_STDOUT, 0, "%s", argsArr[i]);
52 }
53 ✗ messageClose(OMC_LOG_STDOUT);
54 ✗ }
55
56 /**
57 * @brief Get Runge-Kutta method from simulation flag FLAG_SR or FLAG_MR.
58 *
59 * Defaults to method RK_ESDIRK4 for single-rate.
60 *
61 * Defaults to method RK_ESDIRK4 for multi-rate method, if single-rate method is implicit.
62 * Otherwise us same method as single-rate method.
63 *
64 * Returns GB_UNKNOWN if flag is not known.
65 *
66 * @param flag FLAG_SR for single-rate method.
67 * FLAG_MR for multi-rate method.
68 * @return enum GB_METHOD Runge-Kutta method.
69 */
70 ✗ enum GB_METHOD getGB_method(enum _FLAG flag)
71 {
72 enum GB_METHOD method;
73 const char* flag_value;
74 ✗ assertStreamPrint(NULL, flag==FLAG_SR || flag==FLAG_MR, "Illegal input to getGB_method. Expected FLAG_SR or FLAG_MR ");
75
76 // Get method from flag
77 ✗ if (omc_flag[flag]) {
78 ✗ flag_value = omc_flagValue[flag];
79 ✗ for (method=GB_UNKNOWN; method<RK_MAX; method++) {
80 ✗ if (strcmp(flag_value, GB_METHOD_NAME[method]) == 0) {
81 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode method: %s", GB_METHOD_NAME[method]);
82 ✗ return method;
83 }
84 }
85 ✗ dumpOptions(FLAG_NAME[flag], flag_value, GB_METHOD_NAME, RK_MAX);
86 ✗ return GB_UNKNOWN;
87 }
88
89 // Default value for multi-rate method
90 ✗ if (flag == FLAG_MR) {
91 ✗ enum GB_METHOD singleRateMethod = getGB_method(FLAG_SR);
92
93 ✗ if (getGB_NLS_method(FLAG_MR_NLS) == GB_NLS_INTERNAL)
94 {
95 // if internal + multirate integrator not set -> use single rate integrator
96 return singleRateMethod;
97 }
98
99 ✗ switch (singleRateMethod)
100 {
101 case RK_GAUSS2:
102 case RK_GAUSS3:
103 case RK_GAUSS4:
104 case RK_GAUSS5:
105 case RK_GAUSS6:
106 case RK_SIRK3_2_3L2SA:
107 case RK_SIRK3_2_4L3SA:
108 case RK_SIRK3_2_5L3SA:
109 case RK_SIRK4_3_LAGUERRE:
110 case RK_SIRK4_3_5L3SA:
111 case RK_SIRK5_4_5L3SA:
112 case RK_SIRK4_3_6L4SA:
113 case RK_SIRK5_4_6L4SA:
114 case RK_SIRK5_4_7L4SA:
115 case RK_SIRK6_5_7L4SA:
116 case RK_SIRK6_5_8L4SA:
117 case RK_SIRK5_4_7L5SA:
118 case RK_FIRK7_6TS_5L4SA:
119 case RK_RADAU_IA_2:
120 case RK_RADAU_IA_3:
121 case RK_RADAU_IA_4:
122 case RK_RADAU_IIA_2:
123 case RK_RADAU_IIA_3:
124 case RK_RADAU_IIA_4:
125 case RK_RADAU_IIA_5:
126 case RK_RADAU_IIA_6:
127 case RK_RADAU_IIA_7:
128 case RK_LOBA_IIIA_3:
129 case RK_LOBA_IIIA_4:
130 case RK_LOBA_IIIB_3:
131 case RK_LOBA_IIIB_4:
132 case RK_LOBA_IIIC_3:
133 case RK_LOBA_IIIC_4:
134 // if not internal + multirate integrator not set -> use default singlerate integrator
135 // as fully implicit is not implemented for standard multirate
136 return RK_ESDIRK4;
137 ✗ default:
138 // use implemented singlerate integrator
139 ✗ return singleRateMethod;
140 }
141 }
142
143 // Default value for single-rate method
144 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode method: esdirk4 [default]");
145 ✗ return RK_ESDIRK4;
146 }
147
148 /**
149 * @brief Get non-linear solver method for Runge-Kutta from flag FLAG_SR_NLS.
150 *
151 * Defaults to GB_NLS_INTERNAL for single-rate.
152 * Defaults to nls method of single-rate for multi-rate.
153 * Returns GB_UNKNOWN if flag is not known.
154 *
155 * @param flag FLAG_SR_NLS for single-rate method.
156 * FLAG_MR_NLS for multi-rate method.
157 * @return enum GB_NLS_METHOD NLS method.
158 */
159 ✗ enum GB_NLS_METHOD getGB_NLS_method(enum _FLAG flag)
160 {
161 enum GB_NLS_METHOD method;
162 const char* flag_value;
163 ✗ assertStreamPrint(NULL, flag==FLAG_SR_NLS || flag==FLAG_MR_NLS, "Illegal input to getGB_NLS_method. Expected FLAG_SR_NLS or FLAG_MR_NLS ");
164
165 // Get method from flag
166 ✗ if (omc_flag[flag]) {
167 ✗ flag_value = omc_flagValue[flag];
168 ✗ for (method = GB_NLS_UNKNOWN; method < GB_NLS_MAX; method++) {
169 ✗ if (strcmp(flag_value, GB_NLS_METHOD_NAME[method]) == 0) {
170 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode NLS method: %s", GB_NLS_METHOD_NAME[method]);
171 ✗ return method;
172 }
173 }
174 ✗ dumpOptions(FLAG_NAME[flag], flag_value, GB_NLS_METHOD_NAME, GB_NLS_MAX);
175 ✗ return GB_NLS_UNKNOWN;
176 }
177
178 // Default value
179 ✗ if (flag == FLAG_MR_NLS) {
180 return getGB_NLS_method(FLAG_SR_NLS);
181 } else {
182 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode NLS method: internal [default]");
183 ✗ return GB_NLS_INTERNAL;
184 }
185 }
186
187 /**
188 * @brief Get step size controller from simulation flag.
189 *
190 * Reads value from from FLAG_SR_CTRL or FLAG_MR_CTRL.
191 * Defaults to IController (GB_CTRL_I) if flag is not set.
192 *
193 * @param flag FLAG_SR_CTRL for single-rate method.
194 * FLAG_MR_CTRL for multi-rate method.
195 * @return enum GB_CTRL_METHOD Step size control method.
196 */
197 ✗ enum GB_CTRL_METHOD getControllerMethod(enum _FLAG flag)
198 {
199 enum GB_CTRL_METHOD method;
200 const char *flag_value;
201 ✗ assertStreamPrint(NULL, flag==FLAG_SR_CTRL || flag==FLAG_MR_CTRL, "Illegal input to getControllerMethod. Expected FLAG_SR_CTRL or FLAG_MR_CTRL ");
202
203 ✗ if (omc_flag[flag]) {
204 ✗ flag_value = omc_flagValue[flag];
205 ✗ for (method = GB_CTRL_UNKNOWN; method < GB_CTRL_MAX; method++) {
206 ✗ if (strcmp(flag_value, GB_CTRL_METHOD_NAME[method]) == 0) {
207 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode step size control: %s", GB_CTRL_METHOD_NAME[method]);
208 ✗ return method;
209 }
210 }
211 ✗ dumpOptions(FLAG_NAME[flag], flag_value, GB_CTRL_METHOD_NAME, GB_CTRL_MAX);
212 ✗ return GB_CTRL_UNKNOWN;
213 } else {
214 // Default value
215 ✗ if (flag == FLAG_MR_CTRL) {
216 return getControllerMethod(FLAG_SR_CTRL);
217 } else {
218 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode step size control: pid_h312 [default]");
219 ✗ return GB_CTRL_PID_H312; // Default for single-rate method
220 }
221 }
222 }
223
224 /**
225 * @brief Get interpolation method from simulation flag.
226 *
227 * Reads value from from FLAG_SR_INT or FLAG_MR_INT.
228 * Defaults to interpolatiom (GB_INTERPOL_HERMITE) if flag is not set.
229 *
230 * @param flag FLAG_SR_INT for single-rate method.
231 * FLAG_MR_INT for multi-rate method.
232 * @return enum GB_INTERPOL_METHOD Interpolation method for emitting
233 * results and slow states interpolation.
234 */
235 ✗ enum GB_INTERPOL_METHOD getInterpolationMethod(enum _FLAG flag)
236 {
237 enum GB_INTERPOL_METHOD method;
238 const char *flag_value;
239 ✗ assertStreamPrint(NULL, flag==FLAG_SR_INT || flag==FLAG_MR_INT, "Illegal input to getInterpolationMethod. Expected FLAG_SR_INT or FLAG_MR_INT ");
240
241 ✗ if (omc_flag[flag]) {
242 ✗ flag_value = omc_flagValue[flag];
243 ✗ for (method = GB_INTERPOL_UNKNOWN; method < GB_INTERPOL_MAX; method++) {
244 ✗ if (strcmp(flag_value, GB_INTERPOL_METHOD_NAME[method]) == 0) {
245 ✗ if (flag == FLAG_MR_INT && (method == GB_INTERPOL_HERMITE_ERRCTRL || method == GB_DENSE_OUTPUT_ERRCTRL)) {
246 ✗ warningStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode interpolation method %s not supported for fast state integration", GB_INTERPOL_METHOD_NAME[method]);
247 method = GB_DENSE_OUTPUT;
248 }
249 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode interpolation method: %s", GB_INTERPOL_METHOD_NAME[method]);
250 ✗ return method;
251 }
252 }
253 ✗ dumpOptions(FLAG_NAME[flag], flag_value, GB_INTERPOL_METHOD_NAME, GB_INTERPOL_MAX);
254 ✗ return GB_INTERPOL_UNKNOWN;
255 } else {
256 // Default value
257 ✗ if (flag == FLAG_MR_INT) {
258 ✗ method = getInterpolationMethod(FLAG_SR_INT);
259 ✗ if (method == GB_INTERPOL_HERMITE_ERRCTRL || method == GB_DENSE_OUTPUT_ERRCTRL) {
260 ✗ warningStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode interpolation method %s not supported for fast state integration", GB_INTERPOL_METHOD_NAME[method]);
261 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode interpolation method: dense_output [default]");
262 method = GB_DENSE_OUTPUT;
263 }
264 ✗ return method;
265 } else {
266 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, "Chosen gbode interpolation method: dense_output_errctrl [default]");
267 ✗ return GB_DENSE_OUTPUT_ERRCTRL;
268 }
269 }
270 }
271
272 /**
273 * @brief Use filter technic for step size control
274 *
275 * Read flag FLAG_SR_CTRL_FILTER to get filter value.
276 * Defaults to 1.
277 * gbctrl_filter = 0 -> constant step size,
278 * gbctrl_filter = 1 -> full adaptation without smoothing.
279 *
280 * @return double Percentage of fast states selection.
281 */
282 ✗ double getGBCtrlFilterValue(void)
283 {
284 double filter = 1.0;
285
286 ✗ if (omc_flag[FLAG_SR_CTRL_FILTER]) {
287 ✗ filter = atof(omc_flagValue[FLAG_SR_CTRL_FILTER]);
288 ✗ if (filter < 0 || filter > 1) {
289 ✗ throwStreamPrint(NULL, "Flag -gbctrl_filter has to be between 0.0 and 1.0, but %s was given.", omc_flagValue[FLAG_SR_CTRL_FILTER]);
290 }
291 }
292
293 ✗ return filter;
294 }
295
296
297 /**
298 * @brief Get percentage of states for the fast states selection.
299 *
300 * Read flag FLAG_MR_PAR to get percentage.
301 * Defaults to 0.
302 *
303 * @return double Percentage of fast states selection.
304 */
305 ✗ double getGBRatio(void)
306 {
307 double percentage = 0.0;
308
309 ✗ if (omc_flag[FLAG_MR_PAR]) {
310 ✗ percentage = atof(omc_flagValue[FLAG_MR_PAR]);
311 ✗ if (percentage < 0 || percentage > 1) {
312 ✗ throwStreamPrint(NULL, "Flag -gbratio has to be between 0.0 and 1.0, but %s was given.", omc_flagValue[FLAG_MR_PAR]);
313 }
314 }
315
316 ✗ return percentage;
317 }
318
319 /**
320 * @brief Get error method from user flag.
321 *
322 * Reads flag FLAG_SR_ERR, FLAG_MR_ERR.
323 * Defaults to GB_ERROR_DEFAULT.
324 *
325 * @param flag Flag specifying error estimation.
326 * Allowed values: FLAG_SR_ERR, FLAG_MR_ERR
327 * @return enum GB_ERROR_METHOD Error method.
328 */
329 ✗ enum GB_ERROR_METHOD getGBErr(enum _FLAG flag)
330 {
331 enum GB_ERROR_METHOD method;
332 const char *flag_value;
333 ✗ assertStreamPrint(NULL, flag == FLAG_SR_ERR || flag == FLAG_MR_ERR, "Illegal input to getGBErr. Expected FLAG_SR_ERR or FLAG_MR_ERR ");
334
335 ✗ if (omc_flag[flag]) {
336 ✗ flag_value = omc_flagValue[flag];
337 ✗ for (method = GB_ERROR_DEFAULT; method < GB_ERROR_MAX; method++) {
338 ✗ if (strcmp(flag_value, GB_ERROR_METHOD_NAME[method]) == 0) {
339 ✗ return method;
340 }
341 }
342 ✗ dumpOptions(FLAG_NAME[flag], flag_value, GB_ERROR_METHOD_NAME + GB_ERROR_DEFAULT, GB_ERROR_MAX - GB_ERROR_DEFAULT);
343 ✗ omc_throw(NULL);
344 }
345
346 return GB_ERROR_DEFAULT;
347 }
348