/*! \fn updateDiscreteSystem * * Function to update the whole system with event iteration. * Evaluates functionDAE() * * \param [ref] [data] */ void updateDiscreteSystem(DATA *data, threadData_t *threadData) { TRACE_PUSH int IterationNum = 0; int discreteChanged = 0; modelica_boolean relationChanged = 0; data->simulationInfo.needToIterate = 0; data->simulationInfo.callStatistics.updateDiscreteSystem++; data->callback->function_updateRelations(data, threadData, 1); updateRelationsPre(data); storeRelations(data); data->callback->functionDAE(data, threadData); debugStreamPrint(LOG_EVENTS_V, 0, "updated discrete System"); relationChanged = checkRelations(data); discreteChanged = data->callback->checkForDiscreteChanges(data, threadData); while(discreteChanged || data->simulationInfo.needToIterate || relationChanged) { if(data->simulationInfo.needToIterate) { debugStreamPrint(LOG_EVENTS_V, 0, "reinit() call. Iteration needed!"); } if(relationChanged) { debugStreamPrint(LOG_EVENTS_V, 0, "relations changed. Iteration needed."); } if(discreteChanged) { debugStreamPrint(LOG_EVENTS_V, 0, "discrete Variable changed. Iteration needed."); } storePreValues(data); updateRelationsPre(data); printRelations(data, LOG_EVENTS_V); printZeroCrossings(data, LOG_EVENTS_V); data->callback->functionDAE(data, threadData); IterationNum++; if(IterationNum > IterationMax) { throwStreamPrint(threadData, "ERROR: Too many event iterations. System is inconsistent. Simulation terminate."); } relationChanged = checkRelations(data); discreteChanged = data->callback->checkForDiscreteChanges(data, threadData); } storeRelations(data); TRACE_POP }
/*! \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 mixed system with extended search * * \param [in] [data] * [sysNumber] index of the corresponing mixed system * * \author wbraun */ int solveMixedSearch(DATA *data, int sysNumber) { MIXED_SYSTEM_DATA* systemData = &(data->simulationInfo->mixedSystemData[sysNumber]); DATA_SEARCHMIXED_SOLVER* solverData = (DATA_SEARCHMIXED_SOLVER*)systemData->solverData; int eqSystemNumber = systemData->equationIndex; int found_solution = 0; /* * We are given the number of the non-linear system. * We want to look it up among all equations. */ int i, ix; int stepCount = 0; int mixedIterations = 0; int success = 0; debugStreamPrint(LOG_NLS, 1, "\n#### Start solver mixed equation system at time %f.", data->localData[0]->timeValue); memset(solverData->stateofSearch, 0, systemData->size); /* update pre iteration vars */ /* update iteration vars */ for(i=0;i<systemData->size;++i) solverData->iterationVarsPre[i] = *(systemData->iterationVarsPtr[i]); do { /* update pre iteration vars */ for(i=0;i<systemData->size;++i) solverData->iterationVars[i] = *(systemData->iterationVarsPtr[i]); /* solve continuous equation part * and update iteration variables in model */ systemData->solveContinuousPart(data); systemData->updateIterationExps(data); /* set new values of boolean variable */ for(i=0;i<systemData->size;++i) solverData->iterationVars2[i] = *(systemData->iterationVarsPtr[i]); found_solution = systemData->continuous_solution; debugStreamPrint(LOG_NLS, 0, "#### continuous system solution status = %d", found_solution); /* restart if any relation has changed */ if(checkRelations(data)) { updateRelationsPre(data); systemData->updateIterationExps(data); debugStreamPrint(LOG_NLS, 0, "#### System relation changed restart iteration"); if(mixedIterations++ > 200) found_solution = -4; /* mixedIterations++ > 200 */ } if(found_solution == -1) { /* system of equations failed */ found_solution = -2; debugStreamPrint(LOG_NLS, 0, "#### NO SOLUTION "); } else { found_solution = 1; for(i = 0; i < systemData->size; i++) { debugStreamPrint(LOG_NLS, 0, " check iterationVar[%d] = %d <-> %d", i, solverData->iterationVars[i], solverData->iterationVars2[i]); if(solverData->iterationVars[i] != solverData->iterationVars2[i]) { found_solution = 0; break; } } debugStreamPrint(LOG_NLS, 0, "#### SOLUTION = %c", found_solution ? 'T' : 'F'); } if(!found_solution ) { /* try next set of values*/ if(nextVar(solverData->stateofSearch, systemData->size)) { debugStreamPrint(LOG_NLS, 0, "#### set next STATE "); for(i = 0; i < systemData->size; i++) *(systemData->iterationVarsPtr[i]) = *(systemData->iterationPreVarsPtr[i]) != solverData->stateofSearch[i]; /* debug output */ if(ACTIVE_STREAM(LOG_NLS)) { const char * __name; for(i = 0; i < systemData->size; i++) { ix = (systemData->iterationVarsPtr[i]-data->localData[0]->booleanVars); __name = data->modelData->booleanVarsData[ix].info.name; debugStreamPrint(LOG_NLS, 0, "%s changed : %d -> %d", __name, solverData->iterationVars[i], *(systemData->iterationVarsPtr[i])); } } } else { /* while the initialization it's okay not a solution */ if(!data->simulationInfo->initial) { warningStreamPrint(LOG_STDOUT, 0, "Error solving mixed equation system with index %d at time %e", eqSystemNumber, data->localData[0]->timeValue); } data->simulationInfo->needToIterate = 1; found_solution = -1; /*TODO: "break simulation?"*/ } } /* we found a solution*/ if(found_solution == 1) { success = 1; if(ACTIVE_STREAM(LOG_NLS)) { const char * __name; debugStreamPrint(LOG_NLS, 0, "#### SOLUTION FOUND! (system %d)", eqSystemNumber); for(i = 0; i < systemData->size; i++) { ix = (systemData->iterationVarsPtr[i]-data->localData[0]->booleanVars); __name = data->modelData->booleanVarsData[ix].info.name; debugStreamPrint(LOG_NLS, 0, "%s = %d pre(%s)= %d", __name, *systemData->iterationVarsPtr[i], __name, *systemData->iterationPreVarsPtr[i]); } } } stepCount++; mixedIterations++; }while(!found_solution); messageClose(LOG_NLS); debugStreamPrint(LOG_NLS, 0, "#### Finished mixed equation system in steps %d.\n", stepCount); return success; }
fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo* eventInfo) { int i; ModelInstance* comp = (ModelInstance *)c; threadData_t *threadData = comp->threadData; if (invalidState(comp, "fmiEventUpdate", modelInitialized)) return fmiError; if (nullPointer(comp, "fmiEventUpdate", "eventInfo", eventInfo)) return fmiError; eventInfo->stateValuesChanged = fmiFalse; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: Start Event Update! Next Sample Event %g", eventInfo->nextEventTime); /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) if (stateSelection(comp->fmuData, threadData, 1, 1)) { 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 */ eventInfo->stateValuesChanged = fmiTrue; } storePreValues(comp->fmuData); /* activate sample event */ for(i=0; i<comp->fmuData->modelData->nSamples; ++i) { if(comp->fmuData->simulationInfo->nextSampleTimes[i] <= comp->fmuData->localData[0]->timeValue) { comp->fmuData->simulationInfo->samples[i] = 1; infoStreamPrint(LOG_EVENTS, 0, "[%ld] sample(%g, %g)", comp->fmuData->modelData->samplesInfo[i].index, comp->fmuData->modelData->samplesInfo[i].start, comp->fmuData->modelData->samplesInfo[i].interval); } } comp->fmuData->callback->functionDAE(comp->fmuData, threadData); /* deactivate sample events */ for(i=0; i<comp->fmuData->modelData->nSamples; ++i) { if(comp->fmuData->simulationInfo->samples[i]) { comp->fmuData->simulationInfo->samples[i] = 0; comp->fmuData->simulationInfo->nextSampleTimes[i] += comp->fmuData->modelData->samplesInfo[i].interval; } } for(i=0; i<comp->fmuData->modelData->nSamples; ++i) if((i == 0) || (comp->fmuData->simulationInfo->nextSampleTimes[i] < comp->fmuData->simulationInfo->nextSampleEvent)) comp->fmuData->simulationInfo->nextSampleEvent = comp->fmuData->simulationInfo->nextSampleTimes[i]; if(comp->fmuData->callback->checkForDiscreteChanges(comp->fmuData, threadData) || comp->fmuData->simulationInfo->needToIterate || checkRelations(comp->fmuData) || eventInfo->stateValuesChanged) { intermediateResults = fmiTrue; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: Need to iterate(discrete changes)!"); eventInfo->iterationConverged = fmiTrue; eventInfo->stateValueReferencesChanged = fmiFalse; eventInfo->stateValuesChanged = fmiTrue; eventInfo->terminateSimulation = fmiFalse; } else { intermediateResults = fmiFalse; eventInfo->iterationConverged = fmiTrue; eventInfo->stateValueReferencesChanged = fmiFalse; eventInfo->terminateSimulation = fmiFalse; } /* due to an event overwrite old values */ overwriteOldSimulationData(comp->fmuData); /* TODO: check the event iteration for relation * in fmi import and export. This is an workaround, * since the iteration seem not starting. */ storePreValues(comp->fmuData); updateRelationsPre(comp->fmuData); if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: intermediateResults = %d", intermediateResults); //Get Next Event Time double nextSampleEvent=0; nextSampleEvent = getNextSampleTimeFMU(comp->fmuData); if (nextSampleEvent == -1) { eventInfo->upcomingTimeEvent = fmiFalse; } else { eventInfo->upcomingTimeEvent = fmiTrue; eventInfo->nextEventTime = nextSampleEvent; } if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: Checked for Sample Events! Next Sample Event %g",eventInfo->nextEventTime); return fmiOK; /* catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) comp->functions.logger(c, comp->instanceName, fmiError, "error", "fmiEventUpdate: terminated by an assertion."); return fmiError; }