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 / 363
Functions: 0.0% 0 / 0 / 13
Branches: 0.0% 0 / 0 / 169

OMCompiler/SimulationRuntime/c/simulation/solver/sundials_error.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 sundials_error.c
29 */
30
31 #include "sundials_error.h"
32
33 #ifdef WITH_SUNDIALS
34
35 #define UNUSED(x) (void)(x) /* Surpress compiler warnings for unused function input */
36
37 /* Internal function prototypes */
38 static void checkReturnFlag_CV(int flag, const char *functionName);
39 static void checkReturnFlag_CVLS(int flag, const char *functionName);
40 #ifndef OMC_FMI_RUNTIME
41 static void checkReturnFlag_KIN(int flag, const char *functionName);
42 static void checkReturnFlag_KINLS(int flag, const char *functionName);
43 static void checkReturnFlag_IDA(int flag, const char *functionName);
44 static void checkReturnFlag_IDALS(int flag, const char *functionName);
45 static void checkReturnFlag_SUNLS(SUNErrCode flag, const char *functionName);
46 static void checkReturnFlag_SUNMatrix(SUNErrCode flag, const char *functionName);
47 #endif
48
49 /**
50 * @brief Checks given flag and reports potential error.
51 *
52 * Checks sundialsFlagType type to decide what kind given flag is.
53 * Possible kinds are: SUNDIALS_KIN_FLAG, SUNDIALS_KINLS_FLAG,
54 * SUNDIALS_SUNLS_FLAG or SUNDIALS_UNKNOWN_FLAG.
55 *
56 * @param flag Return value of Sundials routine.
57 * @param type Type of Sundials flag returned by routine specified by
58 * functionName.
59 * @param functionName Name of Sundials function that returned the flag.
60 */
61 ✗ void checkReturnFlag_SUNDIALS(int flag, sundialsFlagType type,
62 const char *functionName) {
63 ✗ switch (type) {
64 ✗ case SUNDIALS_UNKNOWN_FLAG:
65 ✗ if (flag < 0) {
66 ✗ throwStreamPrint(NULL, "##SUNDIALS##: Some error with value %i occurred in function %s.", flag, functionName);
67 }
68 break;
69 ✗ case SUNDIALS_CV_FLAG:
70 ✗ checkReturnFlag_CV(flag, functionName);
71 ✗ break;
72 ✗ case SUNDIALS_CVLS_FLAG:
73 ✗ checkReturnFlag_CVLS(flag, functionName);
74 ✗ break;
75 #ifndef OMC_FMI_RUNTIME
76 ✗ case SUNDIALS_IDA_FLAG:
77 ✗ checkReturnFlag_IDA(flag, functionName);
78 ✗ break;
79 ✗ case SUNDIALS_IDALS_FLAG:
80 ✗ checkReturnFlag_IDALS(flag, functionName);
81 ✗ break;
82 ✗ case SUNDIALS_KIN_FLAG:
83 ✗ checkReturnFlag_KIN(flag, functionName);
84 ✗ break;
85 ✗ case SUNDIALS_KINLS_FLAG:
86 ✗ checkReturnFlag_KINLS(flag, functionName);
87 ✗ break;
88 ✗ case SUNDIALS_SUNLS_FLAG:
89 ✗ checkReturnFlag_SUNLS(flag, functionName);
90 ✗ break;
91 ✗ case SUNDIALS_MATRIX_FLAG:
92 ✗ checkReturnFlag_SUNMatrix(flag, functionName);
93 ✗ break;
94 #endif
95 ✗ default:
96 ✗ throwStreamPrint(NULL, "In function checkReturnFlag_SUNDIALS: Invalid sundialsFlagType %u.", type);
97 }
98 ✗ }
99
100 /**
101 * @brief Checks given CVODE flag and reports potential error.
102 *
103 * @param flag Return value of CVODE routine.
104 * @param functionName Name of CVODE function that returned the flag.
105 */
106 ✗ static void checkReturnFlag_CV(int flag, const char *functionName) {
107
108 ✗ const char* flagName = CVodeGetReturnFlagName(flag);
109
110 ✗ switch (flag) {
111 case CV_SUCCESS:
112 case CV_TSTOP_RETURN:
113 case CV_ROOT_RETURN:
114 break;
115 ✗ case CV_WARNING:
116 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0, "##CVODE## %s In function %s: Got some warning.", flagName, functionName);
117 ✗ break;
118 ✗ case CV_TOO_MUCH_WORK:
119 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The solver took maximum number of internal steps but could not reach tout.", flagName, functionName);
120 break;
121 ✗ case CV_TOO_MUCH_ACC:
122 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The solver could not satisfy the accuracy demanded by the user for some internal step.", flagName, functionName);
123 break;
124 ✗ case CV_ERR_FAILURE:
125 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: Error test failures occurred too many times during one internal time step or minimum step size was reached.", flagName, functionName);
126 break;
127 ✗ case CV_CONV_FAILURE:
128 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: Convergence test failures occurred too many times during one internal time step or minimum step size was reached.", flagName, functionName);
129 break;
130 ✗ case CV_LINIT_FAIL:
131 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The linear solver’s initialization function failed.", flagName, functionName);
132 break;
133 ✗ case CV_LSETUP_FAIL:
134 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The linear solver’s setup function failed in an unrecoverable manner.", flagName, functionName);
135 break;
136 ✗ case CV_LSOLVE_FAIL:
137 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The linear solver’s solve function failed in an unrecoverable manner.", flagName, functionName);
138 break;
139 ✗ case CV_RHSFUNC_FAIL:
140 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The right-hand side function failed in an unrecoverable manner.", flagName, functionName);
141 break;
142 ✗ case CV_FIRST_RHSFUNC_ERR:
143 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The right-hand side function failed at the first call.", flagName, functionName);
144 break;
145 ✗ case CV_REPTD_RHSFUNC_ERR:
146 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The right-hand side function had repeated recoverable errors.", flagName, functionName);
147 break;
148 ✗ case CV_UNREC_RHSFUNC_ERR:
149 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The right-hand side function had a recoverable error, but no recovery is possible.", flagName, functionName);
150 break;
151 ✗ case CV_RTFUNC_FAIL:
152 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The rootfinding function failed in an unrecoverable manner.", flagName, functionName);
153 break;
154 ✗ case CV_NLS_INIT_FAIL:
155 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The nonlinear solver’s init routine failed.", flagName, functionName);
156 break;
157 ✗ case CV_NLS_SETUP_FAIL:
158 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The nonlinear solver’s setup routine failed.", flagName, functionName);
159 break;
160 ✗ case CV_CONSTR_FAIL:
161 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The inequality constraints were violated and the solver was unable to recover.", flagName, functionName);
162 break;
163 ✗ case CV_NLS_FAIL:
164 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The nonlinear solver failed in an unrecoverable manner.", flagName, functionName);
165 break;
166 ✗ case CV_MEM_FAIL:
167 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: A memory allocation failed.", flagName, functionName);
168 break;
169 ✗ case CV_MEM_NULL:
170 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The cvode mem argument was NULL.", flagName, functionName);
171 break;
172 ✗ case CV_ILL_INPUT:
173 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: One of the function inputs is illegal.", flagName, functionName);
174 break;
175 ✗ case CV_NO_MALLOC:
176 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The cvode memory block was not allocated by a call to CVodeMalloc.", flagName, functionName);
177 break;
178 ✗ case CV_BAD_K:
179 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The derivative order k is larger than the order used.", flagName, functionName);
180 break;
181 ✗ case CV_BAD_T:
182 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The time t is outside the last step taken.", flagName, functionName);
183 break;
184 ✗ case CV_BAD_DKY:
185 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The output derivative vector is NULL.", flagName, functionName);
186 break;
187 ✗ case CV_TOO_CLOSE:
188 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The output and initial times are too close to each other.", flagName, functionName);
189 break;
190 ✗ case CV_VECTOROP_ERR:
191 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: A vector operation failed.", flagName, functionName);
192 break;
193 ✗ case CV_PROJ_MEM_NULL:
194 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The projection memory was NULL.", flagName, functionName);
195 break;
196 ✗ case CV_PROJFUNC_FAIL:
197 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The projection function failed in an unrecoverable manner.", flagName, functionName);
198 break;
199 ✗ case CV_REPTD_PROJFUNC_ERR:
200 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The projection function had repeated recoverable errors.", flagName, functionName);
201 break;
202 ✗ case CV_UNRECOGNIZED_ERR:
203 default:
204 ✗ throwStreamPrint(NULL,"##CVODE## In function %s: Error with flag %i.", functionName, flag);
205 }
206
207 ✗ free((char*)flagName); // We leak memory if an error is thrown, but doesn't matter in that case.
208 ✗ }
209
210 /**
211 * @brief Checks given CVODE linear solver flag and reports potential error.
212 *
213 * @param flag Return value of Cvode linear solver routine.
214 * @param functionName Name of CVODE function that returned the flag.
215 */
216 ✗ static void checkReturnFlag_CVLS(int flag, const char *functionName) {
217
218 ✗ const char* flagName = CVodeGetLinReturnFlagName(flag);
219
220 ✗ switch (flag) {
221 case CVLS_SUCCESS:
222 break;
223 ✗ case CVLS_MEM_NULL:
224 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The cvode mem argument was NULL.", flagName, functionName);
225 break;
226 ✗ case CVLS_LMEM_NULL:
227 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The cvls linear solver has not been initialized.", flagName, functionName);
228 break;
229 ✗ case CVLS_ILL_INPUT:
230 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The cvls solver is not compatible with the current nvector module.", flagName, functionName);
231 break;
232 ✗ case CVLS_MEM_FAIL:
233 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: A memory allocation request failed.", flagName, functionName);
234 break;
235 ✗ case CVLS_PMEM_NULL:
236 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The preconditioner module has not been initialized.", flagName, functionName);
237 break;
238 ✗ case CVLS_JACFUNC_UNRECVR:
239 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The Jacobian function failed in an unrecoverable manner.", flagName, functionName);
240 break;
241 ✗ case CVLS_JACFUNC_RECVR:
242 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: The Jacobian function had a recoverable error.", flagName, functionName);
243 break;
244 ✗ case CVLS_SUNMAT_FAIL:
245 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: An error occurred with the current sunmatrix module", flagName, functionName);
246 break;
247 ✗ case CVLS_SUNLS_FAIL:
248 ✗ throwStreamPrint(NULL, "##CVODE## %s In function %s: An error occurred with the current sunlinsol module", flagName, functionName);
249 break;
250 ✗ default:
251 ✗ throwStreamPrint(NULL,"##CVODE## In function %s: Error with flag %i.", functionName, flag);
252 }
253 ✗ }
254
255 /**
256 * @brief Mute SUNDIALS' own output for a context.
257 *
258 * Use the OMC log streams instead.
259 *
260 * @param sunctx SUNDIALS context whose logger should be muted.
261 */
262 ✗ void sundialsSilenceLogger(SUNContext sunctx) {
263 ✗ SUNLogger logger = NULL;
264
265 ✗ if (SUNContext_GetLogger(sunctx, &logger) != SUN_SUCCESS || logger == NULL) {
266 ✗ return;
267 }
268 /* An empty filename disables the stream */
269 ✗ SUNLogger_SetErrorFilename(logger, "");
270 ✗ SUNLogger_SetWarningFilename(logger, "");
271 ✗ SUNLogger_SetInfoFilename(logger, "");
272 ✗ SUNLogger_SetDebugFilename(logger, "");
273 }
274
275 /**
276 * @brief Error handler function for the integrators, CVODE and IDA.
277 *
278 * Registered on the SUNContext with SUNContext_PushErrHandler.
279 *
280 * @param line Line in the SUNDIALS source where the error was raised.
281 * @param func Name of the SUNDIALS function in which the error occurred.
282 * @param file SUNDIALS source file where the error was raised.
283 * @param msg Error message.
284 * @param err_code SUNDIALS error code.
285 * @param err_user_data Pointer to user data given with SUNContext_PushErrHandler.
286 * @param sunctx SUNDIALS context, unused.
287 */
288 ✗ void sundialsErrorHandlerFunction(int line, const char *func, const char *file,
289 const char *msg, SUNErrCode err_code,
290 void *err_user_data, SUNContext sunctx)
291 {
292 UNUSED(sunctx); /* Disables compiler warning */
293
294 ✗ if (err_user_data != NULL && OMC_ACTIVE_STREAM(OMC_LOG_SOLVER)) {
295 ✗ infoStreamPrint(OMC_LOG_SOLVER, 1, "#### SUNDIALS error message #####");
296 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, " -> error code %d\n -> function %s\n -> at %s:%d", err_code, func, file, line);
297 /* Package level codes (CV_ and IDA_ ones) are not SUNErrCodes, so
298 * SUNGetErrMsg() only makes sense when SUNDIALS did not supply a message. */
299 ✗ infoStreamPrint(OMC_LOG_SOLVER, 0, " Message: %s", msg ? msg : SUNGetErrMsg(err_code));
300 ✗ messageClose(OMC_LOG_SOLVER);
301 }
302 ✗ }
303
304 #ifndef OMC_FMI_RUNTIME
305 /**
306 * @brief Checks given KINSOL flag and reports potential error.
307 *
308 * @param flag Return value of Kinsol routine.
309 * @param functionName Name of Kinsol function that returned the flag.
310 */
311 ✗ static void checkReturnFlag_KIN(int flag, const char *functionName) {
312
313 ✗ const char* flagName = KINGetReturnFlagName(flag);
314
315 ✗ switch (flag) {
316 case KIN_SUCCESS:
317 case KIN_INITIAL_GUESS_OK:
318 case KIN_STEP_LT_STPTOL:
319 break;
320 ✗ case KIN_WARNING:
321 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0,
322 "##KINSOL## %s In function %s: Got some warning.", flagName, functionName);
323 ✗ break;
324 ✗ case KIN_MEM_NULL:
325 ✗ throwStreamPrint(NULL, "##KINSOL## %s In function %s: Out of memory.", flagName, functionName);
326 break;
327 ✗ case KIN_ILL_INPUT:
328 ✗ throwStreamPrint(NULL, "##KINSOL## %s In function %s: An input argument has an illegal value.", flagName, functionName);
329 break;
330 ✗ case KIN_NO_MALLOC:
331 ✗ throwStreamPrint(NULL, "##KINSOL## %s In function %s: Kinsol memory was not allocated by a call to KINCreate.", flagName, functionName);
332 break;
333 ✗ case KIN_MEM_FAIL:
334 ✗ throwStreamPrint(NULL, "##KINSOL## %s In function %s: A memory allocation request has failed.", flagName, functionName);
335 break;
336 ✗ case KIN_LINESEARCH_NONCONV:
337 ✗ throwStreamPrint(NULL,
338 "##KINSOL## %s In function %s: The line search algorithm was "
339 "unable to find an iterate sufficiently distinct from the "
340 "current iterate, or could not find an iterate satisfying "
341 "the sufficient decrease condition.", flagName,
342 functionName);
343 break;
344 ✗ case KIN_MAXITER_REACHED:
345 ✗ throwStreamPrint(NULL,
346 "##KINSOL## %s In function %s: The maximum number of "
347 "nonlinear iterations has been reached.", flagName,
348 functionName);
349 break;
350 ✗ case KIN_MXNEWT_5X_EXCEEDED:
351 ✗ throwStreamPrint(NULL,
352 "##KINSOL## %s In function %s: Error KIN_MXNEWT_5X_EXCEEDED.", flagName,
353 functionName);
354 break;
355 ✗ case KIN_LINESEARCH_BCFAIL:
356 ✗ throwStreamPrint(NULL,
357 "##KINSOL## %s In function %s: Error KIN_LINESEARCH_BCFAIL.", flagName,
358 functionName);
359 break;
360 ✗ case KIN_LINSOLV_NO_RECOVERY:
361 ✗ throwStreamPrint(
362 NULL,
363 "##KINSOL## %s In function %s: Error KIN_LINSOLV_NO_RECOVERY.", flagName,
364 functionName);
365 break;
366 ✗ case KIN_LINIT_FAIL:
367 ✗ throwStreamPrint(NULL,
368 "##KINSOL## %s In function %s: Error KIN_LINIT_FAIL.", flagName,
369 functionName);
370 break;
371 ✗ case KIN_LSETUP_FAIL:
372 ✗ throwStreamPrint(NULL,
373 "##KINSOL## %s In function %s: Error KIN_LSETUP_FAIL.", flagName,
374 functionName);
375 break;
376 ✗ case KIN_LSOLVE_FAIL:
377 ✗ throwStreamPrint(NULL,
378 "##KINSOL## %s In function %s: Error KIN_LSOLVE_FAIL.", flagName,
379 functionName);
380 break;
381 ✗ case KIN_SYSFUNC_FAIL:
382 ✗ throwStreamPrint(NULL,
383 "##KINSOL## %s In function %s: Error KIN_SYSFUNC_FAIL.", flagName,
384 functionName);
385 break;
386 ✗ case KIN_FIRST_SYSFUNC_ERR:
387 ✗ throwStreamPrint(NULL,
388 "##KINSOL## %s In function %s: Error KIN_FIRST_SYSFUNC_ERR.", flagName,
389 functionName);
390 break;
391 ✗ case KIN_REPTD_SYSFUNC_ERR:
392 ✗ throwStreamPrint(NULL,
393 "##KINSOL## %s In function %s: Error KIN_REPTD_SYSFUNC_ERR.", flagName,
394 functionName);
395 break;
396 ✗ case KIN_VECTOROP_ERR:
397 ✗ throwStreamPrint(NULL,
398 "##KINSOL## %s In function %s: Error KIN_VECTOROP_ERR.", flagName,
399 functionName);
400 break;
401 ✗ default:
402 ✗ throwStreamPrint(NULL,
403 "##KINSOL## %s In function %s: Error with flag %i.", flagName,
404 functionName, flag);
405 }
406
407 ✗ free((char*)flagName);
408 ✗ }
409
410 /**
411 * @brief Checks given KINLS flag and reports potential error.
412 *
413 * @param flag Return value of Kinsol routine.
414 * @param functionName Name of Kinsol function that returned the flag.
415 */
416 ✗ static void checkReturnFlag_KINLS(int flag, const char *functionName) {
417 ✗ switch (flag) {
418 case KINLS_SUCCESS:
419 break;
420 ✗ case KINLS_MEM_NULL:
421 ✗ throwStreamPrint(NULL,
422 "##KINLS## In function %s: The kin_mem pointer is NULL.",
423 functionName);
424 break;
425 ✗ case KINLS_ILL_INPUT:
426 ✗ throwStreamPrint(NULL,
427 "##KINLS## In function %s: An input argument has an "
428 "illegal value or is incompatible.",
429 functionName);
430 break;
431 ✗ case KINLS_MEM_FAIL:
432 ✗ throwStreamPrint(
433 NULL,
434 "##KINLS## In function %s: A memory allocation request failed.",
435 functionName);
436 break;
437 ✗ case KINLS_PMEM_NULL:
438 ✗ throwStreamPrint(NULL,
439 "##KINLS## In function %s: TODO: ADD ERROR MESSAGE.",
440 functionName);
441 break;
442 ✗ case KINLS_JACFUNC_ERR:
443 ✗ throwStreamPrint(NULL,
444 "##KINLS## In function %s: TODO: ADD ERROR MESSAGE.",
445 functionName);
446 break;
447 ✗ case KINLS_SUNMAT_FAIL:
448 ✗ throwStreamPrint(NULL,
449 "##KINLS## In function %s: TODO: ADD ERROR MESSAGE.",
450 functionName);
451 break;
452 ✗ case KINLS_SUNLS_FAIL:
453 ✗ throwStreamPrint(
454 NULL,
455 "##KINLS## In function %s: A call to the LS object failed.",
456 functionName);
457 break;
458 ✗ default:
459 ✗ throwStreamPrint(NULL,
460 "##KINLS## In function %s: Error with flag %i.",
461 functionName, flag);
462 }
463 ✗ }
464
465 /**
466 * @brief Checks given IDA/IDAS flag and reports potential error.
467 *
468 * Throws on errors.
469 *
470 * TODO: Make it optionla to throw error and only report error instead.
471 *
472 * @param flag Return value of IDA routine.
473 * @param functionName Name of IDA function that returned the flag.
474 */
475 ✗ static void checkReturnFlag_IDA(int flag, const char *functionName) {
476 ✗ switch (flag) {
477 case IDA_SUCCESS: /* Successful function return. */
478 case IDA_TSTOP_RETURN: /* IDASolve succeeded by reaching the specified stopping point. */
479 case IDA_ROOT_RETURN: /* IDASolve succeeded and found one or more roots. */
480 break;
481 ✗ case IDA_WARNING:
482 ✗ warningStreamPrint(OMC_LOG_STDOUT, 0,
483 "##IDA## In function %s: Got some warning.",
484 functionName);
485 ✗ break;
486 ✗ case IDA_TOO_MUCH_WORK:
487 ✗ throwStreamPrint(NULL,
488 "##IDA## In function %s: The solver took mxstep internal "
489 "steps but could not reach tout.",
490 functionName);
491 break;
492 ✗ case IDA_TOO_MUCH_ACC:
493 ✗ throwStreamPrint(NULL,
494 "##IDA## In function %s: The solver could not satisfy the "
495 "accuracy demanded by the user for some internal step.",
496 functionName);
497 break;
498 ✗ case IDA_ERR_FAIL:
499 ✗ throwStreamPrint(
500 NULL,
501 "##IDA## In function %s: Error test failures occurred too many times "
502 "during one internal time step or minimum step size was reached.",
503 functionName);
504 break;
505 ✗ case IDA_CONV_FAIL:
506 ✗ throwStreamPrint(
507 NULL,
508 "##IDA## In function %s: Convergence test failures occurred too many "
509 "times during one internal time step or minimum step size was reached.",
510 functionName);
511 break;
512 ✗ case IDA_LINIT_FAIL:
513 ✗ throwStreamPrint(NULL,
514 "##IDA## In function %s: The linear solver's "
515 "initialization function failed.",
516 functionName);
517 break;
518 ✗ case IDA_LSETUP_FAIL:
519 ✗ throwStreamPrint(NULL,
520 "##IDA## In function %s: The linear solver's setup "
521 "function failed in an unrecoverable manner.",
522 functionName);
523 break;
524 ✗ case IDA_LSOLVE_FAIL:
525 ✗ throwStreamPrint(NULL,
526 "##IDA## In function %s: The linear solver's solve "
527 "function failed in an unrecoverable manner.",
528 functionName);
529 break;
530 ✗ case IDA_RES_FAIL:
531 ✗ throwStreamPrint(NULL,
532 "##IDA## In function %s: The user-provided residual "
533 "function failed in an unrecoverable manner.",
534 functionName);
535 break;
536 ✗ case IDA_REP_RES_ERR:
537 ✗ throwStreamPrint(NULL,
538 "##IDA## In function %s: The user-provided residual "
539 "function repeatedly returned a recoverable error flag, "
540 "but the solver was unable to recover.",
541 functionName);
542 break;
543 ✗ case IDA_RTFUNC_FAIL:
544 ✗ throwStreamPrint(NULL,
545 "##IDA## In function %s: The rootfinding function failed "
546 "in an unrecoverable manner.",
547 functionName);
548 break;
549 ✗ case IDA_CONSTR_FAIL:
550 ✗ throwStreamPrint(NULL,
551 "##IDA## In function %s: The inequality constraints were "
552 "violated and the solver was unable to recover.",
553 functionName);
554 break;
555 ✗ case IDA_FIRST_RES_FAIL:
556 ✗ throwStreamPrint(NULL,
557 "##IDA## In function %s: The user-provided residual "
558 "function failed recoverably on the first call.",
559 functionName);
560 break;
561 ✗ case IDA_LINESEARCH_FAIL:
562 ✗ throwStreamPrint(NULL,
563 "##IDA## In function %s: The line search failed.",
564 functionName);
565 break;
566 ✗ case IDA_NO_RECOVERY:
567 ✗ throwStreamPrint(
568 NULL,
569 "##IDA## In function %s: The residual function, linear solver setup "
570 "function, or linear solver solve function had a recoverable failure, "
571 "but IDACalcIC could not recover.",
572 functionName);
573 break;
574 ✗ case IDA_NLS_INIT_FAIL:
575 ✗ throwStreamPrint(NULL,
576 "##IDA## In function %s: The nonlinear solver's init routine failed.",
577 functionName);
578 break;
579 ✗ case IDA_NLS_SETUP_FAIL:
580 ✗ throwStreamPrint(NULL,
581 "##IDA## In function %s: The nonlinear solver's setup routine failed.",
582 functionName);
583 break;
584 ✗ case IDA_NLS_FAIL:
585 ✗ throwStreamPrint(NULL,
586 "##IDA## In function %s: IDA_NLS_FAIL.",
587 functionName);
588 break;
589 ✗ case IDA_MEM_NULL:
590 ✗ throwStreamPrint(NULL,
591 "##IDA## In function %s: The ida_mem argument was NULL.",
592 functionName);
593 break;
594 ✗ case IDA_MEM_FAIL:
595 ✗ throwStreamPrint(NULL,
596 "##IDA## In function %s: A memory allocation failed.",
597 functionName);
598 break;
599 ✗ case IDA_ILL_INPUT:
600 ✗ throwStreamPrint(NULL,
601 "##IDA## In function %s: One of the function inputs is illegal.",
602 functionName);
603 break;
604 ✗ case IDA_NO_MALLOC:
605 ✗ throwStreamPrint(NULL,
606 "##IDA## In function %s: The ida memory was not allocated by a call to IDAInit.",
607 functionName);
608 break;
609 ✗ case IDA_BAD_EWT:
610 ✗ throwStreamPrint(NULL,
611 "##IDA## In function %s: Zero value of some error weight component.",
612 functionName);
613 break;
614 ✗ case IDA_BAD_K:
615 ✗ throwStreamPrint(NULL,
616 "##IDA## In function %s: The k-th derivative is not available.",
617 functionName);
618 break;
619 ✗ case IDA_BAD_T:
620 ✗ throwStreamPrint(NULL,
621 "##IDA## In function %s: The time t is outside the last step taken.",
622 functionName);
623 break;
624 ✗ case IDA_BAD_DKY:
625 ✗ throwStreamPrint(NULL,
626 "##IDA## In function %s: The vector argument where derivative should be stored is NULL.",
627 functionName);
628 break;
629 ✗ case IDA_NO_QUAD:
630 ✗ throwStreamPrint(NULL,
631 "##IDA## In function %s: Quadratures were not initialized.",
632 functionName);
633 break;
634 ✗ case IDA_QRHS_FAIL:
635 ✗ throwStreamPrint(NULL,
636 "##IDA## In function %s: The user-provided right-hand side function for quadratures "
637 "failed in an unrecoverable manner.",
638 functionName);
639 break;
640 ✗ case IDA_FIRST_QRHS_ERR:
641 ✗ throwStreamPrint(NULL,
642 "##IDA## In function %s: The user-provided right-hand side function for quadratures "
643 "failed in an unrecoverable manner on the first call.",
644 functionName);
645 break;
646 ✗ case IDA_REP_QRHS_ERR:
647 ✗ throwStreamPrint(NULL,
648 "##IDA## In function %s: The user-provided right-hand side repeatedly returned "
649 "a recoverable error flag, but the solver was unable to recover.",
650 functionName);
651 break;
652 ✗ case IDA_NO_SENS:
653 ✗ throwStreamPrint(NULL,
654 "##IDA## In function %s: Sensitivities were not initialized.",
655 functionName);
656 break;
657 ✗ case IDA_SRES_FAIL:
658 ✗ throwStreamPrint(NULL,
659 "##IDA## In function %s: The user-provided sensitivity residual function failed "
660 "in an unrecoverable manner.",
661 functionName);
662 break;
663 ✗ case IDA_REP_SRES_ERR:
664 ✗ throwStreamPrint(NULL,
665 "##IDA## In function %s: The user-provided sensitivity residual function repeatedly "
666 "returned a recoverable error flag, but the solver was unable to recover.",
667 functionName);
668 break;
669 ✗ case IDA_BAD_IS:
670 ✗ throwStreamPrint(NULL,
671 "##IDA## In function %s: The sensitivity identifier is not valid.",
672 functionName);
673 break;
674 ✗ case IDA_NO_QUADSENS:
675 ✗ throwStreamPrint(NULL,
676 "##IDA## In function %s: Sensitivity-dependent quadratures were not initialized.",
677 functionName);
678 break;
679 ✗ case IDA_QSRHS_FAIL:
680 ✗ throwStreamPrint(NULL,
681 "##IDA## In function %s: The user-provided sensitivity-dependent quadrature "
682 "righthand side function failed in an unrecoverable manner.",
683 functionName);
684 break;
685 ✗ case IDA_FIRST_QSRHS_ERR:
686 ✗ throwStreamPrint(NULL,
687 "##IDA## In function %s: The user-provided sensitivity-dependent quadrature "
688 "righthand side function failed in an unrecoverable manner on the first call.",
689 functionName);
690 break;
691 ✗ case IDA_REP_QSRHS_ERR:
692 ✗ throwStreamPrint(NULL,
693 "##IDA## In function %s: The user-provided sensitivity-dependent quadrature "
694 "righthand side repeatedly returned a recoverable error flag, but the solver "
695 "was unable to recover.",
696 functionName);
697 break;
698 ✗ default:
699 ✗ throwStreamPrint(NULL,
700 "##IDA## In function %s: Error with flag %i.",
701 functionName, flag);
702 }
703 ✗ }
704
705 /**
706 * @brief Checks given IDALS flag and reports potential error.
707 *
708 * @param flag Return value of Kinsol routine.
709 * @param functionName Name of IDALS function that returned the flag.
710 */
711 ✗ static void checkReturnFlag_IDALS(int flag, const char *functionName) {
712 ✗ switch (flag) {
713 case IDALS_SUCCESS:
714 break;
715 ✗ case IDALS_MEM_NULL:
716 ✗ throwStreamPrint(NULL,
717 "##IDALS## In function %s: The ida_mem argument was NULL.",
718 functionName);
719 break;
720 ✗ case IDALS_LMEM_NULL:
721 ✗ throwStreamPrint(NULL,
722 "##IDALS## In function %s: The IDALS linear solver has "
723 "not been initialized.",
724 functionName);
725 break;
726 ✗ case IDALS_ILL_INPUT:
727 ✗ throwStreamPrint(NULL,
728 "##IDALS## In function %s: The IDALS solver is not "
729 "compatible with the current NVECTOR module.",
730 functionName);
731 break;
732 ✗ case IDALS_MEM_FAIL:
733 ✗ throwStreamPrint(
734 NULL, "##IDALS## In function %s: A memory allocation request failed.",
735 functionName);
736 break;
737 ✗ case IDALS_PMEM_NULL:
738 ✗ throwStreamPrint(NULL,
739 "##IDALS## In function %s: The preconditioner module has "
740 "not been initialized.",
741 functionName);
742 break;
743 ✗ case IDALS_JACFUNC_UNRECVR:
744 ✗ throwStreamPrint(NULL,
745 "##IDALS## In function %s: The Jacobian function failed "
746 "in an unrecoverable manner.",
747 functionName);
748 break;
749 ✗ case IDALS_JACFUNC_RECVR:
750 ✗ throwStreamPrint(NULL,
751 "##IDALS## In function %s: The Jacobian function had a "
752 "recoverable error.",
753 functionName);
754 break;
755 ✗ case IDALS_SUNMAT_FAIL:
756 ✗ throwStreamPrint(NULL,
757 "##IDALS## In function %s: An error occurred with the "
758 "current SUNMATRIX module.",
759 functionName);
760 break;
761 ✗ case IDALS_SUNLS_FAIL:
762 ✗ throwStreamPrint(NULL,
763 "##IDALS## In function %s: An error occurred with the "
764 "current SUNLINSOL module.",
765 functionName);
766 break;
767 ✗ default:
768 ✗ throwStreamPrint(NULL, "##IDALS## In function %s: Error with flag %i.",
769 functionName, flag);
770 }
771 ✗ }
772
773 /**
774 * @brief Checks given SUNLS flag and reports potential error.
775 *
776 * @param flag Return value of SUNLS routine.
777 * @param functionName Name of SUNLS function that returned the flag.
778 */
779 ✗ static void checkReturnFlag_SUNLS(SUNErrCode flag, const char *functionName) {
780 ✗ if (flag == SUN_SUCCESS) {
781 ✗ return;
782 }
783 ✗ throwStreamPrint(NULL, "##SUNLS## In function %s: %s (SUNErrCode %i).",
784 functionName, SUNGetErrMsg(flag), flag);
785 }
786
787 /**
788 * @brief Checks given SUNMatrix flag and reports potential error.
789 *
790 * SUNMatrix operations return a generic SUNErrCode, so let SUNDIALS spell the error out for us.
791 *
792 * @param flag Return value of SUNMatrix routine.
793 * @param functionName Name of SUNMatrix function that returned the flag.
794 */
795 ✗ static void checkReturnFlag_SUNMatrix(SUNErrCode flag, const char *functionName) {
796 ✗ if (flag == SUN_SUCCESS) {
797 ✗ return;
798 }
799 ✗ throwStreamPrint(NULL, "##SUNMatrix## In function %s: %s (SUNErrCode %i).",
800 functionName, SUNGetErrMsg(flag), flag);
801 }
802
803 /**
804 * @brief Debug print function for CSC SunMatrix
805 *
806 * @param A CSC SUNMatrix
807 * @param name Name of matrix A
808 * @param logLevel Stream to print output to
809 */
810 ✗ void sundialsPrintSparseMatrix(SUNMatrix A, const char* name, const int logLevel) {
811
812 int i;
813 long int columns, rows, nnz, np;
814 int lengthData, lengthIndexptrs;
815
816 double* data;
817 sunindextype* indexvals;
818 sunindextype* indexptrs;
819
820 ✗ assertStreamPrint(NULL, NULL != SM_DATA_S(A), "matrix data is NULL pointer");
821
822 ✗ if (SM_SPARSETYPE_S(A) != SUN_CSC_MAT) {
823 ✗ errorStreamPrint(OMC_LOG_STDOUT, 0,
824 "In function sundialsPrintSparseMatrix: Wrong sparse format "
825 "of SUNMatrix A%s.", name);
826 }
827
828 ✗ if (OMC_ACTIVE_STREAM(logLevel)) {
829 ✗ nnz = SUNSparseMatrix_NNZ(A);
830 ✗ np = SM_NP_S(A);
831 ✗ columns = SUNSparseMatrix_Columns(A);
832 ✗ rows = SUNSparseMatrix_Rows(A);
833
834 ✗ data = SM_DATA_S(A);
835 ✗ indexvals = SM_INDEXVALS_S(A);
836 ✗ indexptrs = SM_INDEXPTRS_S(A);
837
838 ✗ infoStreamPrint(logLevel, 1, "##SUNDIALS## Sparse Matrix %s", name);
839 ✗ infoStreamPrint(logLevel, 0, "Columns: N=%li, Rows: M=%li, CSC matrix, NNZ: %li, NP: %li", columns, rows, nnz, np);
840
841 /* Print data array */
842 ✗ lengthData = indexptrs[SUNSparseMatrix_NP(A)];
843
844 const int tmpBuffSize = 20;
845 ✗ const int bufferSize = fmax(1,lengthData)*fmax(1,columns);
846 ✗ char *buffer = (char*)malloc(sizeof(char)*bufferSize*tmpBuffSize);
847 ✗ char *tmpBuffer = (char*)malloc(sizeof(char)*tmpBuffSize);
848 ✗ buffer[0] = 0;
849 ✗ for (i=0; i<lengthData-1; i++) {
850 ✗ snprintf(tmpBuffer, tmpBuffSize, "%10g, ", data[i]);
851 strncat(buffer, tmpBuffer, tmpBuffSize);
852 }
853 ✗ snprintf(tmpBuffer, tmpBuffSize, "%10g", data[lengthData-1]);
854 strncat(buffer, tmpBuffer, tmpBuffSize);
855 ✗ infoStreamPrint(logLevel, 0, "data = {%s}", buffer);
856
857 /* Print indexvals array */
858 ✗ buffer[0] = 0;
859 ✗ for (i=0; i<lengthData-1; i++) {
860 ✗ snprintf(tmpBuffer, tmpBuffSize, OMC_INT_FORMAT ", ", indexvals[i]);
861 strncat(buffer, tmpBuffer, tmpBuffSize);
862 }
863 ✗ snprintf(tmpBuffer, tmpBuffSize, OMC_INT_FORMAT, indexvals[lengthData-1]);
864 strncat(buffer, tmpBuffer, tmpBuffSize);
865 ✗ infoStreamPrint(logLevel, 0, "indexvals = {%s}", buffer);
866
867 /* Print indexptrs array */
868 ✗ buffer[0] = 0;
869 ✗ for (i=0; i<SUNSparseMatrix_NP(A); i++) {
870 ✗ snprintf(tmpBuffer, tmpBuffSize, OMC_INT_FORMAT ", ", indexptrs[i]);
871 strncat(buffer, tmpBuffer, tmpBuffSize);
872 }
873 ✗ snprintf(tmpBuffer, tmpBuffSize, OMC_INT_FORMAT, indexptrs[SUNSparseMatrix_NP(A)]);
874 strncat(buffer, tmpBuffer, tmpBuffSize);
875 ✗ infoStreamPrint(logLevel, 0, "indexvals = {%s}", buffer);
876
877 ✗ messageClose(logLevel);
878 ✗ free(buffer);
879 ✗ free(tmpBuffer);
880 }
881 ✗ }
882
883 /**
884 * @brief Error handler function given to KINSOL.
885 *
886 * @param errorCode Error code from KINSOL
887 * @param module Name of the KINSOL module reporting the error.
888 * @param function Name of the function in which the error occurred.
889 * @param msg Error Message.
890 * @param userData Pointer to user data given with KINSetUserData.
891 */
892 ✗ void kinsolErrorHandlerFunction(int line, const char *func, const char *file,
893 const char *msg, SUNErrCode err_code,
894 void *err_user_data, SUNContext sunctx) {
895 /* Variables */
896 NLS_KINSOL_DATA* kinsolData;
897 DATA* data;
898 NONLINEAR_SYSTEM_DATA* nlsData;
899 long eqSystemNumber = -1;
900
901 UNUSED(sunctx); /* Disables compiler warning */
902
903 ✗ if (err_user_data != NULL) {
904 kinsolData = (NLS_KINSOL_DATA *)err_user_data;
905 ✗ data = kinsolData->userData->data;
906 ✗ nlsData = kinsolData->userData->nlsData;
907 ✗ if (nlsData) {
908 ✗ eqSystemNumber = nlsData->equationIndex;
909 }
910 }
911
912 ✗ if (OMC_ACTIVE_STREAM(OMC_LOG_NLS)) {
913 ✗ if (err_user_data != NULL && eqSystemNumber > 0) {
914 ✗ warningStreamPrint(
915 OMC_LOG_NLS, 1, "kinsol failed for system %d",
916 ✗ modelInfoGetEquation(&data->modelData->modelDataXml, eqSystemNumber).id);
917 } else {
918 ✗ warningStreamPrint(
919 OMC_LOG_NLS, 1, "kinsol failed");
920 }
921
922 ✗ warningStreamPrint(OMC_LOG_NLS, 0,
923 "[function] %s | [at] %s:%d | [error_code] %d",
924 func, file, line, err_code);
925 /* Package level codes (KIN_* and friends) are not SUNErrCodes, so
926 * SUNGetErrMsg() only makes sense when SUNDIALS did not supply a message. */
927 ✗ warningStreamPrint(OMC_LOG_NLS, 0, "%s", msg ? msg : SUNGetErrMsg(err_code));
928
929 ✗ messageCloseWarning(OMC_LOG_NLS);
930 }
931 ✗ }
932
933 #endif /* #ifndef OMC_FMI_RUNTIME */
934
935 #else
936
937 /**
938 * @brief Function not supported without WITH_SUNDIALS
939 *
940 * @param flag
941 * @param type
942 * @param functionName
943 */
944 void checkReturnFlag_SUNDIALS(int flag, int type, const char *functionName) {
945 throwStreamPrint(NULL, "No sundials/kinsol support activated.");
946 }
947
948
949 #endif /* WITH_SUNDIALS */
950