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 |