OMCompiler/SimulationRuntime/c/simulation/solver/linearSolverTotalPivot.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 nonlinear_solver.c | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <math.h> | ||
| 32 | #include <stdlib.h> | ||
| 33 | #include <string.h> /* memcpy */ | ||
| 34 | |||
| 35 | #include "../../simulation_data.h" | ||
| 36 | #include "../simulation_info_json.h" | ||
| 37 | #include "../jacobian_util.h" | ||
| 38 | #include "../../util/omc_error.h" | ||
| 39 | #include "omc_math.h" | ||
| 40 | #include "../../util/varinfo.h" | ||
| 41 | #include "model_help.h" | ||
| 42 | |||
| 43 | #include "linearSystem.h" | ||
| 44 | #include "linearSolverTotalPivot.h" | ||
| 45 | |||
| 46 | ✗ | void debugMatrixDoubleLS(int logName, char* matrixName, double* matrix, int n, int m) | |
| 47 | { | ||
| 48 | ✗ | if(OMC_ACTIVE_STREAM(logName)) | |
| 49 | { | ||
| 50 | int i, j; | ||
| 51 | int sparsity = 0; | ||
| 52 | ✗ | char *buffer = (char*)malloc(sizeof(char)*m*18); | |
| 53 | |||
| 54 | ✗ | infoStreamPrint(logName, 1, "%s [%dx%d-dim]", matrixName, n, m); | |
| 55 | ✗ | for(i=0; i<n;i++) | |
| 56 | { | ||
| 57 | char *p = buffer; | ||
| 58 | ✗ | for(j=0; j<m; j++) | |
| 59 | { | ||
| 60 | if (sparsity) | ||
| 61 | { | ||
| 62 | if (fabs(matrix[i + j*(m-1)])<1e-12) | ||
| 63 | p += sprintf(p, " 0"); | ||
| 64 | else | ||
| 65 | p += sprintf(p, " *"); | ||
| 66 | } | ||
| 67 | else | ||
| 68 | { | ||
| 69 | ✗ | p += sprintf(p, " %12.4g", matrix[i + j*(m-1)]); | |
| 70 | } | ||
| 71 | } | ||
| 72 | ✗ | infoStreamPrint(logName, 0, "%s", buffer); | |
| 73 | } | ||
| 74 | ✗ | messageClose(logName); | |
| 75 | ✗ | free(buffer); | |
| 76 | } | ||
| 77 | ✗ | } | |
| 78 | |||
| 79 | ✗ | void debugVectorDoubleLS(int logName, char* vectorName, double* vector, int n) | |
| 80 | { | ||
| 81 | ✗ | if(OMC_ACTIVE_STREAM(logName)) | |
| 82 | { | ||
| 83 | int i; | ||
| 84 | ✗ | char *buffer = (char*)malloc(sizeof(char)*n*22); | |
| 85 | |||
| 86 | ✗ | infoStreamPrint(logName, 1, "%s [%d-dim]", vectorName, n); | |
| 87 | { | ||
| 88 | char *p = buffer; | ||
| 89 | ✗ | if (vector[0]<-1e+300) | |
| 90 | ✗ | p += sprintf(p, " -INF"); | |
| 91 | ✗ | else if (vector[0]>1e+300) | |
| 92 | ✗ | p += sprintf(p, " +INF"); | |
| 93 | else | ||
| 94 | ✗ | p += sprintf(p, " %16.8g", vector[0]); | |
| 95 | ✗ | for(i=1; i<n;i++) | |
| 96 | { | ||
| 97 | ✗ | if (vector[i]<-1e+300) | |
| 98 | ✗ | p += sprintf(p, " -INF"); | |
| 99 | ✗ | else if (vector[i]>1e+300) | |
| 100 | ✗ | p += sprintf(p, " +INF"); | |
| 101 | else | ||
| 102 | ✗ | p += sprintf(p, " %16.8g", vector[i]); | |
| 103 | } | ||
| 104 | } | ||
| 105 | ✗ | infoStreamPrint(logName, 0, "%s", buffer); | |
| 106 | ✗ | free(buffer); | |
| 107 | ✗ | messageClose(logName); | |
| 108 | } | ||
| 109 | ✗ | } | |
| 110 | |||
| 111 | ✗ | void debugStringLS(int logName, char* message) | |
| 112 | { | ||
| 113 | ✗ | infoStreamPrint(logName, 0, "%s", message); | |
| 114 | ✗ | } | |
| 115 | |||
| 116 | ✗ | void debugIntLS(int logName, char* message, int value) | |
| 117 | { | ||
| 118 | ✗ | infoStreamPrint(logName, 1, "%s %d", message, value); | |
| 119 | ✗ | } | |
| 120 | |||
| 121 | ✗ | void vecMultScalingLS(int n, double *a, double *b, double *c) | |
| 122 | { | ||
| 123 | int i; | ||
| 124 | ✗ | for (i=0;i<n;i++) | |
| 125 | ✗ | c[i] = a[i]*fabs(b[i]); | |
| 126 | ✗ | } | |
| 127 | |||
| 128 | ✗ | void vecAddScalLS(int n, double *a, double *b, double s, double *c) | |
| 129 | { | ||
| 130 | int i; | ||
| 131 | ✗ | for (i=0;i<n;i++) | |
| 132 | ✗ | c[i] = a[i] + s*b[i]; | |
| 133 | ✗ | } | |
| 134 | |||
| 135 | ✗ | void vecAddLS(int n, double *a, double *b, double *c) | |
| 136 | { | ||
| 137 | int i; | ||
| 138 | ✗ | for (i=0;i<n;i++) | |
| 139 | ✗ | c[i] = a[i] + b[i]; | |
| 140 | ✗ | } | |
| 141 | |||
| 142 | ✗ | void vecCopyLS(int n, double *a, double *b) | |
| 143 | { | ||
| 144 | ✗ | memcpy(b, a, n*(sizeof(double))); | |
| 145 | ✗ | } | |
| 146 | |||
| 147 | ✗ | void vecConstLS(int n, double value, double *a) | |
| 148 | { | ||
| 149 | int i; | ||
| 150 | ✗ | for (i=0;i<n;i++) | |
| 151 | ✗ | a[i] = value; | |
| 152 | ✗ | } | |
| 153 | |||
| 154 | ✗ | void vecScalarMultLS(int n, double *a, double s, double *b) | |
| 155 | { | ||
| 156 | int i; | ||
| 157 | ✗ | for (i=0;i<n;i++) | |
| 158 | ✗ | b[i] = s*a[i]; | |
| 159 | ✗ | } | |
| 160 | |||
| 161 | ✗ | void getIndicesOfPivotElementLS(int *n, int *m, int *l, double* A, int *indRow, int *indCol, int *pRow, int *pCol, double *absMax) | |
| 162 | { | ||
| 163 | int i, j; | ||
| 164 | |||
| 165 | ✗ | *absMax = fabs(A[indRow[*l] + indCol[*l]* *n]); | |
| 166 | ✗ | *pCol = *l; | |
| 167 | ✗ | *pRow = *l; | |
| 168 | ✗ | for (i = *l; i < *n; i++) { | |
| 169 | ✗ | for (j = *l; j < *m; j++) { | |
| 170 | ✗ | if (fabs(A[indRow[i] + indCol[j]* *n]) > *absMax) { | |
| 171 | ✗ | *absMax = fabs(A[indRow[i] + indCol[j]* *n]); | |
| 172 | ✗ | *pCol = j; | |
| 173 | ✗ | *pRow = i; | |
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | ✗ | } | |
| 178 | |||
| 179 | /** | ||
| 180 | * @brief Linear solver for A*x = b based on a total pivot search. | ||
| 181 | * | ||
| 182 | * \author bbachmann | ||
| 183 | * | ||
| 184 | * @param data Simulation data. | ||
| 185 | * @param n Size of matrix a | ||
| 186 | * @param x On return: Solution dim n+1, last column is 1 for solvable systems. | ||
| 187 | * @param Ab Matrix A|b: first n columns are matrix A, last column is -b | ||
| 188 | * @param indRow Work array for row indices, used for coloring. | ||
| 189 | * @param indCol Work array for column indices, used for coloring. | ||
| 190 | * @param rank On return: Rank of matrix A|b. | ||
| 191 | * @return int Return 0 on success, -1 if system is under-determined. | ||
| 192 | */ | ||
| 193 | ✗ | int solveSystemWithTotalPivotSearchLS(DATA* data, int n, double* x, double* Ab, int* indRow, int* indCol, int *rank) | |
| 194 | { | ||
| 195 | ✗ | int i, k, j, l, m=n+1, nrsh=1, singular=0; | |
| 196 | int pCol, pRow; | ||
| 197 | double hValue; | ||
| 198 | double hInt; | ||
| 199 | double absMax; | ||
| 200 | int r,s; | ||
| 201 | int permutation = 1; | ||
| 202 | |||
| 203 | /* assume full rank of matrix A|b [n x (n+1)] */ | ||
| 204 | ✗ | *rank = n; | |
| 205 | |||
| 206 | ✗ | for (i=0; i<n; i++) { | |
| 207 | ✗ | indRow[i] = i; | |
| 208 | } | ||
| 209 | ✗ | for (i=0; i<m; i++) { | |
| 210 | ✗ | indCol[i] = i; | |
| 211 | } | ||
| 212 | |||
| 213 | ✗ | for (i = 0; i < n; i++) { | |
| 214 | ✗ | getIndicesOfPivotElementLS(&n, &n, &i, Ab, indRow, indCol, &pRow, &pCol, &absMax); | |
| 215 | /* this criteria should be evaluated and may be improved in future */ | ||
| 216 | ✗ | if (absMax < DBL_EPSILON) { | |
| 217 | ✗ | *rank = i; | |
| 218 | ✗ | if (data->simulationInfo->initial) { | |
| 219 | ✗ | warningStreamPrint(OMC_LOG_LS, 1, "Total Pivot: Matrix (nearly) singular at initialization."); | |
| 220 | } else { | ||
| 221 | ✗ | warningStreamPrint(OMC_LOG_LS, 1, "Total Pivot: Matrix (nearly) singular at time %f.", data->localData[0]->timeValue); | |
| 222 | } | ||
| 223 | ✗ | warningStreamPrint(OMC_LOG_LS, 0, "Continuing anyway. For more information please use -lv %s.", OMC_LOG_STREAM_NAME[OMC_LOG_LS]); | |
| 224 | ✗ | messageCloseWarning(OMC_LOG_LS); | |
| 225 | ✗ | infoStreamPrint(OMC_LOG_LS, 0, "rank = %u", *rank); | |
| 226 | ✗ | break; | |
| 227 | } | ||
| 228 | /* swap row indices */ | ||
| 229 | ✗ | if (pRow!=i) { | |
| 230 | ✗ | hInt = indRow[i]; | |
| 231 | ✗ | indRow[i] = indRow[pRow]; | |
| 232 | ✗ | indRow[pRow] = hInt; | |
| 233 | } | ||
| 234 | /* swap column indices */ | ||
| 235 | ✗ | if (pCol!=i) { | |
| 236 | ✗ | hInt = indCol[i]; | |
| 237 | ✗ | indCol[i] = indCol[pCol]; | |
| 238 | ✗ | indCol[pCol] = hInt; | |
| 239 | } | ||
| 240 | |||
| 241 | /* Gauss elimination of row indRow[i] */ | ||
| 242 | ✗ | for (k=i+1; k<n; k++) { | |
| 243 | ✗ | hValue = -Ab[indRow[k] + indCol[i]*n]/Ab[indRow[i] + indCol[i]*n]; | |
| 244 | ✗ | for (j=i+1; j<m; j++) { | |
| 245 | ✗ | Ab[indRow[k] + indCol[j]*n] = Ab[indRow[k] + indCol[j]*n] + hValue*Ab[indRow[i] + indCol[j]*n]; | |
| 246 | } | ||
| 247 | ✗ | Ab[indRow[k] + indCol[i]*n] = 0; | |
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | ✗ | debugMatrixDoubleLS(OMC_LOG_LS_V,"LGS: matrix Ab manipulated",Ab, n, n+1); | |
| 252 | /* solve even singular matrix */ | ||
| 253 | ✗ | for (i=n-1;i>=0; i--) { | |
| 254 | ✗ | if (i>=*rank) { | |
| 255 | /* this criteria should be evaluated and may be improved in future */ | ||
| 256 | ✗ | if (fabs(Ab[indRow[i] + n*n])>1e-12) { | |
| 257 | ✗ | warningStreamPrint(OMC_LOG_LS, 0, "under-determined linear system not solvable!"); | |
| 258 | ✗ | return -1; | |
| 259 | } else { | ||
| 260 | ✗ | x[indCol[i]] = 0.0; | |
| 261 | } | ||
| 262 | } else { | ||
| 263 | ✗ | x[indCol[i]] = -Ab[indRow[i] + n*n]; | |
| 264 | ✗ | for (j=n-1; j>i; j--) { | |
| 265 | ✗ | x[indCol[i]] = x[indCol[i]] - Ab[indRow[i] + indCol[j]*n]*x[indCol[j]]; | |
| 266 | } | ||
| 267 | ✗ | x[indCol[i]]=x[indCol[i]]/Ab[indRow[i] + indCol[i]*n]; | |
| 268 | } | ||
| 269 | } | ||
| 270 | ✗ | x[n]=1.0; | |
| 271 | ✗ | debugVectorDoubleLS(OMC_LOG_LS_V,"LGS: solution vector x",x, n+1); | |
| 272 | |||
| 273 | ✗ | return 0; | |
| 274 | } | ||
| 275 | |||
| 276 | /*! \fn allocate memory for linear system solver totalpivot | ||
| 277 | * | ||
| 278 | * \author bbachmann | ||
| 279 | */ | ||
| 280 | ✗ | int allocateTotalPivotData(int size, void** voiddata) | |
| 281 | { | ||
| 282 | ✗ | DATA_TOTALPIVOT* data = (DATA_TOTALPIVOT*) malloc(sizeof(DATA_TOTALPIVOT)); | |
| 283 | |||
| 284 | /* memory for linear system */ | ||
| 285 | ✗ | data->Ab = (double*) calloc((size*(size+1)),sizeof(double)); | |
| 286 | ✗ | data->b = (double*) malloc(size*sizeof(double)); | |
| 287 | ✗ | data->x = (double*) calloc(size+1,sizeof(double)); | |
| 288 | |||
| 289 | /* used for pivot strategy */ | ||
| 290 | ✗ | data->indRow =(int*) calloc(size,sizeof(int)); | |
| 291 | ✗ | data->indCol =(int*) calloc(size+1,sizeof(int)); | |
| 292 | |||
| 293 | ✗ | voiddata[1] = (void*)data; | |
| 294 | ✗ | return 0; | |
| 295 | } | ||
| 296 | |||
| 297 | /*! \fn free memory for nonlinear solver totalpivot | ||
| 298 | * | ||
| 299 | * \author bbachmann | ||
| 300 | */ | ||
| 301 | ✗ | int freeTotalPivotData(void** voiddata) | |
| 302 | { | ||
| 303 | ✗ | DATA_TOTALPIVOT* data = (DATA_TOTALPIVOT*) voiddata[1]; | |
| 304 | |||
| 305 | /* memory for linear system */ | ||
| 306 | ✗ | free(data->Ab); | |
| 307 | ✗ | free(data->b); | |
| 308 | ✗ | free(data->x); | |
| 309 | |||
| 310 | /* used for pivot strategy */ | ||
| 311 | ✗ | free(data->indRow); | |
| 312 | ✗ | free(data->indCol); | |
| 313 | |||
| 314 | ✗ | free(voiddata[1]); | |
| 315 | ✗ | voiddata[1] = NULL; | |
| 316 | |||
| 317 | ✗ | return 0; | |
| 318 | } | ||
| 319 | |||
| 320 | /*! \fn getAnalyticalJacobian | ||
| 321 | * | ||
| 322 | * function calculates analytical jacobian | ||
| 323 | * | ||
| 324 | * \param [ref] [data] | ||
| 325 | * \param [out] [jac] | ||
| 326 | * | ||
| 327 | * \author wbraun | ||
| 328 | * | ||
| 329 | */ | ||
| 330 | ✗ | void getAnalyticalJacobianTotalPivot(DATA* data, threadData_t *threadData, LINEAR_SYSTEM_DATA* systemData, modelica_real* jac) | |
| 331 | { | ||
| 332 | ✗ | JACOBIAN* jacobian = systemData->jacobian; | |
| 333 | ✗ | JACOBIAN* parentJacobian = systemData->parentJacobian; | |
| 334 | |||
| 335 | /* call generic dense Jacobian */ | ||
| 336 | ✗ | evalJacobian(data, threadData, jacobian, parentJacobian, jac, TRUE); | |
| 337 | ✗ | } | |
| 338 | |||
| 339 | /*! \fn wrapper_fvec_hybrd for the residual Function | ||
| 340 | * calls for the subroutine fcn(n, x, fvec, iflag, data) | ||
| 341 | * | ||
| 342 | * | ||
| 343 | */ | ||
| 344 | static int wrapper_fvec_totalpivot(double* x, double* f, RESIDUAL_USERDATA* resUserData, int sysNumber) | ||
| 345 | { | ||
| 346 | int currentSys = sysNumber; | ||
| 347 | ✗ | int iflag = 0; | |
| 348 | |||
| 349 | ✗ | resUserData->data->simulationInfo->linearSystemData[currentSys].residualFunc(resUserData, x, f, &iflag); | |
| 350 | ✗ | return 0; | |
| 351 | } | ||
| 352 | |||
| 353 | /** | ||
| 354 | * @brief Solve linear system with total pivot method. | ||
| 355 | * | ||
| 356 | * \author bbachmann | ||
| 357 | * | ||
| 358 | * @param data Runtime data struct. | ||
| 359 | * @param threadData Thread data for error handling. | ||
| 360 | * @param sysNumber Index of the corresponding non-linear system. | ||
| 361 | * @param aux_x Work array with old values of x. Will be overwritten with solution. | ||
| 362 | * @return int Return 1 on success and 0 on failure. | ||
| 363 | */ | ||
| 364 | ✗ | int solveTotalPivot(DATA *data, threadData_t *threadData, int sysNumber, double* aux_x) | |
| 365 | { | ||
| 366 | ✗ | RESIDUAL_USERDATA resUserData = {.data=data, .threadData=threadData, .solverData=NULL}; | |
| 367 | int i, j; | ||
| 368 | ✗ | LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); | |
| 369 | ✗ | DATA_TOTALPIVOT* solverData = (DATA_TOTALPIVOT*) systemData->solverData[1]; | |
| 370 | |||
| 371 | ✗ | int n = systemData->size, status; | |
| 372 | double fdeps = 1e-8; | ||
| 373 | double xTol = 1e-8; | ||
| 374 | ✗ | int eqSystemNumber = systemData->equationIndex; | |
| 375 | ✗ | int indexes[2] = {1,eqSystemNumber}; | |
| 376 | int rank; | ||
| 377 | _omc_scalar residualNorm = 0; | ||
| 378 | |||
| 379 | /* We are given the number of the linear system. | ||
| 380 | * We want to look it up among all equations. */ | ||
| 381 | /* int eqSystemNumber = systemData->equationIndex; */ | ||
| 382 | int success = 1; | ||
| 383 | double tmpJacEvalTime; | ||
| 384 | |||
| 385 | ✗ | infoStreamPrintWithEquationIndexes(OMC_LOG_LS, omc_dummyFileInfo, 0, indexes, | |
| 386 | "Start solving Linear System %d (size %d) at time %g with Total Pivot Solver", | ||
| 387 | ✗ | eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); | |
| 388 | |||
| 389 | ✗ | debugVectorDoubleLS(OMC_LOG_LS_V,"SCALING",systemData->nominal,n); | |
| 390 | ✗ | debugVectorDoubleLS(OMC_LOG_LS_V,"Old VALUES",aux_x,n); | |
| 391 | |||
| 392 | ✗ | rt_ext_tp_tick(&(solverData->timeClock)); | |
| 393 | ✗ | if (0 == systemData->method) { | |
| 394 | |||
| 395 | /* reset matrix A */ | ||
| 396 | ✗ | vecConstLS(n*n, 0.0, systemData->A); | |
| 397 | /* update matrix A -> first n columns of matrix Ab*/ | ||
| 398 | ✗ | systemData->setA(data, threadData, systemData); | |
| 399 | ✗ | vecCopyLS(n*n, systemData->A, solverData->Ab); | |
| 400 | |||
| 401 | /* update vector b (rhs) -> -b is last column of matrix Ab*/ | ||
| 402 | ✗ | rt_ext_tp_tick(&(solverData->timeClock)); | |
| 403 | ✗ | systemData->setb(data, threadData, systemData); | |
| 404 | ✗ | vecScalarMultLS(n, systemData->b, -1.0, solverData->Ab + n*n); | |
| 405 | } else { | ||
| 406 | |||
| 407 | /* calculate jacobian -> first n columns of matrix Ab*/ | ||
| 408 | ✗ | if(systemData->jacobianIndex != -1){ | |
| 409 | ✗ | getAnalyticalJacobianTotalPivot(data, threadData, systemData, solverData->Ab); | |
| 410 | } else { | ||
| 411 | assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); | ||
| 412 | } | ||
| 413 | /* calculate vector b (rhs) -> -b is last column of matrix Ab */ | ||
| 414 | ✗ | wrapper_fvec_totalpivot(aux_x, solverData->Ab + n*n, &resUserData, sysNumber); | |
| 415 | } | ||
| 416 | ✗ | tmpJacEvalTime = rt_ext_tp_tock(&(solverData->timeClock)); | |
| 417 | ✗ | systemData->jacobianTime += tmpJacEvalTime; | |
| 418 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 0, "### %f time to set Matrix A and vector b.", tmpJacEvalTime); | |
| 419 | ✗ | debugMatrixDoubleLS(OMC_LOG_LS_V,"LGS: matrix Ab",solverData->Ab, n, n+1); | |
| 420 | |||
| 421 | ✗ | rt_ext_tp_tick(&(solverData->timeClock)); | |
| 422 | ✗ | status = solveSystemWithTotalPivotSearchLS(data, n, solverData->x, solverData->Ab, solverData->indRow, solverData->indCol, &rank); | |
| 423 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); | |
| 424 | |||
| 425 | ✗ | if (status != 0) { | |
| 426 | ✗ | warningStreamPrint(OMC_LOG_STDOUT, 0, "Error solving linear system of equations (no. %d) at time %f.", (int)systemData->equationIndex, data->localData[0]->timeValue); | |
| 427 | success = 0; | ||
| 428 | } else { | ||
| 429 | ✗ | debugVectorDoubleLS(OMC_LOG_LS_V, "SOLUTION:", solverData->x, n+1); | |
| 430 | ✗ | if (1 == systemData->method) { | |
| 431 | /* add the solution to old solution vector*/ | ||
| 432 | ✗ | vecAddLS(n, aux_x, solverData->x, aux_x); | |
| 433 | ✗ | wrapper_fvec_totalpivot(aux_x, solverData->b, &resUserData, sysNumber); | |
| 434 | } else { | ||
| 435 | /* take the solution */ | ||
| 436 | ✗ | vecCopyLS(n, solverData->x, aux_x); | |
| 437 | } | ||
| 438 | |||
| 439 | ✗ | if (OMC_ACTIVE_STREAM(OMC_LOG_LS_V)) { | |
| 440 | ✗ | if (1 == systemData->method) { | |
| 441 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 1, "Residual Norm %.15g of solution x:", residualNorm); | |
| 442 | } else { | ||
| 443 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 1, "Solution x:"); | |
| 444 | } | ||
| 445 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); | |
| 446 | ✗ | for(i=0; i<systemData->size; ++i) | |
| 447 | { | ||
| 448 | ✗ | infoStreamPrint(OMC_LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], aux_x[i]); | |
| 449 | } | ||
| 450 | ✗ | messageClose(OMC_LOG_LS_V); | |
| 451 | } | ||
| 452 | } | ||
| 453 | ✗ | return success; | |
| 454 | } | ||
| 455 |