static int simulationUpdate(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) { prefixedName_updateContinuousSystem(data, threadData); if (solverInfo->solverMethod == S_SYM_IMP_EULER) data->callback->symEulerUpdate(data, solverInfo->solverStepSize); saveZeroCrossings(data, threadData); messageClose(LOG_SOLVER); /***** Event handling *****/ if (measure_time_flag) rt_tick(SIM_TIMER_EVENT); int syncRet = handleTimers(data, threadData, solverInfo); int syncRet1; do { int eventType = checkEvents(data, threadData, solverInfo->eventLst, &(solverInfo->currentTime), solverInfo); if(eventType > 0 || syncRet == 2) /* event */ { threadData->currentErrorStage = ERROR_EVENTHANDLING; infoStreamPrint(LOG_EVENTS, 1, "%s event at time=%.12g", eventType == 1 ? "time" : "state", solverInfo->currentTime); /* prevent emit if noEventEmit flag is used */ if (!(omc_flag[FLAG_NOEVENTEMIT])) /* output left limit */ sim_result.emit(&sim_result, data, threadData); handleEvents(data, threadData, solverInfo->eventLst, &(solverInfo->currentTime), solverInfo); messageClose(LOG_EVENTS); threadData->currentErrorStage = ERROR_SIMULATION; solverInfo->didEventStep = 1; overwriteOldSimulationData(data); } else /* no event */ { solverInfo->laststep = solverInfo->currentTime; solverInfo->didEventStep = 0; } if (measure_time_flag) rt_accumulate(SIM_TIMER_EVENT); /***** End event handling *****/ /***** check state selection *****/ if (stateSelection(data, threadData, 1, 1)) { /* if new set is calculated reinit the solver */ solverInfo->didEventStep = 1; overwriteOldSimulationData(data); } /* Check for warning of variables out of range assert(min<x || x>xmax, ...)*/ data->callback->checkForAsserts(data, threadData); storePreValues(data); storeOldValues(data); syncRet1 = handleTimers(data, threadData, solverInfo); syncRet = syncRet1 == 0 ? syncRet : syncRet1; } while (syncRet1); return syncRet; }
/*! \fn copyStartValuestoInitValues * * Function to copy all start values to initial values * * \param [ref] [data] */ void copyStartValuestoInitValues(DATA *data) { TRACE_PUSH /* just copy all start values to initial */ setAllParamsToStart(data); setAllVarsToStart(data); storePreValues(data); overwriteOldSimulationData(data); TRACE_POP }
/*! \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 updateContinuousSystem * * Function to update the whole system with EventIteration. * Evaluate the functionDAE() * * \param [ref] [data] */ static void prefixedName_updateContinuousSystem(DATA *data, threadData_t *threadData) { TRACE_PUSH externalInputUpdate(data); data->callback->input_function(data, threadData); data->callback->functionODE(data, threadData); data->callback->functionAlgebraics(data, threadData); data->callback->output_function(data, threadData); data->callback->function_storeDelayed(data, threadData); storePreValues(data); TRACE_POP }
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; }
/*! \fn updateContinuousSystem * * Function to update the whole system with EventIteration. * Evaluate the functionDAE() * * \param [ref] [data] */ static void prefixedName_updateContinuousSystem(DATA *data, threadData_t *threadData) { TRACE_PUSH externalInputUpdate(data); data->callback->input_function(data, threadData); if (compiledInDAEMode) /* dae mode */ { data->simulationInfo->daeModeData->evaluateDAEResiduals(data, threadData, EVAL_ALGEBRAIC); } else /* ode mode */ { data->callback->functionODE(data, threadData); data->callback->functionAlgebraics(data, threadData); } data->callback->output_function(data, threadData); data->callback->setc_function(data, threadData); data->callback->function_storeDelayed(data, threadData); storePreValues(data); TRACE_POP }
static void fmtEmitStep(DATA* data, threadData_t *threadData, MEASURE_TIME* mt, SOLVER_INFO* solverInfo) { if(mt->fmtReal) { int i, flag=1; double tmpdbl; unsigned int tmpint; int total = data->modelData->modelDataXml.nFunctions + data->modelData->modelDataXml.nProfileBlocks; rt_tick(SIM_TIMER_OVERHEAD); rt_accumulate(SIM_TIMER_STEP); /* Disable time measurements if we have trouble writing to the file... */ flag = flag && 1 == fwrite(&mt->stepNo, sizeof(unsigned int), 1, mt->fmtInt); mt->stepNo++; flag = flag && 1 == fwrite(&(data->localData[0]->timeValue), sizeof(double), 1, mt->fmtReal); tmpdbl = rt_accumulated(SIM_TIMER_STEP); flag = flag && 1 == fwrite(&tmpdbl, sizeof(double), 1, mt->fmtReal); flag = flag && total == fwrite(rt_ncall_arr(SIM_TIMER_FIRST_FUNCTION), sizeof(uint32_t), total, mt->fmtInt); for(i=0; i<data->modelData->modelDataXml.nFunctions + data->modelData->modelDataXml.nProfileBlocks; i++) { tmpdbl = rt_accumulated(i + SIM_TIMER_FIRST_FUNCTION); flag = flag && 1 == fwrite(&tmpdbl, sizeof(double), 1, mt->fmtReal); } rt_accumulate(SIM_TIMER_OVERHEAD); if(!flag) { warningStreamPrint(LOG_SOLVER, 0, "Disabled time measurements because the output file could not be generated: %s", strerror(errno)); fclose(mt->fmtInt); fclose(mt->fmtReal); mt->fmtInt = NULL; mt->fmtReal = NULL; } } /* prevent emit if noEventEmit flag is used, if it's an event */ if ((omc_flag[FLAG_NOEVENTEMIT] && solverInfo->didEventStep == 0) || !omc_flag[FLAG_NOEVENTEMIT]) { sim_result.emit(&sim_result, data, threadData); } #if !defined(OMC_MINIMAL_RUNTIME) if (embedded_server_update(data->embeddedServerState, data->localData[0]->timeValue)) { solverInfo->didEventStep = 1; overwriteOldSimulationData(data); storePreValues(data); // Maybe?? storeOldValues(data); // Maybe?? sim_result.emit(&sim_result, data, threadData); } if (data->real_time_sync.enabled) { double time = data->localData[0]->timeValue; int64_t res = rt_ext_tp_sync_nanosec(&data->real_time_sync.clock, (uint64_t) (data->real_time_sync.scaling*(time-data->real_time_sync.time)*1e9)); int64_t maxLateNano = data->simulationInfo->stepSize*1e9*0.1*data->real_time_sync.scaling /* Maximum late time: 10% of step size */; if (res > maxLateNano) { int t=0,tMaxLate=0; const char *unit = prettyPrintNanoSec(res, &t); const char *unit2 = prettyPrintNanoSec(maxLateNano, &tMaxLate); errorStreamPrint(LOG_RT, 0, "Missed deadline at time %g; delta was %d %s (maxLate=%d %s)", time, t, unit, tMaxLate, unit2); } if (res > data->real_time_sync.maxLate) { data->real_time_sync.maxLate = res; } } printAllVarsDebug(data, 0, LOG_DEBUG); /* ??? */ #endif }
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; }
/*! \fn static int symbolic_initialization(DATA *data) * * \param [ref] [data] * * \author lochel */ static int symbolic_initialization(DATA *data, threadData_t *threadData, long numLambdaSteps) { TRACE_PUSH long step; int retVal; /* initial sample and delay before initial the system */ initDelay(data, data->simulationInfo->startTime); /* initialize all relations that are ZeroCrossings */ storePreValues(data); overwriteOldSimulationData(data); if (data->callback->useHomotopy && numLambdaSteps > 1) { long i; char buffer[4096]; FILE *pFile = NULL; modelica_real* realVars = (modelica_real*)calloc(data->modelData->nVariablesReal, sizeof(modelica_real)); modelica_integer* integerVars = (modelica_integer*)calloc(data->modelData->nVariablesInteger, sizeof(modelica_integer)); modelica_boolean* booleanVars = (modelica_boolean*)calloc(data->modelData->nVariablesBoolean, sizeof(modelica_boolean)); modelica_string* stringVars = (modelica_string*) omc_alloc_interface.malloc_uncollectable(data->modelData->nVariablesString * sizeof(modelica_string)); MODEL_DATA *mData = data->modelData; assertStreamPrint(threadData, 0 != realVars, "out of memory"); assertStreamPrint(threadData, 0 != integerVars, "out of memory"); assertStreamPrint(threadData, 0 != booleanVars, "out of memory"); assertStreamPrint(threadData, 0 != stringVars, "out of memory"); for(i=0; i<mData->nVariablesReal; ++i) { realVars[i] = mData->realVarsData[i].attribute.start; } for(i=0; i<mData->nVariablesInteger; ++i) { integerVars[i] = mData->integerVarsData[i].attribute.start; } for(i=0; i<mData->nVariablesBoolean; ++i) { booleanVars[i] = mData->booleanVarsData[i].attribute.start; } for(i=0; i<mData->nVariablesString; ++i) { stringVars[i] = mData->stringVarsData[i].attribute.start; } if(ACTIVE_STREAM(LOG_INIT)) { sprintf(buffer, "%s_homotopy.csv", mData->modelFilePrefix); pFile = fopen(buffer, "wt"); fprintf(pFile, "%s,", "lambda"); for(i=0; i<mData->nVariablesReal; ++i) fprintf(pFile, "%s,", mData->realVarsData[i].info.name); fprintf(pFile, "\n"); } infoStreamPrint(LOG_INIT, 1, "homotopy process"); for(step=0; step<numLambdaSteps; ++step) { data->simulationInfo->lambda = ((double)step)/(numLambdaSteps-1); if(data->simulationInfo->lambda > 1.0) { data->simulationInfo->lambda = 1.0; } if(0 == step) data->callback->functionInitialEquations_lambda0(data, threadData); else data->callback->functionInitialEquations(data, threadData); infoStreamPrint(LOG_INIT, 0, "lambda = %g done", data->simulationInfo->lambda); if(ACTIVE_STREAM(LOG_INIT)) { fprintf(pFile, "%.16g,", data->simulationInfo->lambda); for(i=0; i<mData->nVariablesReal; ++i) fprintf(pFile, "%.16g,", data->localData[0]->realVars[i]); fprintf(pFile, "\n"); } if(check_nonlinear_solutions(data, 0) || check_linear_solutions(data, 0) || check_mixed_solutions(data, 0)) break; setAllStartToVars(data); } messageClose(LOG_INIT); if(ACTIVE_STREAM(LOG_INIT)) fclose(pFile); for(i=0; i<mData->nVariablesReal; ++i) mData->realVarsData[i].attribute.start = realVars[i]; for(i=0; i<mData->nVariablesInteger; ++i) mData->integerVarsData[i].attribute.start = integerVars[i]; for(i=0; i<mData->nVariablesBoolean; ++i) mData->booleanVarsData[i].attribute.start = booleanVars[i]; for(i=0; i<mData->nVariablesString; ++i) mData->stringVarsData[i].attribute.start = stringVars[i]; free(realVars); free(integerVars); free(booleanVars); omc_alloc_interface.free_uncollectable(stringVars); } else { data->simulationInfo->lambda = 1.0; data->callback->functionInitialEquations(data, threadData); } storeRelations(data); /* check for over-determined systems */ retVal = data->callback->functionRemovedInitialEquations(data, threadData); TRACE_POP return retVal; }