/*! 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;
}
Esempio n. 3
0
/*! \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;
}