fmiStatus fmiGetDerivatives(fmiComponent c, fmiReal derivatives[], size_t nx) { unsigned int i=0; ModelInstance* comp = (ModelInstance *)c; threadData_t *threadData = comp->threadData; if (invalidState(comp, "fmiGetDerivatives", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetDerivatives", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiGetDerivatives", "derivatives[]", derivatives)) return fmiError; /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) comp->fmuData->callback->functionODE(comp->fmuData, comp->threadData); #if (NUMBER_OF_STATES>0) for (i=0; i<nx; i++) { fmiValueReference vr = vrStatesDerivatives[i]; derivatives[i] = getReal(comp, vr); // to be implemented by the includer of this file if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetDerivatives: #r%d# = %.16g", vr, derivatives[i]); } #endif return fmiOK; /* catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) comp->functions.logger(c, comp->instanceName, fmiError, "error", "fmiGetDerivatives: terminated by an assertion."); return fmiError; }
/*! \fn nlsKinsolResiduals * * \param [in] [x] * \param [out] [f] * \param [ref] [user_data] * */ static int nlsKinsolResiduals(N_Vector x, N_Vector f, void *userData) { double *xdata = NV_DATA_S(x); double *fdata = NV_DATA_S(f); NLS_KINSOL_USERDATA *kinsolUserData = (NLS_KINSOL_USERDATA*) userData; DATA* data = kinsolUserData->data; threadData_t *threadData = kinsolUserData->threadData; int sysNumber = kinsolUserData->sysNumber; void *dataAndThreadData[2] = {data, threadData}; NONLINEAR_SYSTEM_DATA *nlsData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); NLS_KINSOL_DATA* kinsolData = (NLS_KINSOL_DATA*) nlsData->solverData; int iflag = 1; kinsolData->countResCalls++; #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif /* call residual function */ data->simulationInfo->nonlinearSystemData[sysNumber].residualFunc(dataAndThreadData, xdata, fdata, (const int*) &iflag); iflag = 0; #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif return iflag; }
/*! \fn updateInnerEquation * * This function updates inner equation with the current x. * * \param [ref] [data] * [in] [sysNumber] index of corresponding non-linear system */ int updateInnerEquation(void **dataIn, int sysNumber, int discrete) { DATA *data = (DATA*) ((void**)dataIn[0]); threadData_t *threadData = (threadData_t*) ((void**)dataIn[1]); NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo->nonlinearSystemData[sysNumber]); int success = 0; /* solve non continuous at discrete points*/ if(discrete) { data->simulationInfo->solveContinuous = 0; } /* try */ #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif /* call residual function */ nonlinsys->residualFunc((void*) dataIn, nonlinsys->nlsx, nonlinsys->resValues, (int*)&nonlinsys->size); /* replace extrapolated values by current x for discrete step */ memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); success = 1; /*catch */ #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } if(discrete) { data->simulationInfo->solveContinuous = 1; } return success; }
/*! \fn solve non-linear systems * * \param [in] [data] * \param [in] [sysNumber] index of corresponding non-linear system * * \author wbraun */ int solve_nonlinear_system(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; int success = 0, saveJumpState; NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo.nonlinearSystemData[sysNumber]); struct dataNewtonAndHybrid *mixedSolverData; data->simulationInfo.currentNonlinearSystemIndex = sysNumber; /* enable to avoid division by zero */ data->simulationInfo.noThrowDivZero = 1; ((DATA*)data)->simulationInfo.solveContinuous = 1; rt_ext_tp_tick(&nonlinsys->totalTimeClock); if(data->simulationInfo.discreteCall) { double *fvec = malloc(sizeof(double)*nonlinsys->size); int success = 0; #ifndef OMC_EMCC /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) #endif ((DATA*)data)->simulationInfo.solveContinuous = 0; nonlinsys->residualFunc((void*) dataAndThreadData, nonlinsys->nlsx, fvec, (int*)&nonlinsys->size); ((DATA*)data)->simulationInfo.solveContinuous = 1; success = 1; #ifndef OMC_EMCC /*catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } free(fvec); }
/*! * helper optData2ModelData * author: Vitalij Ruge **/ static inline void updateDOSystem(OptData * optData, DATA * data, threadData_t *threadData, const int i, const int j, const int index, const int m){ /* try */ optData->scc = 0; #if !defined(OMC_EMCC) MMC_TRY_INTERNAL(simulationJumpBuffer) #endif data->callback->input_function(data); /*data->callback->functionDAE(data);*/ updateDiscreteSystem(data); if(index){ diffSynColoredOptimizerSystem(optData, optData->J[i][j], i, j, m); } optData->scc = 1; #if !defined(OMC_EMCC) MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif }
fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean* callEventUpdate) { ModelInstance* comp = (ModelInstance *)c; threadData_t *threadData = comp->threadData; if (invalidState(comp, "fmiCompletedIntegratorStep", modelInitialized)) return fmiError; if (nullPointer(comp, "fmiCompletedIntegratorStep", "callEventUpdate", callEventUpdate)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiCompletedIntegratorStep"); /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) comp->fmuData->callback->functionAlgebraics(comp->fmuData, comp->threadData); comp->fmuData->callback->output_function(comp->fmuData, comp->threadData); comp->fmuData->callback->function_storeDelayed(comp->fmuData, comp->threadData); storePreValues(comp->fmuData); *callEventUpdate = fmiFalse; /******** check state selection ********/ if (stateSelection(comp->fmuData, comp->threadData, 1, 0)) { if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: Need to iterate state values changed!"); /* if new set is calculated reinit the solver */ *callEventUpdate = fmiTrue; } /* TODO: fix the extrapolation in non-linear system * then we can stop to save all variables in * in the whole ringbuffer */ overwriteOldSimulationData(comp->fmuData); return fmiOK; /* catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) comp->functions.logger(c, comp->instanceName, fmiError, "error", "fmiCompletedIntegratorStep: terminated by an assertion."); return fmiError; }
fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_t ni) { unsigned int i=0; ModelInstance* comp = (ModelInstance *)c; threadData_t *threadData = comp->threadData; if (invalidState(comp, "fmiGetEventIndicators", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetEventIndicators", "ni", ni, NUMBER_OF_EVENT_INDICATORS)) return fmiError; /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) #if NUMBER_OF_EVENT_INDICATORS>0 /* eval needed equations*/ comp->fmuData->callback->function_ZeroCrossingsEquations(comp->fmuData, comp->threadData); comp->fmuData->callback->function_ZeroCrossings(comp->fmuData, comp->threadData, comp->fmuData->simulationInfo->zeroCrossings); for (i=0; i<ni; i++) { /* retVal = getEventIndicator(comp, i, eventIndicators[i]); // to be implemented by the includer of this file * getEventIndicator(comp, eventIndicators); // to be implemented by the includer of this file */ eventIndicators[i] = comp->fmuData->simulationInfo->zeroCrossings[i]; if (comp->loggingOn){ comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetEventIndicators: z%d = %.16g", i, eventIndicators[i]); } } #endif return fmiOK; /* catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) comp->functions.logger(c, comp->instanceName, fmiError, "error", "fmiGetEventIndicators: terminated by an assertion."); return fmiError; }
/********************************************************************************************** * DASSL with synchronous treating of when equation * - without integrated ZeroCrossing method. * + ZeroCrossing are handled outside DASSL. * + if no event occurs outside DASSL performs a warm-start **********************************************************************************************/ int dassl_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) { TRACE_PUSH double tout = 0; int i = 0; unsigned int ui = 0; int retVal = 0; int saveJumpState; static unsigned int dasslStepsOutputCounter = 1; DASSL_DATA *dasslData = (DASSL_DATA*) solverInfo->solverData; SIMULATION_DATA *sData = data->localData[0]; SIMULATION_DATA *sDataOld = data->localData[1]; MODEL_DATA *mData = (MODEL_DATA*) data->modelData; modelica_real* stateDer = dasslData->stateDer; dasslData->rpar[0] = (double*) (void*) data; dasslData->rpar[1] = (double*) (void*) dasslData; dasslData->rpar[2] = (double*) (void*) threadData; // printf("\tlastdesiredStep: %f\n", solverInfo->lastdesiredStep); // printf("\tstateEvents: %d\n", solverInfo->stateEvents); // printf("\tdidEventStep: %d\n", solverInfo->didEventStep); // printf("\tsampleEvents: %d\n", solverInfo->sampleEvents); // printf("\tintegratorSteps: %d\n", solverInfo->integratorSteps); saveJumpState = threadData->currentErrorStage; threadData->currentErrorStage = ERROR_INTEGRATOR; /* try */ #if !defined(OMC_EMCC) MMC_TRY_INTERNAL(simulationJumpBuffer) #endif assertStreamPrint(threadData, 0 != dasslData->rpar, "could not passed to DDASKR"); /* If an event is triggered and processed restart dassl. */ if(!dasslData->dasslAvoidEventRestart && (solverInfo->didEventStep || 0 == dasslData->idid)) { debugStreamPrint(LOG_EVENTS_V, 0, "Event-management forced reset of DDASKR"); /* obtain reset */ dasslData->info[0] = 0; dasslData->idid = 0; memcpy(stateDer, data->localData[1]->realVars + data->modelData->nStates, sizeof(double)*data->modelData->nStates); } /* Calculate steps until TOUT is reached */ if (dasslData->dasslSteps) { /* If dasslsteps is selected, the dassl run to stopTime or next sample event */ if (data->simulationInfo->nextSampleEvent < data->simulationInfo->stopTime) { tout = data->simulationInfo->nextSampleEvent; } else { tout = data->simulationInfo->stopTime; } } else { tout = solverInfo->currentTime + solverInfo->currentStepSize; } /* Check that tout is not less than timeValue * else will dassl get in trouble. If that is the case we skip the current step. */ if (solverInfo->currentStepSize < DASSL_STEP_EPS) { infoStreamPrint(LOG_DASSL, 0, "Desired step to small try next one"); infoStreamPrint(LOG_DASSL, 0, "Interpolate linear"); /*euler step*/ for(i = 0; i < data->modelData->nStates; i++) { sData->realVars[i] = sDataOld->realVars[i] + stateDer[i] * solverInfo->currentStepSize; } sData->timeValue = solverInfo->currentTime + solverInfo->currentStepSize; data->callback->functionODE(data, threadData); solverInfo->currentTime = sData->timeValue; TRACE_POP return 0; }
/*! \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 systems * * \param [in] [data] * \param [in] [sysNumber] index of corresponding non-linear system * * \author wbraun */ int solve_nonlinear_system(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; int success = 0, saveJumpState; NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo->nonlinearSystemData[sysNumber]); struct dataNewtonAndHybrid *mixedSolverData; data->simulationInfo->currentNonlinearSystemIndex = sysNumber; /* enable to avoid division by zero */ data->simulationInfo->noThrowDivZero = 1; ((DATA*)data)->simulationInfo->solveContinuous = 1; /* performance measurement */ rt_ext_tp_tick(&nonlinsys->totalTimeClock); /* grab the initial guess */ infoStreamPrint(LOG_NLS_EXTRAPOLATE, 1, "############ Start new iteration for system %ld at time at %g ############", nonlinsys->equationIndex, data->localData[0]->timeValue); /* if last solving is too long ago use just old values */ if (fabs(data->localData[0]->timeValue - nonlinsys->lastTimeSolved) < 5*data->simulationInfo->stepSize) { getInitialGuess(nonlinsys, data->localData[0]->timeValue); } else { nonlinsys->getIterationVars(data, nonlinsys->nlsx); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } /* update non continuous */ if (data->simulationInfo->discreteCall) { updateInnerEquation(dataAndThreadData, sysNumber, 1); } /* try */ #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif /* handle asserts */ saveJumpState = threadData->currentErrorStage; threadData->currentErrorStage = ERROR_NONLINEARSOLVER; /* use the selected solver for solving nonlinear system */ switch(data->simulationInfo->nlsMethod) { #if !defined(OMC_MINIMAL_RUNTIME) case NLS_HYBRID: success = solveHybrd(data, threadData, sysNumber); break; case NLS_KINSOL: success = nlsKinsolSolve(data, threadData, sysNumber); break; case NLS_NEWTON: success = solveNewton(data, threadData, sysNumber); /* check if solution process was successful, if not use alternative tearing set if available (dynamic tearing)*/ if (!success && nonlinsys->strictTearingFunctionCall != NULL){ debugString(LOG_DT, "Solving the casual tearing set failed! Now the strict tearing set is used."); success = nonlinsys->strictTearingFunctionCall(data, threadData); if (success) success=2; } break; #endif case NLS_HOMOTOPY: success = solveHomotopy(data, threadData, sysNumber); break; #if !defined(OMC_MINIMAL_RUNTIME) case NLS_MIXED: mixedSolverData = nonlinsys->solverData; nonlinsys->solverData = mixedSolverData->newtonData; success = solveHomotopy(data, threadData, sysNumber); /* check if solution process was successful, if not use alternative tearing set if available (dynamic tearing)*/ if (!success && nonlinsys->strictTearingFunctionCall != NULL){ debugString(LOG_DT, "Solving the casual tearing set failed! Now the strict tearing set is used."); success = nonlinsys->strictTearingFunctionCall(data, threadData); if (success){ success=2; /* update iteration variables of the causal set*/ nonlinsys->getIterationVars(data, nonlinsys->nlsx); } } if (!success) { nonlinsys->solverData = mixedSolverData->hybridData; success = solveHybrd(data, threadData, sysNumber); } nonlinsys->solverData = mixedSolverData; break; #endif default: throwStreamPrint(threadData, "unrecognized nonlinear solver"); } /* set result */ nonlinsys->solved = success; /* handle asserts */ threadData->currentErrorStage = saveJumpState; /*catch */ #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif /* update value list database */ updateInitialGuessDB(nonlinsys, data->localData[0]->timeValue, data->simulationInfo->currentContext); if (nonlinsys->solved == 1) { nonlinsys->lastTimeSolved = data->localData[0]->timeValue; } /* enable to avoid division by zero */ data->simulationInfo->noThrowDivZero = 0; ((DATA*)data)->simulationInfo->solveContinuous = 0; /* performance measurement and statistics */ nonlinsys->totalTime += rt_ext_tp_tock(&(nonlinsys->totalTimeClock)); nonlinsys->numberOfCall++; /* write csv file for debugging */ #if !defined(OMC_MINIMAL_RUNTIME) if (data->simulationInfo->nlsCsvInfomation) { print_csvLineCallStats(((struct csvStats*) nonlinsys->csvData)->callStats, nonlinsys->numberOfCall, data->localData[0]->timeValue, nonlinsys->numberOfIterations, nonlinsys->numberOfFEval, nonlinsys->totalTime, nonlinsys->solved ); } #endif return check_nonlinear_solution(data, 1, sysNumber); }
/*! \fn solve non-linear systems * * \param [in] [data] * \param [in] [sysNumber] index of corresponding non-linear system * * \author wbraun */ int solve_nonlinear_system(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; int success = 0, saveJumpState; NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo->nonlinearSystemData[sysNumber]); struct dataNewtonAndHybrid *mixedSolverData; data->simulationInfo->currentNonlinearSystemIndex = sysNumber; /* enable to avoid division by zero */ data->simulationInfo->noThrowDivZero = 1; ((DATA*)data)->simulationInfo->solveContinuous = 1; rt_ext_tp_tick(&nonlinsys->totalTimeClock); /* value extrapolation */ infoStreamPrint(LOG_NLS_EXTRAPOLATE, 1, "############ Start new iteration for system %d at time at %g ############", sysNumber, data->localData[0]->timeValue); printValuesListTimes((VALUES_LIST*)nonlinsys->oldValueList); /* if list is empty use current start values */ if (listLen(((VALUES_LIST*)nonlinsys->oldValueList)->valueList)==0) { //memcpy(nonlinsys->nlsxOld, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); //memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } else { /* get extrapolated values */ getValues((VALUES_LIST*)nonlinsys->oldValueList, data->localData[0]->timeValue, nonlinsys->nlsxExtrapolation, nonlinsys->nlsxOld); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } if(data->simulationInfo->discreteCall) { double *fvec = malloc(sizeof(double)*nonlinsys->size); int success = 0; #ifndef OMC_EMCC /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) #endif ((DATA*)data)->simulationInfo->solveContinuous = 0; nonlinsys->residualFunc((void*) dataAndThreadData, nonlinsys->nlsx, fvec, (int*)&nonlinsys->size); ((DATA*)data)->simulationInfo->solveContinuous = 1; success = 1; memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); #ifndef OMC_EMCC /*catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } free(fvec); }