/*! \fn initSample * * \param [ref] [data] * \param [in] [startTime] * \param [in] [stopTime] * * This function initializes sample-events. */ void initSample(DATA* data, double startTime, double stopTime) { TRACE_PUSH long i; data->callback->function_initSample(data); /* set-up sample */ data->simulationInfo.nextSampleEvent = stopTime + 1.0; /* should never be reached */ for(i=0; i<data->modelData.nSamples; ++i) { if(startTime < data->modelData.samplesInfo[i].start) { data->simulationInfo.nextSampleTimes[i] = data->modelData.samplesInfo[i].start; } else { data->simulationInfo.nextSampleTimes[i] = data->modelData.samplesInfo[i].start + ceil((startTime-data->modelData.samplesInfo[i].start) / data->modelData.samplesInfo[i].interval) * data->modelData.samplesInfo[i].interval; } if((i == 0) || (data->simulationInfo.nextSampleTimes[i] < data->simulationInfo.nextSampleEvent)) { data->simulationInfo.nextSampleEvent = data->simulationInfo.nextSampleTimes[i]; } } if(stopTime < data->simulationInfo.nextSampleEvent) { debugStreamPrint(LOG_EVENTS, 0, "there are no sample-events"); } else { debugStreamPrint(LOG_EVENTS, 0, "first sample-event at t = %g", data->simulationInfo.nextSampleEvent); } TRACE_POP }
/*! \fn checkForStateEvent * * \param [ref] [data] * \param [ref] [eventList] * * This function checks for events in interval=[oldTime, timeValue] * If a zero crossing function cause a sign change, root finding * process will start */ int checkForStateEvent(DATA* data, LIST *eventList) { TRACE_PUSH long i=0; debugStreamPrint(LOG_EVENTS, 1, "check state-event zerocrossing at time %g", data->localData[0]->timeValue); for(i=0; i<data->modelData.nZeroCrossings; i++) { int *eq_indexes; const char *exp_str = data->callback->zeroCrossingDescription(i,&eq_indexes); debugStreamPrintWithEquationIndexes(LOG_EVENTS, 1, eq_indexes, "%s", exp_str); if(sign(data->simulationInfo.zeroCrossings[i]) != sign(data->simulationInfo.zeroCrossingsPre[i])) { debugStreamPrint(LOG_EVENTS, 0, "changed: %s", (data->simulationInfo.zeroCrossingsPre[i] > 0) ? "TRUE -> FALSE" : "FALSE -> TRUE"); listPushFront(eventList, &(data->simulationInfo.zeroCrossingIndex[i])); } else { debugStreamPrint(LOG_EVENTS, 0, "unchanged: %s", (data->simulationInfo.zeroCrossingsPre[i] > 0) ? "TRUE -- TRUE" : "FALSE -- FALSE"); } if (DEBUG_STREAM(LOG_EVENTS)) messageClose(LOG_EVENTS); } if (DEBUG_STREAM(LOG_EVENTS)) messageClose(LOG_EVENTS); if(listLen(eventList) > 0) { TRACE_POP return 1; }
/*! \fn printRelationsDebug * * print all relations * * \param [in] [data] * \param [in] [stream] */ void printRelationsDebug(DATA *data, int stream) { TRACE_PUSH long i; debugStreamPrint(stream, 1, "status of relations at time=%.12g", data->localData[0]->timeValue); for(i=0; i<data->modelData.nRelations; i++) debugStreamPrint(stream, 0, "[%ld] %s = %c | pre(%s) = %c", i, data->callback->relationDescription(i), data->simulationInfo.relations[i] ? 'T' : 'F', data->callback->relationDescription(i), data->simulationInfo.relationsPre[i] ? 'T' : 'F'); messageClose(stream); 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 saveZeroCrossings * * Function saves all zero-crossing values * * \param [ref] [data] */ void saveZeroCrossings(DATA* data, threadData_t *threadData) { TRACE_PUSH long i = 0; debugStreamPrint(LOG_ZEROCROSSINGS, 0, "save all zero-crossings"); for(i=0; i<data->modelData.nZeroCrossings; i++) data->simulationInfo.zeroCrossingsPre[i] = data->simulationInfo.zeroCrossings[i]; data->callback->function_ZeroCrossings(data, threadData, data->simulationInfo.zeroCrossings); TRACE_POP }
/********************************************************************************************** * 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 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; }
/*! \fn printAllVarsDebug * * prints all variable values * * \param [in] [data] * \param [in] [ringSegment] */ void printAllVarsDebug(DATA *data, int ringSegment, int stream) { TRACE_PUSH long i; MODEL_DATA *mData = &(data->modelData); SIMULATION_INFO *sInfo = &(data->simulationInfo); debugStreamPrint(stream, 1, "Print values for buffer segment %d regarding point in time : %e", ringSegment, data->localData[ringSegment]->timeValue); debugStreamPrint(stream, 1, "states variables"); for(i=0; i<mData->nStates; ++i) debugStreamPrint(stream, 0, "%ld: %s = %g (pre: %g)", i+1, mData->realVarsData[i].info.name, data->localData[ringSegment]->realVars[i], sInfo->realVarsPre[i]); messageClose(stream); debugStreamPrint(stream, 1, "derivatives variables"); for(i=mData->nStates; i<2*mData->nStates; ++i) debugStreamPrint(stream, 0, "%ld: %s = %g (pre: %g)", i+1, mData->realVarsData[i].info.name, data->localData[ringSegment]->realVars[i], sInfo->realVarsPre[i]); messageClose(stream); debugStreamPrint(stream, 1, "other real values"); for(i=2*mData->nStates; i<mData->nVariablesReal; ++i) debugStreamPrint(stream, 0, "%ld: %s = %g (pre: %g)", i+1, mData->realVarsData[i].info.name, data->localData[ringSegment]->realVars[i], sInfo->realVarsPre[i]); messageClose(stream); debugStreamPrint(stream, 1, "integer variables"); for(i=0; i<mData->nVariablesInteger; ++i) debugStreamPrint(stream, 0, "%ld: %s = %ld (pre: %ld)", i+1, mData->integerVarsData[i].info.name, data->localData[ringSegment]->integerVars[i], sInfo->integerVarsPre[i]); messageClose(stream); debugStreamPrint(stream, 1, "boolean variables"); for(i=0; i<mData->nVariablesBoolean; ++i) debugStreamPrint(stream, 0, "%ld: %s = %s (pre: %s)", i+1, mData->booleanVarsData[i].info.name, data->localData[ringSegment]->booleanVars[i] ? "true" : "false", sInfo->booleanVarsPre[i] ? "true" : "false"); messageClose(stream); debugStreamPrint(stream, 1, "string variables"); for(i=0; i<mData->nVariablesString; ++i) debugStreamPrint(stream, 0, "%ld: %s = %s (pre: %s)", i+1, mData->stringVarsData[i].info.name, data->localData[ringSegment]->stringVars[i], sInfo->stringVarsPre[i]); messageClose(stream); messageClose(stream); TRACE_POP }
int checkCommandLineArguments(int argc, char **argv) { int i,j; /* This works not that well - but is probably better than no check */ assertStreamPrint(NULL, !strcmp(FLAG_NAME[FLAG_MAX], "FLAG_MAX"), "unbalanced command line flag structure: FLAG_NAME"); assertStreamPrint(NULL, !strcmp(FLAG_DESC[FLAG_MAX], "FLAG_MAX"), "unbalanced command line flag structure: FLAG_DESC"); assertStreamPrint(NULL, !strcmp(FLAG_DETAILED_DESC[FLAG_MAX], "FLAG_MAX"), "unbalanced command line flag structure: FLAG_DETAILED_DESC"); for(i=0; i<FLAG_MAX; ++i) { omc_flag[i] = 0; omc_flagValue[i] = NULL; } #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 1, "used command line options"); for(i=1; i<argc; ++i) debugStreamPrint(LOG_STDOUT, 0, "%s", argv[i]); messageClose(LOG_STDOUT); debugStreamPrint(LOG_STDOUT, 1, "interpreted command line options"); #endif for(i=1; i<argc; ++i) { int found=0; for(j=1; j<FLAG_MAX; ++j) { if((FLAG_TYPE[j] == FLAG_TYPE_FLAG) && flagSet(FLAG_NAME[j], 1, argv+i)) { if(omc_flag[j]) { warningStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); return 1; } omc_flag[j] = 1; found=1; #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 0, "-%s", FLAG_NAME[j]); #endif break; } else if((FLAG_TYPE[j] == FLAG_TYPE_OPTION) && flagSet(FLAG_NAME[j], 1, argv+i) && (i+1 < argc)) { if(omc_flag[j]) { warningStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); return 1; } omc_flag[j] = 1; omc_flagValue[j] = (char*)getFlagValue(FLAG_NAME[j], 1, argv+i); i++; found=1; #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 0, "-%s %s", FLAG_NAME[j], omc_flagValue[j]); #endif break; } else if((FLAG_TYPE[j] == FLAG_TYPE_OPTION) && optionSet(FLAG_NAME[j], 1, argv+i)) { if(omc_flag[j]) { warningStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); return 1; } omc_flag[j] = 1; omc_flagValue[j] = (char*)getOption(FLAG_NAME[j], 1, argv+i); found=1; #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 0, "-%s=%s", FLAG_NAME[j], omc_flagValue[j]); #endif break; } } if(!found) { #ifdef USE_DEBUG_OUTPUT messageClose(LOG_STDOUT); #endif warningStreamPrint(LOG_STDOUT, 0, "invalid command line option: %s", argv[i]); return 1; } } #ifdef USE_DEBUG_OUTPUT messageClose(LOG_STDOUT); #endif return 0; }