int nlsKinsolSolve(DATA *data, threadData_t *threadData, int sysNumber) { NONLINEAR_SYSTEM_DATA *nlsData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); NLS_KINSOL_DATA *kinsolData = (NLS_KINSOL_DATA*)nlsData->solverData; long eqSystemNumber = nlsData->equationIndex; int indexes[2] = {1,eqSystemNumber}; int flag, i; long nFEval; int success = 0; int retry = 0; double *xStart = NV_DATA_S(kinsolData->initialGuess); double *xScaling = NV_DATA_S(kinsolData->xScale); double *fScaling = NV_DATA_S(kinsolData->fScale); double fNormValue; /* set user data */ kinsolData->userData.data = data; kinsolData->userData.threadData = threadData; kinsolData->userData.sysNumber = sysNumber; /* reset configuration settings */ nlsKinsolConfigSetup(kinsolData); infoStreamPrint(LOG_NLS, 0, "------------------------------------------------------"); infoStreamPrintWithEquationIndexes(LOG_NLS, 1, indexes, "Start solving non-linear system >>%ld<< using Kinsol solver at time %g", eqSystemNumber, data->localData[0]->timeValue); nlsKinsolResetInitial(data, kinsolData, nlsData, INITIAL_EXTRAPOLATION); /* set x scaling */ nlsKinsolXScaling(data, kinsolData, nlsData, SCALING_NOMINALSTART); /* set f scaling */ _omc_fillVector(_omc_createVector(nlsData->size, fScaling), 1.); /* */ do{ /* dump configuration */ nlsKinsolConfigPrint(kinsolData, nlsData); flag = KINSol(kinsolData->kinsolMemory, /* KINSol memory block */ kinsolData->initialGuess, /* initial guess on input; solution vector */ kinsolData->kinsolStrategy, /* global strategy choice */ kinsolData->xScale, /* scaling vector, for the variable cc */ kinsolData->fScale); /* scaling vector for function values fval */ infoStreamPrint(LOG_NLS_V, 0, "KINSol finished with errorCode %d.", flag); /* check for errors */ if(flag < 0) { retry = nlsKinsolErrorHandler(flag, data, nlsData, kinsolData); } /* solution found */ if ((flag == KIN_SUCCESS) || (flag == KIN_INITIAL_GUESS_OK) || (flag == KIN_STEP_LT_STPTOL)) { success = 1; } kinsolData->retries++; /* write statistics */ KINGetNumNonlinSolvIters(kinsolData->kinsolMemory, &nFEval); nlsData->numberOfIterations += nFEval; nlsData->numberOfFEval += kinsolData->countResCalls; infoStreamPrint(LOG_NLS_V, 0, "Next try? success = %d, retry = %d, retries = %d = %s\n", success, retry, kinsolData->retries,!success && !(retry<1) && kinsolData->retries<RETRY_MAX ? "true" : "false" ); }while(!success && !(retry<0) && kinsolData->retries < RETRY_MAX); /* solution found */ if (success) { /* check if solution really solves the residuals */ nlsKinsolResiduals(kinsolData->initialGuess, kinsolData->fRes, &kinsolData->userData); fNormValue = N_VWL2Norm(kinsolData->fRes, kinsolData->fRes); infoStreamPrint(LOG_NLS, 0, "scaled Euclidean norm of F(u) = %e", fNormValue); if (FTOL_WITH_LESS_ACCURANCY<fNormValue) { warningStreamPrint(LOG_NLS, 0, "False positive solution. FNorm is too small."); success = 0; } else /* solved system for reuse linear solver information */ { kinsolData->solved = 1; } /* copy solution */ memcpy(nlsData->nlsx, xStart, nlsData->size*(sizeof(double))); /* dump solution */ if(ACTIVE_STREAM(LOG_NLS)) { infoStreamPrintWithEquationIndexes(LOG_NLS, 1, indexes, "solution for NLS %ld at t=%g", eqSystemNumber, kinsolData->userData.data->localData[0]->timeValue); for(i=0; i<nlsData->size; ++i) { infoStreamPrintWithEquationIndexes(LOG_NLS, 0, indexes, "[%d] %s = %g", i+1, modelInfoGetEquation(&kinsolData->userData.data->modelData->modelDataXml,eqSystemNumber).vars[i], nlsData->nlsx[i]); } messageClose(LOG_NLS); } } messageClose(LOG_NLS); return success; }
/*! \fn solve linear system with UmfPack method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * * author: kbalzereit, wbraun */ int solveUmfPack(DATA *data, int sysNumber) { LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo.linearSystemData[sysNumber]); DATA_UMFPACK* solverData = (DATA_UMFPACK*)systemData->solverData; int i, j, status = UMFPACK_OK, success = 0, ni=0, n = systemData->size, eqSystemNumber = systemData->equationIndex, indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with UMFPACK Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* set A matrix */ solverData->Ap[0] = 0; systemData->setA(data, systemData); solverData->Ap[solverData->n_row] = solverData->nnz; if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Matrix A"); printMatrixCSR(solverData->Ap, solverData->Ai, solverData->Ax, n); messageClose(LOG_LS_V); } /* set b vector */ systemData->setb(data, systemData); } else { solverData->Ap[0] = 0; /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1) { getAnalyticalJacobianUmfPack(data, sysNumber); } else { assertStreamPrint(data->threadData, 1, "jacobian function pointer is invalid" ); } solverData->Ap[solverData->n_row] = solverData->nnz; /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); wrapper_fvec_umfpack(solverData->work, systemData->b, data, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); if (ACTIVE_STREAM(LOG_LS_V)) { if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Old solution x:"); for(i = 0; i < solverData->n_row; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } infoStreamPrint(LOG_LS_V, 1, "Matrix A n_rows = %d", solverData->n_row); for (i=0; i<solverData->n_row; i++) { infoStreamPrint(LOG_LS_V, 0, "%d. Ap => %d -> %d", i, solverData->Ap[i], solverData->Ap[i+1]); for (j=solverData->Ap[i]; j<solverData->Ap[i+1]; j++) { infoStreamPrint(LOG_LS_V, 0, "A[%d,%d] = %f", i, solverData->Ai[j], solverData->Ax[j]); } } messageClose(LOG_LS_V); for (i=0; i<solverData->n_row; i++) infoStreamPrint(LOG_LS_V, 0, "b[%d] = %e", i, systemData->b[i]); } rt_ext_tp_tick(&(solverData->timeClock)); /* symbolic pre-ordering of A to reduce fill-in of L and U */ if (0 == solverData->numberSolving) { status = umfpack_di_symbolic(solverData->n_col, solverData->n_row, solverData->Ap, solverData->Ai, solverData->Ax, &(solverData->symbolic), solverData->control, solverData->info); } /* compute the LU factorization of A */ if (0 == status) { status = umfpack_di_numeric(solverData->Ap, solverData->Ai, solverData->Ax, solverData->symbolic, &(solverData->numeric), solverData->control, solverData->info); } if (0 == status) { if (1 == systemData->method) { status = umfpack_di_solve(UMFPACK_A, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } else { status = umfpack_di_solve(UMFPACK_Aat, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } } if (status == UMFPACK_OK) { success = 1; } else if (status == UMFPACK_WARNING_singular_matrix) { if (!solveSingularSystem(systemData)) { success = 1; } } infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); /* print solution */ if (1 == success) { if (1 == systemData->method) { /* take the solution */ for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += solverData->work[i]; /* update inner equations */ wrapper_fvec_umfpack(systemData->x, solverData->work, data, sysNumber); } else { /* the solution is automatically in x */ } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, status); } solverData->numberSolving += 1; return success; }
/*! \fn solve linear system with lapack method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * \author wbraun */ int solveLapack(DATA *data, int sysNumber) { int i, j, iflag = 1; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo.linearSystemData[sysNumber]); DATA_LAPACK* solverData = (DATA_LAPACK*)systemData->solverData; int success = 1; /* We are given the number of the linear system. * We want to look it up among all equations. */ int eqSystemNumber = systemData->equationIndex; int indexes[2] = {1,eqSystemNumber}; _omc_scalar residualNorm = 0; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Lapack Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); /* set data */ _omc_setVectorData(solverData->x, systemData->x); _omc_setVectorData(solverData->b, systemData->b); _omc_setMatrixData(solverData->A, systemData->A); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* reset matrix A */ memset(systemData->A, 0, (systemData->size)*(systemData->size)*sizeof(double)); /* update matrix A */ systemData->setA(data, systemData); /* update vector b (rhs) */ systemData->setb(data, systemData); } else { /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobianLapack(data, solverData->A->data, sysNumber); } else { assertStreamPrint(data->threadData, 1, "jacobian function pointer is invalid" ); } /* calculate vector b (rhs) */ _omc_copyVector(solverData->work, solverData->x); wrapper_fvec_lapack(solverData->work, solverData->b, &iflag, data, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); /* Log A*x=b */ if(ACTIVE_STREAM(LOG_LS_V)){ _omc_printVector(solverData->x, "Vector old x", LOG_LS_V); _omc_printMatrix(solverData->A, "Matrix A", LOG_LS_V); _omc_printVector(solverData->b, "Vector b", LOG_LS_V); } rt_ext_tp_tick(&(solverData->timeClock)); /* Solve system */ dgesv_((int*) &systemData->size, (int*) &solverData->nrhs, solverData->A->data, (int*) &systemData->size, solverData->ipiv, solverData->b->data, (int*) &systemData->size, &solverData->info); infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if(solverData->info < 0) { warningStreamPrint(LOG_LS, 0, "Error solving linear system of equations (no. %d) at time %f. Argument %d illegal.", (int)systemData->equationIndex, data->localData[0]->timeValue, (int)solverData->info); success = 0; } else if(solverData->info > 0) { warningStreamPrint(LOG_LS, 0, "Failed to solve linear system of equations (no. %d) at time %f, system is singular for U[%d, %d].", (int)systemData->equationIndex, data->localData[0]->timeValue, (int)solverData->info+1, (int)solverData->info+1); success = 0; /* debug output */ if (ACTIVE_STREAM(LOG_LS)){ _omc_printMatrix(solverData->A, "Matrix U", LOG_LS); _omc_printVector(solverData->b, "Output vector x", LOG_LS); } } if (1 == success){ if (1 == systemData->method){ /* take the solution */ solverData->x = _omc_addVectorVector(solverData->x, solverData->work, solverData->b); /* update inner equations */ wrapper_fvec_lapack(solverData->x, solverData->work, &iflag, data, sysNumber); residualNorm = _omc_euclideanVectorNorm(solverData->work); } else { /* take the solution */ _omc_copyVector(solverData->x, solverData->b); } if (ACTIVE_STREAM(LOG_LS_V)){ infoStreamPrint(LOG_LS_V, 1, "Residual Norm %f of solution x:", residualNorm); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) { infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); } messageClose(LOG_LS_V); } } return success; }
/*! \fn solve non-linear system with newton method * * \param [in] [data] * [sysNumber] index of the corresponding non-linear system * * \author wbraun */ int solveNewton(DATA *data, threadData_t *threadData, int sysNumber) { NONLINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); DATA_NEWTON* solverData = (DATA_NEWTON*)(systemData->solverData); int eqSystemNumber = 0; int i; double xerror = -1, xerror_scaled = -1; int success = 0; int nfunc_evals = 0; int continuous = 1; double local_tol = solverData->ftol; int giveUp = 0; int retries = 0; int retries2 = 0; int nonContinuousCase = 0; modelica_boolean *relationsPreBackup = NULL; int casualTearingSet = data->simulationInfo->nonlinearSystemData[sysNumber].strictTearingFunctionCall != NULL; DATA_USER* userdata = (DATA_USER*)malloc(sizeof(DATA_USER)); assert(userdata != NULL); userdata->data = (void*)data; userdata->threadData = threadData; userdata->sysNumber = sysNumber; /* * We are given the number of the non-linear system. * We want to look it up among all equations. */ eqSystemNumber = systemData->equationIndex; local_tol = solverData->ftol; relationsPreBackup = (modelica_boolean*) malloc(data->modelData->nRelations*sizeof(modelica_boolean)); solverData->nfev = 0; /* try to calculate jacobian only once at the beginning of the iteration */ solverData->calculate_jacobian = 0; // Initialize lambda variable if (data->simulationInfo->nonlinearSystemData[sysNumber].homotopySupport) { solverData->x[solverData->n] = 1.0; solverData->x_new[solverData->n] = 1.0; } else { solverData->x[solverData->n] = 0.0; solverData->x_new[solverData->n] = 0.0; } /* debug output */ if(ACTIVE_STREAM(LOG_NLS_V)) { int indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_NLS_V, 1, indexes, "Start solving Non-Linear System %d at time %g with Newton Solver", eqSystemNumber, data->localData[0]->timeValue); for(i = 0; i < solverData->n; i++) { infoStreamPrint(LOG_NLS_V, 1, "x[%d] = %.15e", i, data->simulationInfo->discreteCall ? systemData->nlsx[i] : systemData->nlsxExtrapolation[i]); infoStreamPrint(LOG_NLS_V, 0, "nominal = %g +++ nlsx = %g +++ old = %g +++ extrapolated = %g", systemData->nominal[i], systemData->nlsx[i], systemData->nlsxOld[i], systemData->nlsxExtrapolation[i]); messageClose(LOG_NLS_V); } messageClose(LOG_NLS_V); } /* set x vector */ if(data->simulationInfo->discreteCall) { memcpy(solverData->x, systemData->nlsx, solverData->n*(sizeof(double))); } else { memcpy(solverData->x, systemData->nlsxExtrapolation, solverData->n*(sizeof(double))); } /* start solving loop */ while(!giveUp && !success) { giveUp = 1; solverData->newtonStrategy = data->simulationInfo->newtonStrategy; _omc_newton(wrapper_fvec_newton, solverData, (void*)userdata); /* check for proper inputs */ if(solverData->info == 0) printErrorEqSyst(IMPROPER_INPUT, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber), data->localData[0]->timeValue); /* reset non-contunuousCase */ if(nonContinuousCase && xerror > local_tol && xerror_scaled > local_tol) { memcpy(data->simulationInfo->relationsPre, relationsPreBackup, sizeof(modelica_boolean)*data->modelData->nRelations); nonContinuousCase = 0; } /* check for error */ xerror_scaled = enorm_(&solverData->n, solverData->fvecScaled); xerror = enorm_(&solverData->n, solverData->fvec); /* solution found */ if((xerror <= local_tol || xerror_scaled <= local_tol) && solverData->info > 0) { success = 1; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS_V)) { infoStreamPrint(LOG_NLS_V, 0, "*** System solved ***\n%d restarts", retries); infoStreamPrint(LOG_NLS_V, 0, "nfunc = %d +++ error = %.15e +++ error_scaled = %.15e", nfunc_evals, xerror, xerror_scaled); for(i = 0; i < solverData->n; i++) infoStreamPrint(LOG_NLS_V, 0, "x[%d] = %.15e\n\tresidual = %e", i, solverData->x[i], solverData->fvec[i]); } /* take the solution */ memcpy(systemData->nlsx, solverData->x, solverData->n*(sizeof(double))); /* Then try with old values (instead of extrapolating )*/ } // If this is the casual tearing set (only exists for dynamic tearing), break after first try else if(retries < 1 && casualTearingSet) { giveUp = 1; infoStreamPrint(LOG_NLS_V, 0, "### No Solution for the casual tearing set at the first try! ###"); } else if(retries < 1) { memcpy(solverData->x, systemData->nlsxOld, solverData->n*(sizeof(double))); retries++; giveUp = 0; nfunc_evals += solverData->nfev; infoStreamPrint(LOG_NLS_V, 0, " - iteration making no progress:\t try old values."); /* try to vary the initial values */ /* evaluate jacobian in every step now */ solverData->calculate_jacobian = 1; } else if(retries < 2) { for(i = 0; i < solverData->n; i++) solverData->x[i] += systemData->nominal[i] * 0.01; retries++; giveUp = 0; nfunc_evals += solverData->nfev; infoStreamPrint(LOG_NLS_V, 0, " - iteration making no progress:\t vary solution point by 1%%."); /* try to vary the initial values */ } else if(retries < 3) { for(i = 0; i < solverData->n; i++) solverData->x[i] = systemData->nominal[i]; retries++; giveUp = 0; nfunc_evals += solverData->nfev; infoStreamPrint(LOG_NLS_V, 0, " - iteration making no progress:\t try nominal values as initial solution."); } else if(retries < 4 && data->simulationInfo->discreteCall) { /* try to solve non-continuous * work-a-round: since other wise some model does * stuck in event iteration. e.g.: Modelica.Mechanics.Rotational.Examples.HeatLosses */ memcpy(solverData->x, systemData->nlsxOld, solverData->n*(sizeof(double))); retries++; /* try to solve a discontinuous system */ continuous = 0; nonContinuousCase = 1; memcpy(relationsPreBackup, data->simulationInfo->relationsPre, sizeof(modelica_boolean)*data->modelData->nRelations); giveUp = 0; nfunc_evals += solverData->nfev; infoStreamPrint(LOG_NLS_V, 0, " - iteration making no progress:\t try to solve a discontinuous system."); } else if(retries2 < 4) { memcpy(solverData->x, systemData->nlsxOld, solverData->n*(sizeof(double))); /* reduce tolarance */ local_tol = local_tol*10; retries = 0; retries2++; giveUp = 0; nfunc_evals += solverData->nfev; infoStreamPrint(LOG_NLS_V, 0, " - iteration making no progress:\t reduce the tolerance slightly to %e.", local_tol); } else { printErrorEqSyst(ERROR_AT_TIME, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber), data->localData[0]->timeValue); if(ACTIVE_STREAM(LOG_NLS_V)) { infoStreamPrint(LOG_NLS_V, 0, "### No Solution! ###\n after %d restarts", retries); infoStreamPrint(LOG_NLS_V, 0, "nfunc = %d +++ error = %.15e +++ error_scaled = %.15e", nfunc_evals, xerror, xerror_scaled); if(ACTIVE_STREAM(LOG_NLS_V)) for(i = 0; i < solverData->n; i++) infoStreamPrint(LOG_NLS_V, 0, "x[%d] = %.15e\n\tresidual = %e", i, solverData->x[i], solverData->fvec[i]); } } } if(ACTIVE_STREAM(LOG_NLS_V)) messageClose(LOG_NLS_V); free(relationsPreBackup); /* write statistics */ systemData->numberOfFEval = solverData->numberOfFunctionEvaluations; systemData->numberOfIterations = solverData->numberOfIterations; return success; }
/*! \fn solve non-linear system with hybrd method * * \param [in] [data] * [sysNumber] index of the corresponing non-linear system * * \author wbraun */ int solveHybrd(DATA *data, threadData_t *threadData, int sysNumber) { NONLINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); DATA_HYBRD* solverData = (DATA_HYBRD*)systemData->solverData; /* * We are given the number of the non-linear system. * We want to look it up among all equations. */ int eqSystemNumber = systemData->equationIndex; int i, j; integer iflag = 1; double xerror, xerror_scaled; int success = 0; double local_tol = 1e-12; double initial_factor = solverData->factor; int nfunc_evals = 0; int continuous = 1; int nonContinuousCase = 0; int giveUp = 0; int retries = 0; int retries2 = 0; int retries3 = 0; int assertCalled = 0; int assertRetries = 0; int assertMessage = 0; modelica_boolean* relationsPreBackup; struct dataAndSys dataAndSysNumber = {data, threadData, sysNumber}; relationsPreBackup = (modelica_boolean*) malloc(data->modelData->nRelations*sizeof(modelica_boolean)); solverData->numberOfFunctionEvaluations = 0; /* debug output */ if(ACTIVE_STREAM(LOG_NLS_V)) { int indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_NLS_V, 1, indexes, "start solving non-linear system >>%d<< at time %g", eqSystemNumber, data->localData[0]->timeValue); for(i=0; i<solverData->n; i++) { infoStreamPrint(LOG_NLS_V, 1, "%d. %s = %f", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->nlsx[i]); infoStreamPrint(LOG_NLS_V, 0, " nominal = %f\nold = %f\nextrapolated = %f", systemData->nominal[i], systemData->nlsxOld[i], systemData->nlsxExtrapolation[i]); messageClose(LOG_NLS_V); } messageClose(LOG_NLS_V); } /* set x vector */ if(data->simulationInfo->discreteCall) memcpy(solverData->x, systemData->nlsx, solverData->n*(sizeof(double))); else memcpy(solverData->x, systemData->nlsxExtrapolation, solverData->n*(sizeof(double))); for(i=0; i<solverData->n; i++){ solverData->xScalefactors[i] = fmax(fabs(solverData->x[i]), systemData->nominal[i]); } /* start solving loop */ while(!giveUp && !success) { for(i=0; i<solverData->n; i++) solverData->xScalefactors[i] = fmax(fabs(solverData->x[i]), systemData->nominal[i]); /* debug output */ if(ACTIVE_STREAM(LOG_NLS_V)) { printVector(solverData->xScalefactors, &(solverData->n), LOG_NLS_V, "scaling factors x vector"); printVector(solverData->x, &(solverData->n), LOG_NLS_V, "Iteration variable values"); } /* Scaling x vector */ if(solverData->useXScaling) { for(i=0; i<solverData->n; i++) { solverData->x[i] = (1.0/solverData->xScalefactors[i]) * solverData->x[i]; } } /* debug output */ if(ACTIVE_STREAM(LOG_NLS_V)) { printVector(solverData->x, &solverData->n, LOG_NLS_V, "Iteration variable values (scaled)"); } /* set residual function continuous */ if(continuous) { ((DATA*)data)->simulationInfo->solveContinuous = 1; } else { ((DATA*)data)->simulationInfo->solveContinuous = 0; } giveUp = 1; /* try */ { int success = 0; #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif hybrj_(wrapper_fvec_hybrj, &solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &solverData->xtol, &solverData->maxfev, solverData->diag, &solverData->mode, &solverData->factor, &solverData->nprint, &solverData->info, &solverData->nfev, &solverData->njev, solverData->r__, &solverData->lr, solverData->qtf, solverData->wa1, solverData->wa2, solverData->wa3, solverData->wa4, (void*) &dataAndSysNumber); success = 1; if(assertCalled) { infoStreamPrint(LOG_NLS, 0, "After assertions failed, found a solution for which assertions did not fail."); /* re-scaling x vector */ for(i=0; i<solverData->n; i++){ if(solverData->useXScaling) systemData->nlsxOld[i] = solverData->x[i]*solverData->xScalefactors[i]; else systemData->nlsxOld[i] = solverData->x[i]; } } assertRetries = 0; assertCalled = 0; success = 1; #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif /* catch */ if (!success) { if (!assertMessage) { if (ACTIVE_WARNING_STREAM(LOG_STDOUT)) { if(data->simulationInfo->initial) warningStreamPrint(LOG_STDOUT, 1, "While solving non-linear system an assertion failed during initialization."); else warningStreamPrint(LOG_STDOUT, 1, "While solving non-linear system an assertion failed at time %g.", data->localData[0]->timeValue); warningStreamPrint(LOG_STDOUT, 0, "The non-linear solver tries to solve the problem that could take some time."); warningStreamPrint(LOG_STDOUT, 0, "It could help to provide better start-values for the iteration variables."); if (!ACTIVE_STREAM(LOG_NLS)) warningStreamPrint(LOG_STDOUT, 0, "For more information simulate with -lv LOG_NLS"); messageClose(LOG_STDOUT); } assertMessage = 1; } solverData->info = -1; xerror_scaled = 1; xerror = 1; assertCalled = 1; } } /* set residual function continuous */ if(continuous) { ((DATA*)data)->simulationInfo->solveContinuous = 0; } else { ((DATA*)data)->simulationInfo->solveContinuous = 1; } /* re-scaling x vector */ if(solverData->useXScaling) for(i=0; i<solverData->n; i++) solverData->x[i] = solverData->x[i]*solverData->xScalefactors[i]; /* check for proper inputs */ if(solverData->info == 0) { printErrorEqSyst(IMPROPER_INPUT, modelInfoGetEquation(&data->modelData->modelDataXml, eqSystemNumber), data->localData[0]->timeValue); } if(solverData->info != -1) { /* evaluate with discontinuities */ if(data->simulationInfo->discreteCall){ int scaling = solverData->useXScaling; int success = 0; if(scaling) solverData->useXScaling = 0; ((DATA*)data)->simulationInfo->solveContinuous = 0; /* try */ #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif wrapper_fvec_hybrj(&solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &iflag, (void*) &dataAndSysNumber); success = 1; #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif /* catch */ if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); solverData->info = -1; xerror_scaled = 1; xerror = 1; assertCalled = 1; } if(scaling) solverData->useXScaling = 1; updateRelationsPre(data); } } if(solverData->info != -1) { /* scaling residual vector */ { int l=0; for(i=0; i<solverData->n; i++){ solverData->resScaling[i] = 1e-16; for(j=0; j<solverData->n; j++){ solverData->resScaling[i] = (fabs(solverData->fjacobian[l]) > solverData->resScaling[i]) ? fabs(solverData->fjacobian[l]) : solverData->resScaling[i]; l++; } solverData->fvecScaled[i] = solverData->fvec[i] * (1 / solverData->resScaling[i]); } /* debug output */ if(ACTIVE_STREAM(LOG_NLS_V)) { infoStreamPrint(LOG_NLS_V, 1, "scaling factors for residual vector"); for(i=0; i<solverData->n; i++) { infoStreamPrint(LOG_NLS_V, 1, "scaled residual [%d] : %.20e", i, solverData->fvecScaled[i]); infoStreamPrint(LOG_NLS_V, 0, "scaling factor [%d] : %.20e", i, solverData->resScaling[i]); messageClose(LOG_NLS_V); } messageClose(LOG_NLS_V); } /* debug output */ if(ACTIVE_STREAM(LOG_NLS_JAC)) { char buffer[4096]; infoStreamPrint(LOG_NLS_JAC, 1, "jacobian matrix [%dx%d]", (int)solverData->n, (int)solverData->n); for(i=0; i<solverData->n; i++) { buffer[0] = 0; for(j=0; j<solverData->n; j++) sprintf(buffer, "%s%10g ", buffer, solverData->fjacobian[i*solverData->n+j]); infoStreamPrint(LOG_NLS_JAC, 0, "%s", buffer); } messageClose(LOG_NLS_JAC); } /* check for error */ xerror_scaled = enorm_(&solverData->n, solverData->fvecScaled); xerror = enorm_(&solverData->n, solverData->fvec); } } /* reset non-contunuousCase */ if(nonContinuousCase && xerror > local_tol && xerror_scaled > local_tol) { memcpy(data->simulationInfo->relationsPre, relationsPreBackup, sizeof(modelica_boolean)*data->modelData->nRelations); nonContinuousCase = 0; } if(solverData->info < 4 && xerror > local_tol && xerror_scaled > local_tol) solverData->info = 4; /* solution found */ if(solverData->info == 1 || xerror <= local_tol || xerror_scaled <= local_tol) { int scaling; success = 1; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { int indexes[2] = {1,eqSystemNumber}; /* output solution */ infoStreamPrintWithEquationIndexes(LOG_NLS, 1, indexes, "solution for NLS %d at t=%g", eqSystemNumber, data->localData[0]->timeValue); for(i=0; i<solverData->n; ++i) { infoStreamPrint(LOG_NLS, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], solverData->x[i]); } messageClose(LOG_NLS); }else if (ACTIVE_STREAM(LOG_NLS_V)){ infoStreamPrint(LOG_NLS_V, 1, "system solved"); infoStreamPrint(LOG_NLS_V, 0, "%d retries\n%d restarts", retries, retries2+retries3); messageClose(LOG_NLS_V); printStatus(data, solverData, eqSystemNumber, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } scaling = solverData->useXScaling; if(scaling) solverData->useXScaling = 0; /* take the solution */ memcpy(systemData->nlsx, solverData->x, solverData->n*(sizeof(double))); /* try */ { int success = 0; #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif wrapper_fvec_hybrj(&solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &iflag, (void*) &dataAndSysNumber); success = 1; #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif /* catch */ if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); solverData->info = 4; xerror_scaled = 1; xerror = 1; assertCalled = 1; success = 0; giveUp = 0; } } if(scaling) solverData->useXScaling = 1; }
/*! \fn solve linear system with totalpivot method * * \param [in] [data] * [sysNumber] index of the corresponing non-linear system * * \author bbachmann */ int solveTotalPivot(DATA *data, threadData_t *threadData, int sysNumber, double* aux_x) { void *dataAndThreadData[2] = {data, threadData}; int i, j; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_TOTALPIVOT* solverData = (DATA_TOTALPIVOT*) systemData->solverData[1]; int n = systemData->size, status; double fdeps = 1e-8; double xTol = 1e-8; int eqSystemNumber = systemData->equationIndex; int indexes[2] = {1,eqSystemNumber}; int rank; /* We are given the number of the linear system. * We want to look it up among all equations. */ /* int eqSystemNumber = systemData->equationIndex; */ int success = 1; double tmpJacEvalTime; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Total Pivot Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); debugVectorDoubleLS(LOG_LS_V,"SCALING",systemData->nominal,n); debugVectorDoubleLS(LOG_LS_V,"Old VALUES",aux_x,n); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method){ /* reset matrix A */ vecConstLS(n*n, 0.0, systemData->A); /* update matrix A -> first n columns of matrix Ab*/ systemData->setA(data, threadData, systemData); vecCopyLS(n*n, systemData->A, solverData->Ab); /* update vector b (rhs) -> -b is last column of matrix Ab*/ rt_ext_tp_tick(&(solverData->timeClock)); systemData->setb(data, threadData, systemData); vecScalarMultLS(n, systemData->b, -1.0, solverData->Ab + n*n); } else { /* calculate jacobian -> first n columns of matrix Ab*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobianTotalPivot(data, threadData, solverData->Ab, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } /* calculate vector b (rhs) -> -b is last column of matrix Ab */ wrapper_fvec_totalpivot(aux_x, solverData->Ab + n*n, dataAndThreadData, sysNumber); } tmpJacEvalTime = rt_ext_tp_tock(&(solverData->timeClock)); systemData->jacobianTime += tmpJacEvalTime; infoStreamPrint(LOG_LS_V, 0, "### %f time to set Matrix A and vector b.", tmpJacEvalTime); debugMatrixDoubleLS(LOG_LS_V,"LGS: matrix Ab",solverData->Ab, n, n+1); rt_ext_tp_tick(&(solverData->timeClock)); status = solveSystemWithTotalPivotSearchLS(n, solverData->x, solverData->Ab, solverData->indRow, solverData->indCol, &rank); infoStreamPrint(LOG_LS_V, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if (status != 0) { warningStreamPrint(LOG_STDOUT, 0, "Error solving linear system of equations (no. %d) at time %f.", (int)systemData->equationIndex, data->localData[0]->timeValue); success = 0; } else { debugVectorDoubleLS(LOG_LS_V, "SOLUTION:", solverData->x, n+1); if (1 == systemData->method){ /* add the solution to old solution vector*/ vecAddLS(n, aux_x, solverData->x, aux_x); wrapper_fvec_totalpivot(aux_x, solverData->b, dataAndThreadData, sysNumber); } else { /* take the solution */ vecCopyLS(n, solverData->x, aux_x); } if (ACTIVE_STREAM(LOG_LS_V)){ infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i=0; i<systemData->size; ++i) { infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], aux_x[i]); } messageClose(LOG_LS_V); } } return success; }
/*! \fn solve linear system with Klu method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * * author: wbraun */ int solveKlu(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_KLU* solverData = (DATA_KLU*)systemData->solverData; int i, j, status = 0, success = 0, n = systemData->size, eqSystemNumber = systemData->equationIndex, indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Klu Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* set A matrix */ solverData->Ap[0] = 0; systemData->setA(data, threadData, systemData); solverData->Ap[solverData->n_row] = solverData->nnz; if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Matrix A"); printMatrixCSR(solverData->Ap, solverData->Ai, solverData->Ax, n); messageClose(LOG_LS_V); } /* set b vector */ systemData->setb(data, threadData, systemData); } else { solverData->Ap[0] = 0; /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobian(data, threadData, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } solverData->Ap[solverData->n_row] = solverData->nnz; /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); residual_wrapper(solverData->work, systemData->b, dataAndThreadData, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); if (ACTIVE_STREAM(LOG_LS_V)) { if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Old solution x:"); for(i = 0; i < solverData->n_row; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } infoStreamPrint(LOG_LS_V, 1, "Matrix A n_rows = %d", solverData->n_row); for (i=0; i<solverData->n_row; i++){ infoStreamPrint(LOG_LS_V, 0, "%d. Ap => %d -> %d", i, solverData->Ap[i], solverData->Ap[i+1]); for (j=solverData->Ap[i]; j<solverData->Ap[i+1]; j++){ infoStreamPrint(LOG_LS_V, 0, "A[%d,%d] = %f", i, solverData->Ai[j], solverData->Ax[j]); } } messageClose(LOG_LS_V); for (i=0; i<solverData->n_row; i++) infoStreamPrint(LOG_LS_V, 0, "b[%d] = %e", i, systemData->b[i]); } rt_ext_tp_tick(&(solverData->timeClock)); /* symbolic pre-ordering of A to reduce fill-in of L and U */ if (0 == solverData->numberSolving) { infoStreamPrint(LOG_LS_V, 0, "Perform analyze settings:\n - ordering used: %d\n - current status: %d", solverData->common.ordering, solverData->common.status); solverData->symbolic = klu_analyze(solverData->n_col, solverData->Ap, solverData->Ai, &solverData->common); } /* compute the LU factorization of A */ if (0 == solverData->common.status){ solverData->numeric = klu_factor(solverData->Ap, solverData->Ai, solverData->Ax, solverData->symbolic, &solverData->common); } if (0 == solverData->common.status){ if (1 == systemData->method){ if (klu_solve(solverData->symbolic, solverData->numeric, solverData->n_col, 1, systemData->b, &solverData->common)){ success = 1; } } else { if (klu_tsolve(solverData->symbolic, solverData->numeric, solverData->n_col, 1, systemData->b, &solverData->common)){ success = 1; } } } infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); /* print solution */ if (1 == success){ if (1 == systemData->method){ /* take the solution */ for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += systemData->b[i]; /* update inner equations */ residual_wrapper(systemData->x, solverData->work, dataAndThreadData, sysNumber); } else { /* the solution is automatically in x */ memcpy(systemData->x, systemData->b, sizeof(double)*systemData->size); } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, status); } solverData->numberSolving += 1; return success; }
int solveLis(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_LIS* solverData = (DATA_LIS*)systemData->solverData; int i, ret, success = 1, ni, iflag = 1, n = systemData->size, eqSystemNumber = systemData->equationIndex; char *lis_returncode[] = {"LIS_SUCCESS", "LIS_ILL_OPTION", "LIS_BREAKDOWN", "LIS_OUT_OF_MEMORY", "LIS_MAXITER", "LIS_NOT_IMPLEMENTED", "LIS_ERR_FILE_IO"}; LIS_INT err; int indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Lis Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); /* set old values as start value for the iteration */ for(i=0; i<n; i++) { err = lis_vector_set_value(LIS_INS_VALUE, i, systemData->x[i], solverData->x); } rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { lis_matrix_set_size(solverData->A, solverData->n_row, 0); /* set A matrix */ systemData->setA(data, threadData, systemData); lis_matrix_assemble(solverData->A); /* set b vector */ systemData->setb(data, threadData, systemData); } else { lis_matrix_set_size(solverData->A, solverData->n_row, 0); /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1) { getAnalyticalJacobianLis(data, threadData, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } lis_matrix_assemble(solverData->A); /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); wrapper_fvec_lis(solverData->work, systemData->b, dataAndThreadData, sysNumber); /* set b vector */ for(i=0; i<n; i++) { err = lis_vector_set_value(LIS_INS_VALUE, i, systemData->b[i], solverData->b); } } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); rt_ext_tp_tick(&(solverData->timeClock)); err = lis_solve(solverData->A,solverData->b,solverData->x,solverData->solver); infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if (err) { warningStreamPrint(LOG_LS_V, 0, "lis_solve : %s(code=%d)\n\n ", lis_returncode[err], err); printLisMatrixCSR(solverData->A, solverData->n_row); success = 0; } /* Log A*x=b */ if(ACTIVE_STREAM(LOG_LS_V)) { char *buffer = (char*)malloc(sizeof(char)*n*25); printLisMatrixCSR(solverData->A, n); /* b vector */ infoStreamPrint(LOG_LS_V, 1, "b vector [%d]", n); for(i=0; i<n; i++) { buffer[0] = 0; sprintf(buffer, "%s%20.12g ", buffer, solverData->b->value[i]); infoStreamPrint(LOG_LS_V, 0, "%s", buffer); } messageClose(LOG_LS_V); free(buffer); } /* print solution */ if (1 == success) { if (1 == systemData->method) { /* take the solution */ lis_vector_get_values(solverData->x, 0, solverData->n_row, systemData->x); for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += solverData->work[i]; /* update inner equations */ wrapper_fvec_lis(systemData->x, solverData->work, dataAndThreadData, sysNumber); } else { /* write solution */ lis_vector_get_values(solverData->x, 0, solverData->n_row, systemData->x); } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, err); } return success; }