/*! \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 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, 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; static state mem_state; modelica_boolean* relationsPreBackup; relationsPreBackup = (modelica_boolean*) malloc(data->modelData.nRelations*sizeof(modelica_boolean)); /* debug output */ if(ACTIVE_STREAM(LOG_NLS)) { INFO2(LOG_NLS, "start solving non-linear system >>%s<< at time %g", modelInfoXmlGetEquation(&data->modelData.modelDataXml, eqSystemNumber).name, data->localData[0]->timeValue); INDENT(LOG_NLS); for(i=0; i<solverData->n; i++) { INFO2(LOG_NLS, "x[%d] = %f", i, systemData->nlsx[i]); INDENT(LOG_NLS); INFO3(LOG_NLS, "scaling = %f\nold = %f\nextrapolated = %f", systemData->nominal[i], systemData->nlsxOld[i], systemData->nlsxExtrapolation[i]); RELEASE(LOG_NLS); } RELEASE(LOG_NLS); } /* 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]); /* evaluate with discontinuities */ { int scaling = solverData->useXScaling; if(scaling) solverData->useXScaling = 0; mem_state = get_memory_state(); /* try */ if(!setjmp(nonlinearJmpbuf)) { wrapper_fvec_hybrj(&solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &iflag, data, sysNumber); restore_memory_state(mem_state); } else { /* catch */ restore_memory_state(mem_state); WARNING(LOG_STDOUT, "Non-Linear Solver try to handle a problem with a called assert."); } if(scaling) { solverData->useXScaling = 1; } } /* 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; mem_state = get_memory_state(); /* try */ if(!setjmp(nonlinearJmpbuf)) { _omc_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, data, sysNumber); restore_memory_state(mem_state); if(assertCalled) { INFO(LOG_NLS, "After asserts was called, values reached which avoided assert call."); memcpy(systemData->nlsxOld, solverData->x, solverData->n*(sizeof(double))); } assertRetries = 0; assertCalled = 0; } else { /* catch */ restore_memory_state(mem_state); if(!assertMessage) { INDENT(LOG_STDOUT); WARNING(LOG_STDOUT, "While solving non-linear system an assert was called."); WARNING(LOG_STDOUT, "The non-linear solver tries to solve the problem that could take some time."); WARNING(LOG_STDOUT, "It could help to provide better start-values for the iteration variables."); WARNING(LOG_STDOUT, "For more information simulate with -lv LOG_NLS"); RELEASE(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, modelInfoXmlGetEquation(&data->modelData.modelDataXml, eqSystemNumber), data->localData[0]->timeValue); } if(solverData->info != -1) { /* evaluate with discontinuities */ if(data->simulationInfo.discreteCall){ int scaling = solverData->useXScaling; if(scaling) solverData->useXScaling = 0; ((DATA*)data)->simulationInfo.solveContinuous = 0; mem_state = get_memory_state(); /* try */ if(!setjmp(nonlinearJmpbuf)) { wrapper_fvec_hybrj(&solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &iflag, data, sysNumber); restore_memory_state(mem_state); } else { /* catch */ restore_memory_state(mem_state); WARNING(LOG_STDOUT, "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; storeRelations(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)) { INFO(LOG_NLS_V, "scaling factors for residual vector"); INDENT(LOG_NLS_V); for(i=0; i<solverData->n; i++) { INFO2(LOG_NLS_V, "scaled residual [%d] : %.20e", i, solverData->fvecScaled[i]); INDENT(LOG_NLS_V); INFO2(LOG_NLS_V, "scaling factor [%d] : %.20e", i, solverData->resScaling[i]); RELEASE(LOG_NLS_V); } RELEASE(LOG_NLS_V); } /* debug output */ if(ACTIVE_STREAM(LOG_NLS_JAC)) { char buffer[4096]; INFO2(LOG_NLS_JAC, "jacobian matrix [%dx%d]", (int)solverData->n, (int)solverData->n); INDENT(LOG_NLS_JAC); 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]); INFO1(LOG_NLS_JAC, "%s", buffer); } RELEASE(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)) { INFO(LOG_NLS, "system solved"); INDENT(LOG_NLS); INFO2(LOG_NLS, "%d retries\n%d restarts", retries, retries2+retries3); RELEASE(LOG_NLS); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS); } scaling = solverData->useXScaling; if(scaling) solverData->useXScaling = 0; /* take the solution */ memcpy(systemData->nlsx, solverData->x, solverData->n*(sizeof(double))); mem_state = get_memory_state(); /* try */ if(!setjmp(nonlinearJmpbuf)) { wrapper_fvec_hybrj(&solverData->n, solverData->x, solverData->fvec, solverData->fjac, &solverData->ldfjac, &iflag, data, sysNumber); restore_memory_state(mem_state); } else { /* catch */ restore_memory_state(mem_state); WARNING(LOG_STDOUT, "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; } else if((solverData->info == 4 || solverData->info == 5) && assertRetries < 1+solverData->n && assertCalled) { /* case only used, when the Modelica code called an assert * then, we try to modify start values to avoid the assert call.*/ int i; memcpy(solverData->x, systemData->nlsxOld, solverData->n*(sizeof(double))); /* set all zero values to nominal values */ if(assertRetries < 1) { for(i=0; i<solverData->n; i++) { if(systemData->nlsx[i] == 0) { systemData->nlsx[i] = systemData->nominal[i]; solverData->x[i] = systemData->nominal[i]; } } } /* change initial guess values one by one */ else if(assertRetries < solverData->n+1) { i = assertRetries-1; solverData->x[i] += 0.01*systemData->nominal[i]; } giveUp = 0; nfunc_evals += solverData->nfev; assertRetries++; if(ACTIVE_STREAM(LOG_NLS)) { INFO1(LOG_NLS, " - try to handle a problem with a called assert vary initial value a bit. (Retry: %d)",assertRetries); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if((solverData->info == 4 || solverData->info == 5) && retries < 3) { /* first try to decrease factor */ /* 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))); solverData->factor = solverData->factor / 10.0; retries++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO1(LOG_NLS, " - iteration making no progress:\t decreasing initial step bound to %f.", solverData->factor); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if((solverData->info == 4 || solverData->info == 5) && retries < 4) { /* try to vary the initial values */ for(i = 0; i < solverData->n; i++) solverData->x[i] += systemData->nominal[i] * 0.1; solverData->factor = initial_factor; retries++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, "iteration making no progress:\t vary solution point by 1%%."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if((solverData->info == 4 || solverData->info == 5) && retries < 5) { /* try old values as x-Scaling factors */ /* 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(systemData->nlsxOld[i]), systemData->nominal[i]); retries++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, "iteration making no progress:\t try old values as scaling factors."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if((solverData->info == 4 || solverData->info == 5) && retries < 6) { int scaling = 0; /* try to disable x-Scaling */ /* 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))); scaling = solverData->useXScaling; if(scaling) solverData->useXScaling = 0; /* reset x-scalling factors */ for(i=0; i<solverData->n; i++) solverData->xScalefactors[i] = fmax(fabs(solverData->x[i]), systemData->nominal[i]); retries++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, "iteration making no progress:\t try without scaling at all."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if((solverData->info == 4 || solverData->info == 5) && retries < 7 && 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; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t try to solve a discontinuous system."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* Then try with old values (instead of extrapolating )*/ } else if((solverData->info == 4 || solverData->info == 5) && retries2 < 1) { int scaling = 0; /* set x vector */ memcpy(solverData->x, systemData->nlsxOld, solverData->n*(sizeof(double))); scaling = solverData->useXScaling; if(!scaling) solverData->useXScaling = 1; continuous = 1; solverData->factor = initial_factor; retries = 0; retries2++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t use old values instead extrapolated."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try to vary the initial values */ } else if((solverData->info == 4 || solverData->info == 5) && retries2 < 2) { /* 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->x[i] *= 1.01; }; retries = 0; retries2++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t vary initial point by adding 1%%."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try to vary the initial values */ } else if((solverData->info == 4 || solverData->info == 5) && retries2 < 3) { /* 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->x[i] *= 0.99; }; retries = 0; retries2++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t vary initial point by -1%%."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try to vary the initial values */ } else if((solverData->info == 4 || solverData->info == 5) && retries2 < 4) { /* set x vector */ memcpy(solverData->x, systemData->nominal, solverData->n*(sizeof(double))); retries = 0; retries2++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t try scaling factor as initial point."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try own scaling factors */ } else if((solverData->info == 4 || solverData->info == 5) && retries2 < 5 && !assertCalled) { /* 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->diag[i] = fabs(solverData->resScaling[i]); if(solverData->diag[i] <= 1e-16) solverData->diag[i] = 1e-16; } retries = 0; retries2++; giveUp = 0; solverData->mode = 2; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t try with own scaling factors."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try without internal scaling */ } else if((solverData->info == 4 || solverData->info == 5) && retries3 < 1) { /* 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->diag[i] = 1.0; solverData->useXScaling = 1; retries = 0; retries2 = 0; retries3++; solverData->mode = 2; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO(LOG_NLS, " - iteration making no progress:\t disable solver internal scaling."); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } /* try to reduce the tolerance a bit */ } else if((solverData->info == 4 || solverData->info == 5) && retries3 < 6) { /* 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))); /* reduce tolarance */ local_tol = local_tol*10; solverData->factor = initial_factor; solverData->mode = 1; retries = 0; retries2 = 0; retries3++; giveUp = 0; nfunc_evals += solverData->nfev; if(ACTIVE_STREAM(LOG_NLS)) { INFO1(LOG_NLS, " - iteration making no progress:\t reduce the tolerance slightly to %e.", local_tol); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS_V); } } else if(solverData->info >= 2 && solverData->info <= 5) { /* while the initialization it's ok to every time a solution */ if(!data->simulationInfo.initial){ printErrorEqSyst(ERROR_AT_TIME, modelInfoXmlGetEquation(&data->modelData.modelDataXml, eqSystemNumber), data->localData[0]->timeValue); } if(ACTIVE_STREAM(LOG_NLS)) { RELEASE(LOG_NLS); INFO1(LOG_NLS, "### No Solution! ###\n after %d restarts", retries*retries2*retries3); printStatus(solverData, &nfunc_evals, &xerror, &xerror_scaled, LOG_NLS); } /* take the best approximation */ memcpy(systemData->nlsx, solverData->x, solverData->n*(sizeof(double))); } } /* reset some solving data */ solverData->factor = initial_factor; solverData->mode = 1; free(relationsPreBackup); return success; }