/*! performQSSSimulation(DATA* data, SOLVER_INFO* solverInfo) * * \param [ref] [data] * \param [ref] [solverInfo] * * This function performs the simulation controlled by solverInfo. */ modelica_integer prefixedName_performQSSSimulation(DATA* data, SOLVER_INFO* solverInfo) { TRACE_PUSH SIMULATION_INFO *simInfo = &(data->simulationInfo); MODEL_DATA *mData = &(data->modelData); uinteger currStepNo = 0; modelica_integer retValIntegrator = 0; modelica_integer retValue = 0; uinteger ind = 0; solverInfo->currentTime = simInfo->startTime; warningStreamPrint(LOG_STDOUT, 0, "This QSS method is under development and should not be used yet."); if (data->callback->initialAnalyticJacobianA(data)) { infoStreamPrint(LOG_STDOUT, 0, "Jacobian or sparse pattern is not generated or failed to initialize."); return UNKNOWN; } printSparseStructure(data, LOG_SOLVER); /* *********************************************************************************** */ /* Initialization */ uinteger i = 0; /* loop var */ SIMULATION_DATA *sData = (SIMULATION_DATA*)data->localData[0]; modelica_real* state = sData->realVars; modelica_real* stateDer = sData->realVars + data->modelData.nStates; const SPARSE_PATTERN* pattern = &(data->simulationInfo.analyticJacobians[data->callback->INDEX_JAC_A].sparsePattern); const uinteger ROWS = data->simulationInfo.analyticJacobians[data->callback->INDEX_JAC_A].sizeRows; const uinteger STATES = data->modelData.nStates; uinteger numDer = 0; /* number of derivatives influenced by state k */ modelica_boolean fail = 0; modelica_real* qik = NULL; /* Approximation of states */ modelica_real* xik = NULL; /* states */ modelica_real* derXik = NULL; /* Derivative of states */ modelica_real* tq = NULL; /* Time of approximation, because not all approximations are calculated at a specific time, each approx. has its own timestamp */ modelica_real* tx = NULL; /* Time of the states, because not all states are calculated at a specific time, each state has its own timestamp */ modelica_real* tqp = NULL; /* Time of the next change in state */ modelica_real* nQh = NULL; /* next value of the state */ modelica_real* dQ = NULL; /* change in quantity of every state, default = nominal*10^-4 */ /* allocate memory*/ qik = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (qik == NULL) ? 1 : ( 0 | fail); xik = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (xik == NULL) ? 1 : ( 0 | fail); derXik = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (derXik == NULL) ? 1 : ( 0 | fail); tq = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (tq == NULL) ? 1 : ( 0 | fail); tx = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (tx == NULL) ? 1 : ( 0 | fail); tqp = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (tqp == NULL) ? 1 : ( 0 | fail); nQh = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (nQh == NULL) ? 1 : ( 0 | fail); dQ = (modelica_real*)calloc(STATES, sizeof(modelica_real)); fail = (dQ == NULL) ? 1 : ( 0 | fail); if (fail) return OO_MEMORY; /* end - allocate memory */ /* further initialization of local variables */ modelica_real diffQ = 0.0, dTnextQ = 0.0, nextQ = 0.0; for (i = 0; i < STATES; i++) { dQ[i] = 0.0001 * data->modelData.realVarsData[i].attribute.nominal; tx[i] = tq[i] = simInfo->startTime; qik[i] = state[i]; xik[i] = state[i]; derXik[i] = stateDer[i]; retValue = deltaQ(data, dQ[i], i, &dTnextQ, &nextQ, &diffQ); if (OK != retValue) return retValue; tqp[i] = tq[i] + dTnextQ; nQh[i] = nextQ; } /* Transform the sparsity pattern into a data structure for an index based access. */ modelica_integer* der = (modelica_integer*)calloc(ROWS, sizeof(modelica_integer)); if (NULL==der) return OO_MEMORY; for (i = 0; i < ROWS; i++) der[i] = -1; /* how many states are involved in each derivative */ /* **** This is needed if we have QSS2 or higher **** */ /* uinteger* numStatesInDer = calloc(ROWS,sizeof(uinteger)); if (NULL==numStatesInDer) return OO_MEMORY; */ /* * dx1/dt = x2 * dx2/dt = x1 + x2 * lead to * StatesInDer[0]-{ 2 } * StatesInDer[1]-{ 1, 2 } */ /* uinteger** StatesInDer = calloc(ROWS,sizeof(uinteger*)); if (NULL==StatesInDer) return OO_MEMORY; */ /* count number of states in each derivative*/ /* for (i = 0; i < pattern->leadindex[ROWS-1]; i++) numStatesInDer[ pattern->index[i] ]++; */ /* collect memory for all stateindices */ /* for (i = 0; i < ROWS; i++) { *(StatesInDer + i) = calloc(numStatesInDer[i], sizeof(uinteger)); if (NULL==*(StatesInDer + i)) return OO_MEMORY; } retValue = getStatesInDer(pattern->index, pattern->leadindex, ROWS, STATES, StatesInDer); if (OK != retValue) return retValue; */ /* retValue = getDerWithStateK(pattern->index, pattern->leadindex, der, &numDer, 0); if (OK != retValue) return retValue; */ /* End of transformation */ #ifdef D FILE* fid=NULL; fid = fopen("log_qss.txt","w"); #endif /* *********************************************************************************** */ /***** Start main simulation loop *****/ while(solverInfo->currentTime < simInfo->stopTime) { modelica_integer success = 0; threadData->currentErrorStage = ERROR_SIMULATION; omc_alloc_interface.collect_a_little(); #if !defined(OMC_EMCC) /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) { #endif #ifdef USE_DEBUG_TRACE if (useStream[LOG_TRACE]) printf("TRACE: push loop step=%u, time=%.12g\n", currStepNo, solverInfo->currentTime); #endif #ifdef D fprintf(fid,"t = %.8f\n",solverInfo->currentTime); fprintf(fid,"%16s\t%16s\t%16s\t%16s\t%16s\t%16s\n","tx","x","dx","tq","q","tqp"); for (i = 0; i < STATES; i++) { fprintf(fid,"%16.8f\t%16.8f\t%16.8f\t%16.8f\t%16.8f\t%16.8f\n",tx[i],xik[i],derXik[i],tq[i],qik[i],tqp[i]); } #endif currStepNo++; ind = minStep(tqp, STATES); if (isnan(tqp[ind])) { #ifdef D fprintf(fid,"Exit caused by #QNAN!\tind=%d",ind); #endif return ISNAN; } if (isinf(tqp[ind])) { /* If all derivatives are zero, the states stay constant and only the * time propagates till stop->time. */ warningStreamPrint(LOG_STDOUT, 0, "All derivatives are zero at time %f!.\n", sData->timeValue); solverInfo->currentTime = simInfo->stopTime; sData->timeValue = solverInfo->currentTime; continue; } qik[ind] = nQh[ind]; xik[ind] = qik[ind]; state[ind] = qik[ind]; tx[ind] = tqp[ind]; tq[ind] = tqp[ind]; solverInfo->currentTime = tqp[ind]; #ifdef D fprintf(fid,"Index: %d\n\n",ind); #endif /* the state[ind] will change again in dTnextQ*/ retValue = deltaQ(data, dQ[ind], ind, &dTnextQ, &nextQ, &diffQ); if (OK != retValue) return retValue; tqp[ind] = tq[ind] + dTnextQ; nQh[ind] = nextQ; if (0 != strcmp("ia", MMC_STRINGDATA(data->simulationInfo.outputFormat))) { communicateStatus("Running", (solverInfo->currentTime-simInfo->startTime)/(simInfo->stopTime-simInfo->startTime)); } /* get the derivatives depending on state[ind] */ for (i = 0; i < ROWS; i++) der[i] = -1; retValue = getDerWithStateK(pattern->index, pattern->leadindex, der, &numDer, ind); uinteger k = 0, j = 0; for (k = 0; k < numDer; k++) { j = der[k]; if (j != ind) { xik[j] = xik[j] + derXik[j] * (solverInfo->currentTime - tx[j]); state[j] = xik[j]; tx[j] = solverInfo->currentTime; } } /* * Recalculate all equations which are affected by state[ind]. * Unfortunately all equations will be calculated up to now. And we need to evaluate * the equations as f(t,q) and not f(t,x). So all states were saved onto a local stack * and overwritten by q. After evaluating the equations the states are written back. */ for (i = 0; i < STATES; i++) { xik[i] = state[i]; /* save current state */ state[i] = qik[i]; /* overwrite current state for dx/dt = f(t,q) */ } /* update continous system */ sData->timeValue = solverInfo->currentTime; externalInputUpdate(data); data->callback->input_function(data); data->callback->functionODE(data); data->callback->functionAlgebraics(data); data->callback->output_function(data); data->callback->function_storeDelayed(data); for (i = 0; i < STATES; i++) { state[i] = xik[i]; /* restore current state */ } /* * Get derivatives affected by state[ind] and write back ALL derivatives. After that we have * states and derivatives for different times tx. */ for (k = 0; k < numDer; k++) { j = der[k]; derXik[j] = stateDer[j]; } derXik[ind] = stateDer[ind]; /* not in every case part of the above derivatives */ for (i = 0; i < STATES; i++) { stateDer[i] = derXik[i]; /* write back all derivatives */ } /* recalculate the time of next change only for the affected states */ for (k = 0; k < numDer; k++) { j = der[k]; retValue = deltaQ(data, dQ[j], j, &dTnextQ, &nextQ, &diffQ); if (OK != retValue) return retValue; tqp[j] = solverInfo->currentTime + dTnextQ; nQh[j] = nextQ; } /*sData->timeValue = solverInfo->currentTime;*/ solverInfo->laststep = solverInfo->currentTime; sim_result.emit(&sim_result, data); /* check if terminate()=true */ if (terminationTerminate) { printInfo(stdout, TermInfo); fputc('\n', stdout); infoStreamPrint(LOG_STDOUT, 0, "Simulation call terminate() at time %f\nMessage : %s", data->localData[0]->timeValue, TermMsg); simInfo->stopTime = solverInfo->currentTime; } /* terminate for some cases: * - integrator fails * - non-linear system failed to solve * - assert was called */ if (retValIntegrator) { retValue = -1 + retValIntegrator; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Integrator failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if (check_nonlinear_solutions(data, 0)) { retValue = -2; infoStreamPrint(LOG_STDOUT, 0, "model terminate | non-linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if (check_linear_solutions(data, 0)) { retValue = -3; infoStreamPrint(LOG_STDOUT, 0, "model terminate | linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if (check_mixed_solutions(data, 0)) { retValue = -4; infoStreamPrint(LOG_STDOUT, 0, "model terminate | mixed system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } success = 1; #if !defined(OMC_EMCC) } /* catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { retValue = -1; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Simulation terminated by an assert at time: %g", data->localData[0]->timeValue); break; } TRACE_POP /* pop loop */ } /* End of main loop */ #ifdef D fprintf(fid,"t = %.8f\n",solverInfo->currentTime); fprintf(fid,"%16s\t%16s\t%16s\t%16s\t%16s\t%16s\n","tx","x","dx","tq","q","tqp"); for (i = 0; i < STATES; i++) { fprintf(fid,"%16.8f\t%16.8f\t%16.8f\t%16.8f\t%16.8f\t%16.8f\n",tx[i],xik[i],derXik[i],tq[i],qik[i],tqp[i]); } fclose(fid); #endif /* free memory*/ free(der); /* for (i = 0; i < ROWS; i++) free(*(StatesInDer + i)); free(StatesInDer); free(numStatesInDer); */ free(qik); free(xik); free(derXik); free(tq); free(tx); free(tqp); free(nQh); free(dQ); /* end - free memory */ TRACE_POP return retValue; }
/*! \fn performSimulation(DATA* data, SOLVER_INFO* solverInfo) * * \param [ref] [data] * \param [ref] [solverInfo] * * This function performs the simulation controlled by solverInfo. */ int prefixedName_performSimulation(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) { TRACE_PUSH int retValIntegrator=0; int retValue=0; int i, retry=0; unsigned int __currStepNo = 0; SIMULATION_INFO *simInfo = &(data->simulationInfo); solverInfo->currentTime = simInfo->startTime; MEASURE_TIME fmt; fmtInit(data, &fmt); printAllVarsDebug(data, 0, LOG_DEBUG); /* ??? */ printSparseStructure(data, LOG_SOLVER); modelica_boolean syncStep = 0; /***** Start main simulation loop *****/ while(solverInfo->currentTime < simInfo->stopTime) { int success = 0; threadData->currentErrorStage = ERROR_SIMULATION; #ifdef USE_DEBUG_TRACE if(useStream[LOG_TRACE]) printf("TRACE: push loop step=%u, time=%.12g\n", __currStepNo, solverInfo->currentTime); #endif omc_alloc_interface.collect_a_little(); /* try */ #if !defined(OMC_EMCC) MMC_TRY_INTERNAL(simulationJumpBuffer) #endif { clear_rt_step(data); rotateRingBuffer(data->simulationData, 1, (void**) data->localData); modelica_boolean syncEventStep = solverInfo->didEventStep || syncStep; /***** Calculation next step size *****/ if(syncEventStep) { infoStreamPrint(LOG_SOLVER, 0, "offset value for the next step: %.16g", (solverInfo->currentTime - solverInfo->laststep)); } else { if (solverInfo->solverNoEquidistantGrid) { if (solverInfo->currentTime >= solverInfo->lastdesiredStep) { double tmpTime = solverInfo->currentTime; do { __currStepNo++; solverInfo->currentStepSize = (double)(__currStepNo*(simInfo->stopTime-simInfo->startTime))/(simInfo->numSteps) + simInfo->startTime - solverInfo->currentTime; }while(solverInfo->currentStepSize <= 0); } } else { __currStepNo++; } } solverInfo->currentStepSize = (double)(__currStepNo*(simInfo->stopTime-simInfo->startTime))/(simInfo->numSteps) + simInfo->startTime - solverInfo->currentTime; solverInfo->lastdesiredStep = solverInfo->currentTime + solverInfo->currentStepSize; /* if retry reduce stepsize */ if(0 != retry) { solverInfo->currentStepSize /= 2; } /***** End calculation next step size *****/ checkForSynchronous(data, solverInfo); /* check for next time event */ checkForSampleEvent(data, solverInfo); /* if regular output point and last time events are almost equals * skip that step and go further */ if (solverInfo->currentStepSize < 1e-15 && syncEventStep){ __currStepNo++; continue; } /* * integration step determine all states by a integration method * update continuous system */ retValIntegrator = simulationStep(data, threadData, solverInfo); if (S_OPTIMIZATION == solverInfo->solverMethod) break; syncStep = simulationUpdate(data, threadData, solverInfo); retry = 0; /* reset retry */ fmtEmitStep(data, threadData, &fmt, solverInfo->didEventStep); saveDasslStats(solverInfo); checkSimulationTerminated(data, solverInfo); /* terminate for some cases: * - integrator fails * - non-linear system failed to solve * - assert was called */ if(retValIntegrator) { retValue = -1 + retValIntegrator; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Integrator failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_nonlinear_solutions(data, 0)) { retValue = -2; infoStreamPrint(LOG_STDOUT, 0, "model terminate | non-linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_linear_solutions(data, 0)) { retValue = -3; infoStreamPrint(LOG_STDOUT, 0, "model terminate | linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_mixed_solutions(data, 0)) { retValue = -4; infoStreamPrint(LOG_STDOUT, 0, "model terminate | mixed system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } success = 1; } #if !defined(OMC_EMCC) MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) /* catch */ { if(0 == retry) { retrySimulationStep(data, threadData, solverInfo); retry = 1; } else { retValue = -1; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Simulation terminated by an assert at time: %g", data->localData[0]->timeValue); break; } } TRACE_POP /* pop loop */ } /* end while solver */ fmtClose(&fmt); TRACE_POP return retValue; }
/*! \fn performSimulation(DATA* data, SOLVER_INFO* solverInfo) * * \param [ref] [data] * \param [ref] [solverInfo] * * This function performs the simulation controlled by solverInfo. */ int prefixedName_performSimulation(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo) { TRACE_PUSH int retValIntegrator=0; int retValue=0; int i, retry=0, steadStateReached=0; unsigned int __currStepNo = 0; SIMULATION_INFO *simInfo = data->simulationInfo; solverInfo->currentTime = simInfo->startTime; MEASURE_TIME fmt; fmtInit(data, &fmt); printAllVarsDebug(data, 0, LOG_DEBUG); /* ??? */ if (!compiledInDAEMode) { printSparseStructure(&(data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A].sparsePattern), data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A].sizeRows, data->simulationInfo->analyticJacobians[data->callback->INDEX_JAC_A].sizeCols, LOG_SOLVER, "ODE sparse pattern"); } else { printSparseStructure(data->simulationInfo->daeModeData->sparsePattern, data->simulationInfo->daeModeData->nResidualVars, data->simulationInfo->daeModeData->nResidualVars, LOG_SOLVER, "DAE sparse pattern"); } if(terminationTerminate) { printInfo(stdout, TermInfo); fputc('\n', stdout); infoStreamPrint(LOG_STDOUT, 0, "Simulation call terminate() at initialization (time %f)\nMessage : %s", data->localData[0]->timeValue, TermMsg); data->simulationInfo->stopTime = solverInfo->currentTime; } else { modelica_boolean syncStep = 0; /***** Start main simulation loop *****/ while(solverInfo->currentTime < simInfo->stopTime || !simInfo->useStopTime) { int success = 0; threadData->currentErrorStage = ERROR_SIMULATION; #ifdef USE_DEBUG_TRACE if(useStream[LOG_TRACE]) { printf("TRACE: push loop step=%u, time=%.12g\n", __currStepNo, solverInfo->currentTime); } #endif /* check for steady state */ if (omc_flag[FLAG_STEADY_STATE]) { if (0 < data->modelData->nStates) { int i; double maxDer = 0.0; double currDer; for(i=data->modelData->nStates; i<2*data->modelData->nStates; ++i) { currDer = fabs(data->localData[0]->realVars[i] / data->modelData->realVarsData[i].attribute.nominal); if(maxDer < currDer) maxDer = currDer; } if (maxDer < steadyStateTol) { steadStateReached=1; infoStreamPrint(LOG_STDOUT, 0, "steady state reached at time = %g\n * max(|d(x_i)/dt|/nominal(x_i)) = %g\n * relative tolerance = %g", solverInfo->currentTime, maxDer, steadyStateTol); break; } } else throwStreamPrint(threadData, "No states in model. Flag -steadyState can only be used if states are present."); } omc_alloc_interface.collect_a_little(); /* try */ #if !defined(OMC_EMCC) MMC_TRY_INTERNAL(simulationJumpBuffer) #endif { printAllVars(data, 0, LOG_SOLVER_V); clear_rt_step(data); if (!compiledInDAEMode) /* do not use ringbuffer for daeMode */ rotateRingBuffer(data->simulationData, 1, (void**) data->localData); modelica_boolean syncEventStep = solverInfo->didEventStep || syncStep; /***** Calculation next step size *****/ if(syncEventStep) { infoStreamPrint(LOG_SOLVER, 0, "offset value for the next step: %.16g", (solverInfo->currentTime - solverInfo->laststep)); } else { if (solverInfo->solverNoEquidistantGrid) { if (solverInfo->currentTime >= solverInfo->lastdesiredStep) { do { __currStepNo++; solverInfo->currentStepSize = (double)(__currStepNo*(simInfo->stopTime-simInfo->startTime))/(simInfo->numSteps) + simInfo->startTime - solverInfo->currentTime; } while(solverInfo->currentStepSize <= 0); } } else { __currStepNo++; } } solverInfo->currentStepSize = (double)(__currStepNo*(simInfo->stopTime-simInfo->startTime))/(simInfo->numSteps) + simInfo->startTime - solverInfo->currentTime; solverInfo->lastdesiredStep = solverInfo->currentTime + solverInfo->currentStepSize; /* if retry reduce stepsize */ if (0 != retry) { solverInfo->currentStepSize /= 2; } /***** End calculation next step size *****/ checkForSynchronous(data, solverInfo); /* check for next time event */ checkForSampleEvent(data, solverInfo); /* if regular output point and last time events are almost equals * skip that step and go further */ if (solverInfo->currentStepSize < 1e-15 && syncEventStep){ __currStepNo++; continue; } /* * integration step determine all states by a integration method * update continuous system */ infoStreamPrint(LOG_SOLVER, 1, "call solver from %g to %g (stepSize: %.15g)", solverInfo->currentTime, solverInfo->currentTime + solverInfo->currentStepSize, solverInfo->currentStepSize); retValIntegrator = simulationStep(data, threadData, solverInfo); infoStreamPrint(LOG_SOLVER, 0, "finished solver step %g", solverInfo->currentTime); messageClose(LOG_SOLVER); if (S_OPTIMIZATION == solverInfo->solverMethod) break; syncStep = simulationUpdate(data, threadData, solverInfo); retry = 0; /* reset retry */ fmtEmitStep(data, threadData, &fmt, solverInfo); saveIntegratorStats(solverInfo); checkSimulationTerminated(data, solverInfo); /* terminate for some cases: * - integrator fails * - non-linear system failed to solve * - assert was called */ if (retValIntegrator) { retValue = -1 + retValIntegrator; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Integrator failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_nonlinear_solutions(data, 0)) { retValue = -2; infoStreamPrint(LOG_STDOUT, 0, "model terminate | non-linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_linear_solutions(data, 0)) { retValue = -3; infoStreamPrint(LOG_STDOUT, 0, "model terminate | linear system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } else if(check_mixed_solutions(data, 0)) { retValue = -4; infoStreamPrint(LOG_STDOUT, 0, "model terminate | mixed system solver failed. | Simulation terminated at time %g", solverInfo->currentTime); break; } success = 1; } #if !defined(OMC_EMCC) MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { /* catch */ if(0 == retry) { retrySimulationStep(data, threadData, solverInfo); retry = 1; } else { retValue = -1; infoStreamPrint(LOG_STDOUT, 0, "model terminate | Simulation terminated by an assert at time: %g", data->localData[0]->timeValue); break; } } TRACE_POP /* pop loop */ } /* end while solver */ } /* end else */ fmtClose(&fmt); if (omc_flag[FLAG_STEADY_STATE] && !steadStateReached) { warningStreamPrint(LOG_STDOUT, 0, "Steady state has not been reached.\nThis may be due to too restrictive relative tolerance (%g) or short stopTime (%g).", steadyStateTol, simInfo->stopTime); } TRACE_POP return retValue; }