コード例 #1
0
ファイル: model_help.c プロジェクト: jschoenbohm/OMCompiler
/*! \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
}
コード例 #2
0
/*! \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;
    }
コード例 #3
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;
}
コード例 #4
0
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;
}