Esempio n. 1
1
 void exec()
 {
     fmi2Flag = fmu.doStep(c, time.to_seconds(), h.to_seconds(), fmi2True);
     if (fmi2Flag == fmi2Discard) {
         fmi2Boolean b;
         // check if model requests to end simulation
         if (fmi2OK != fmu.getBooleanStatus(c, fmi2Terminated, &b)) {
             return SC_REPORT_ERROR(name(),"could not complete simulation of the model. getBooleanStatus return other than fmi2OK");
         }
         if (b == fmi2True) {
             return SC_REPORT_ERROR(name(),"the model requested to end the simulation");
         }
         return SC_REPORT_ERROR(name(),"could not complete simulation of the model");
     }
     if (fmi2Flag != fmi2OK)
         return SC_REPORT_ERROR(name(),"could not complete simulation of the model");
     
     // FIXME: res = outputRow(fmu, c, time, file, separator, fmi2False); // output values for this step
     auto res = getRealOutput(&fmu, c, output_index);
     oval = sub_signal(time, time+h,
                 [this,res](const sc_time& t)
                 {
                     return res;
                 }
            );
 }
Esempio n. 2
0
 //Implementing the abstract semantics
 void init()
 {
     time = SC_ZERO_TIME;
     fmuResourceLocation = getTempResourcesLocation();
     visible = fmi2False;
     //~ callbacks = {fmuLogger, calloc, free, NULL, fmu};
     toleranceDefined = fmi2False;
     tolerance = 0;
     //~ vs = 0;
     
     // load the FMU
     loadFMU(fmuFileName.c_str(), &fmu);
     
     // run the simulation
     // instantiate the fmu   
     md = fmu.modelDescription;
     guid = getAttributeValue((Element *)md, att_guid);
     instanceName = getAttributeValue((Element *)getCoSimulation(md),
         att_modelIdentifier);
     c = fmu.instantiate(instanceName, fmi2CoSimulation, guid,
         fmuResourceLocation, &callbacks, visible, fmi2False/*logging off*/);
     free(fmuResourceLocation);
     if (!c) return SC_REPORT_ERROR(name(),"could not instantiate model");
     
     defaultExp = getDefaultExperiment(md);
     if (defaultExp) tolerance = getAttributeDouble(defaultExp, att_tolerance, &vs);
     if (vs == valueDefined) {
         toleranceDefined = fmi2True;
     }
     
     fmi2Flag = fmu.setupExperiment(c, toleranceDefined, tolerance, 0, fmi2True, 1000/* FIXME */);
     if (fmi2Flag > fmi2Warning) {
         return SC_REPORT_ERROR(name(),"could not initialize model; failed FMI setup experiment");
     }
     
     fmi2Flag = fmu.enterInitializationMode(c);
     if (fmi2Flag > fmi2Warning) {
         return SC_REPORT_ERROR(name(),"could not initialize model; failed FMI enter initialization mode");
     }
     
     fmi2Flag = fmu.exitInitializationMode(c);
     if (fmi2Flag > fmi2Warning) {
         return SC_REPORT_ERROR(name(),"could not initialize model; failed FMI exit initialization mode");
     }
     
     // output solution for time t0
     // FIXME: outputRow(fmu, c, tStart, file, separator, fmi2False); // output values
     //~ auto res = getRealOutput(fmu, c, 0);
     //~ oval = sub_signal(time, time+h,
                 //~ [this,res](const sc_time& t)
                 //~ {
                     //~ return res;
                 //~ }
            //~ );
     //~ WRITE_MULTIPORT(oport1, oval)
     //~ time += h;
     //~ wait(time - sc_time_stamp());
     ival1 = iport1.read();
 }
Esempio n. 3
0
 void clean()
 {
     // end simulation
     fmu.terminate(c);
     fmu.freeInstance(c);
 
     #ifdef _MSC_VER
         FreeLibrary(fmu.dllHandle);
     #else
         dlclose(fmu.dllHandle);
     #endif
     freeModelDescription(fmu.modelDescription);
     deleteUnzippedFiles();
 }
Esempio n. 4
0
///////////////////////////////////////////////////////////////////////////////
/// Simulate the given FMU using the forward euler method.
/// Time events are processed by reducing step size to exactly hit tNext.
/// State events are checked and fired only at the end of an Euler step. 
/// The simulator may therefore miss state events and fires state events typically too late.
///
///\param fmu FMU.
///\param tEnd Ending time of simulation.
///\param h Tiem step size.
///\param loggingOn Controller for logging.
///\param separator Separator character.
///\return 0 if there is no error occurred.
///////////////////////////////////////////////////////////////////////////////
static int simulate(FMU* fmu, double tEnd, double h, fmiBoolean loggingOn, char separator) {
		
  int i, n;
  fmiBoolean timeEvent, stateEvent, stepEvent;
  double time;  
  ModelDescription* md;            // handle to the parsed XML file        
  const char* guid;                // global unique id of the fmu
  fmiCallbackFunctions callbacks;  // called by the model during simulation
  fmiComponent c;                  // instance of the fmu 
  fmiStatus fmiFlag;               // return code of the fmu functions
  fmiReal t0 = 0;                  // start time
	fmiBoolean toleranceControlled = fmiFalse;
  int nSteps = 0;
  FILE* file;

	fmiValueReference vr;			// add it to get value reference for variables

  //Note: User defined references
  //Begin------------------------------------------------------------------
  fmiValueReference vru[1], vry[1]; // value references for two input and two output variables 
  //End--------------------------------------------------------------------

	ScalarVariable** vars = fmu->modelDescription->modelVariables;		// add it to get variables
	int k;							// add a counter for variables
	fmiReal ru1, ru2, ry, ry1, ry2;	// add real variables for input and output
	fmiInteger ix, iy;				// add integer variables for input and output
	fmiBoolean bx, by;				// add boolean variables for input and output
	fmiString sx, sy;				// Zuo: add string variables for input and output
	fmiStatus status;				// Zuo: add stauus for fmi

	printDebug("Instantiate the fmu.\n");		
  // instantiate the fmu
  md = fmu->modelDescription;
  guid = getString(md, att_guid);
	printfDebug("Got GUID = %s!\n", guid);	
  callbacks.logger = fmuLogger;
  callbacks.allocateMemory = calloc;
  callbacks.freeMemory = free;
	printDebug("Got callbacks!\n");
	printfDebug("Model Identifer is %s\n", getModelIdentifier(md));
 	c = fmu->instantiateSlave(getModelIdentifier(md), guid, "Model1", "", 10, fmiFalse, fmiFalse, callbacks, loggingOn);
  if (!c) {
    printError("could not instantiate slaves.\n");
    return 1;
  }
  printDebug("Instantiated slaves!\n");	

  // Open result file
  if (!(file=fopen(RESULT_FILE, "w"))) {
    printfError("could not write %s because:\n", RESULT_FILE);
    printfError("    %s\n", strerror(errno));
    return 1;
  }
  printDebug("Open results file!\n");    

  // Set the start time and initialize
  time = t0;

	printDebug("start to initialize fmu!\n");	   
	fmiFlag =  fmu->initializeSlave(c, t0, fmiTrue, tEnd);	
	printDebug("Initialized fmu!\n");
  if (fmiFlag > fmiWarning) {
    printError("could not initialize model");
    return 1;
  }
 
  // Output solution for time t0 
  printDebug("start to outputRow");
  //outputRow(fmu, c, t0, file, separator, TRUE);  // output column names
  //outputRow(fmu, c, t0, file, separator, FALSE); // output initla value of fmu 
  outputdata(t0, file, separator, 0, 0, TRUE);
  
  printDebug("start to getValueReference");
  ///////////////////////////////////////////////////////////////////////////// 
  // Get value references for input and output varibles
  // Note: User needs to specify the name of variables for their own fmus
  //Begin------------------------------------------------------------------
  vru[0] = getValueReference(getVariableByName(md, "Toa"));
  //vru[1] = getValueReference(getVariableByName(md, "u2"));
  vry[0] = getValueReference(getVariableByName(md, "TrmSou"));
  //vry[1] = getValueReference(getVariableByName(md, "y2"));
  //End--------------------------------------------------------------------
  
  printDebug("Enter in simulation loop.\n");	

  // enter the simulation loop
  while (time < tEnd) {
    if (loggingOn) printf("Step %d to t=%.4f\n", nSteps, time);		  

    ///////////////////////////////////////////////////////////////////////////
    // Step 1: get values of output variables	from slaves
    for (k=0; vars[k]; k++) {
	    ScalarVariable* sv = vars[k];
	    if (getAlias(sv)!=enu_noAlias) continue;	
	    if (getCausality(sv) != enu_output) continue; // only get output variable
      vr = getValueReference(sv);

      switch (sv->typeSpec->type){
        case elm_Real:
          fmu->getReal(c, &vr, 1, &ry); 
          break;
        case elm_Integer:
          fmu->getInteger(c, &vr, 1, &iy);  
          break;
        case elm_Boolean:
          fmu->getBoolean(c, &vr, 1, &by);
          break;
        case elm_String:
          fmu->getString(c, &vr, 1, &sy);
          break;
      }


      // Allocate values to cooresponding varibles on master program
      // Note: User needs to specify the output variables for their own fmu 
      //Begin------------------------------------------------------------------
      if (vr == vry[0]) ry1 = ry;
      //else if(vr == vry[1]) ry2 = ry;
      //End--------------------------------------------------------------------
    } 
    
    ///////////////////////////////////////////////////////////////////////////
    // Step 2: compute on master side 
    // Note: User can adjust the computing schemes of mater program
    //Begin------------------------------------------------------------------
     printf("Dymola output = %f\n", ry1);
	 //= ry2 + 3.0; 
    ru1 = 293;
    //End--------------------------------------------------------------------

    //////////////////////////////////////////////////////////////////////////
    // Step 3: set input variables back to slaves
    for (k=0; vars[k]; k++) {
      ScalarVariable* sv = vars[k];
      if (getAlias(sv)!=enu_noAlias) continue;
	    if (getCausality(sv) != enu_input) continue; // only set input variable
        vr = getValueReference(sv);
        // Note: User can adjust the settings for input variables
        //Begin------------------------------------------------------------------
        switch (sv->typeSpec->type){
          case elm_Real:

            if(vr == vru[0]) {
              fmu->setReal(c, &vr, 1, &ru1); 				
              printDebug("Set u1.\n");
            }
            //else if (vr == vru[1]) {
            //  fmu->setReal(c, &vr, 1, &ru2);
            //  printDebug("Set u2.\n");
            //}
            else
              printf("Warning: no data given for input variable.\n");
            break;
          case elm_Integer:
            fmu->setInteger(c, &vr, 1, &ix);  
            break;
          case elm_Boolean:
            fmu->setBoolean(c, &vr, 1, &bx);
            break;
          case elm_String:
		    printDebug("Get string in simulatio()");
            fmu->setString(c, &vr, 1, &sx);
            break;        
        }
        //End--------------------------------------------------------------------        
    } 
    
    // Advance to next time step
    status = fmu->doStep(c, time, h, fmiTrue);  
    // Terminate this row
    // fprintf(file, "\n");  (comment out this line to get rid of the blank line between the results in the csv file.)    
   
    time = min(time+h, tEnd);
    //outputRow(fmu, c, time, file, separator, FALSE); // output values for this step
	outputdata(time, file, separator, ru1, ry1, FALSE);
    nSteps++;
   
  } // end of while  

  // Cleanup
  fclose(file);

  // Print simulation summary 
  if (loggingOn) printf("Step %d to t=%.4f\n", nSteps, time);		
  printf("Simulation from %g to %g terminated successful\n", t0, tEnd);
  printf("  steps ............ %d\n", nSteps);
  printf("  fixed step size .. %g\n", h);

  return 0; // success
}
Esempio n. 5
0
///////////////////////////////////////////////////////////////////////////////
/// Output time and all non-alias variables in CSV format.
/// If separator is ',', columns are separated by ',' and '.' is used for floating-point numbers.
/// Otherwise, the given separator (e.g. ';' or '\t') is to separate columns, and ',' is used for 
/// floating-point numbers.
///
///\param fmu FMU.
///\param c FMI component.
///\param time Time when data is outputed.
///\param separator Separator in file.
///\param header Indicator of row head.
///////////////////////////////////////////////////////////////////////////////
static void outputRow(FMU *fmu, fmiComponent c, double time, FILE* file, char separator, boolean header, double x, double y) {
  int k;
  fmiReal r;
  fmiInteger i;
  fmiBoolean b;
  fmiString s;
  fmiValueReference vr;				
  ScalarVariable** vars = fmu->modelDescription->modelVariables;
  char buffer[32];
  
  // Print first column
  if (header) 
    fprintf(file, "time"); 
  else {
    if (separator==',') 
      fprintf(file, "%.4f", time);				
    else {
      // Separator is e.g. ';' or '\t'
      doubleToCommaString(buffer, time);
      fprintf(file, "%s", buffer);       
    }
  }
    
  // Print all other columns
  for (k=0; vars[k]; k++) {
    ScalarVariable* sv = vars[k];
    if (getAlias(sv)!=enu_noAlias) continue;
    if (header) {
      // Output names only
      fprintf(file, "%c%s", separator, getName(sv));
    }
    else {
      // Output values
      vr = getValueReference(sv);
      switch (sv->typeSpec->type){
        case elm_Real:
          fmu->getReal(c, &vr, 1, &r);
          if (separator==',') 
            fprintf(file, ",%.4f", r);				
        else {
          // Separator is e.g. ';' or '\t'
          doubleToCommaString(buffer, r);
          fprintf(file, "%c%s", separator, buffer);       
          }
          break;
        case elm_Integer:
          fmu->getInteger(c, &vr, 1, &i);
          fprintf(file, "%c%d", separator, i);
          break;
        case elm_Boolean:
          fmu->getBoolean(c, &vr, 1, &b);
          fprintf(file, "%c%d", separator, b);
          break;
        case elm_String:
		  printDebug("get string in outputrow");
          //fmu->getString(c, &vr, 1, &s);
          //fprintf(file, "%c%s", separator, s);
          break;
      }
    }
  } // for
    
  // Terminate this row
  fprintf(file, "\n"); 
}
Esempio n. 6
0
// simulate the given FMU from tStart = 0 to tEnd.
static int simulate(FMU* fmu, double tEnd, double h, fmi2Boolean loggingOn, char separator,
                    int nCategories, const fmi2String categories[]) {
    double time;
    double tStart = 0;                      // start time
    const char *guid;                       // global unique id of the fmu
    const char *instanceName;               // instance name
    fmi2Component c;                        // instance of the fmu
    fmi2Status fmi2Flag;                    // return code of the fmu functions
    char *fmuResourceLocation = getTempResourcesLocation(); // path to the fmu resources as URL, "file://C:\QTronic\sales"
    fmi2Boolean visible = fmi2False;        // no simulator user interface

    fmi2CallbackFunctions callbacks = {fmuLogger, calloc, free, NULL, fmu};  // called by the model during simulation
    ModelDescription* md;                      // handle to the parsed XML file
    fmi2Boolean toleranceDefined = fmi2False;  // true if model description define tolerance
    fmi2Real tolerance = 0;                    // used in setting up the experiment
    ValueStatus vs = 0;
    int nSteps = 0;
    Element *defaultExp;
    FILE* file;

    // instantiate the fmu
    md = fmu->modelDescription;
    guid = getAttributeValue((Element *)md, att_guid);
    instanceName = getAttributeValue((Element *)getCoSimulation(md), att_modelIdentifier);
    c = fmu->instantiate(instanceName, fmi2CoSimulation, guid, fmuResourceLocation,
                    &callbacks, visible, loggingOn);
    free(fmuResourceLocation);
    if (!c) return error("could not instantiate model");

    if (nCategories > 0) {
        fmi2Flag = fmu->setDebugLogging(c, fmi2True, nCategories, categories);
        if (fmi2Flag > fmi2Warning) {
            return error("could not initialize model; failed FMI set debug logging");
        }
    }

    defaultExp = getDefaultExperiment(md);
    if (defaultExp) tolerance = getAttributeDouble(defaultExp, att_tolerance, &vs);
    if (vs == valueDefined) {
        toleranceDefined = fmi2True;
    }

    fmi2Flag = fmu->setupExperiment(c, toleranceDefined, tolerance, tStart, fmi2True, tEnd);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI setup experiment");
    }
    fmi2Flag = fmu->enterInitializationMode(c);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI enter initialization mode");
    }
    fmi2Flag = fmu->exitInitializationMode(c);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI exit initialization mode");
    }

    // open result file
    if (!(file = fopen(RESULT_FILE, "w"))) {
        printf("could not write %s because:\n", RESULT_FILE);
        printf("    %s\n", strerror(errno));
        return 0; // failure
    }

    // output solution for time t0
    outputRow(fmu, c, tStart, file, separator, fmi2True);  // output column names
    outputRow(fmu, c, tStart, file, separator, fmi2False); // output values

    // enter the simulation loop
    time = tStart;
    while (time < tEnd) {
        fmi2Flag = fmu->doStep(c, time, h, fmi2True);
        if (fmi2Flag == fmi2Discard) {
            fmi2Boolean b;
            // check if model requests to end simulation
            if (fmi2OK != fmu->getBooleanStatus(c, fmi2Terminated, &b)) {
                return error("could not complete simulation of the model. getBooleanStatus return other than fmi2OK");
            }
            if (b == fmi2True) {
                return error("the model requested to end the simulation");
            }
            return error("could not complete simulation of the model");
        }
        if (fmi2Flag != fmi2OK) return error("could not complete simulation of the model");
        time += h;
        outputRow(fmu, c, time, file, separator, fmi2False); // output values for this step
        nSteps++;
    }

    // end simulation
    fmu->terminate(c);
    fmu->freeInstance(c);
    fclose(file);

    // print simulation summary
    printf("Simulation from %g to %g terminated successful\n", tStart, tEnd);
    printf("  steps ............ %d\n", nSteps);
    printf("  fixed step size .. %g\n", h);
    return 1; // success
}
Esempio n. 7
0
// simulate the given FMU using the forward euler method.
// time events are processed by reducing step size to exactly hit tNext.
// state events are checked and fired only at the end of an Euler step. 
// the simulator may therefore miss state events and fires state events typically too late.
static int simulate(FMU* fmu, double tEnd, double h, fmi2Boolean loggingOn, char separator,
                    int nCategories, const fmi2String categories[]) {
    int i;
    double dt, tPre;
    fmi2Boolean timeEvent, stateEvent, stepEvent, terminateSimulation;
    double time;
    int nx;                          // number of state variables
    int nz;                          // number of state event indicators
    double *x = NULL;                // continuous states
    double *xdot = NULL;             // the corresponding derivatives in same order
    double *z = NULL;                // state event indicators
    double *prez = NULL;             // previous values of state event indicators
    fmi2EventInfo eventInfo;         // updated by calls to initialize and eventUpdate
    ModelDescription* md;            // handle to the parsed XML file
    const char* guid;                // global unique id of the fmu
    fmi2CallbackFunctions callbacks = {fmuLogger, calloc, free, NULL, fmu}; // called by the model during simulation
    fmi2Component c;                 // instance of the fmu
    fmi2Status fmi2Flag;             // return code of the fmu functions
    fmi2Real tStart = 0;             // start time
    fmi2Boolean toleranceDefined = fmi2False; // true if model description define tolerance
    fmi2Real tolerance = 0;          // used in setting up the experiment
    fmi2Boolean visible = fmi2False; // no simulator user interface
    const char *instanceName;        // instance name
    char *fmuResourceLocation = getTempResourcesLocation(); // path to the fmu resources as URL, "file://C:\QTronic\sales"
    int nSteps = 0;
    int nTimeEvents = 0;
    int nStepEvents = 0;
    int nStateEvents = 0;
    FILE* file;
    ValueStatus vs;

    // instantiate the fmu
    md = fmu->modelDescription;
    guid = getAttributeValue((Element *)md, att_guid);
    instanceName = getAttributeValue((Element *)getModelExchange(md), att_modelIdentifier);
    c = fmu->instantiate(instanceName, fmi2ModelExchange, guid, fmuResourceLocation,
                        &callbacks, visible, loggingOn);
    free(fmuResourceLocation);
    if (!c) return error("could not instantiate model");

    if (nCategories > 0) {
        fmi2Flag = fmu->setDebugLogging(c, fmi2True, nCategories, categories);
        if (fmi2Flag > fmi2Warning) {
            return error("could not initialize model; failed FMI set debug logging");
        }
    }

    // allocate memory
    nx = getDerivativesSize(getModelStructure(md)); // number of continuous states is number of derivatives
                                                    // declared in model structure
    nz = getAttributeInt((Element *)md, att_numberOfEventIndicators, &vs); // number of event indicators
    x    = (double *) calloc(nx, sizeof(double));
    xdot = (double *) calloc(nx, sizeof(double));
    if (nz>0) {
        z    =  (double *) calloc(nz, sizeof(double));
        prez =  (double *) calloc(nz, sizeof(double));
    }
    if ((!x || !xdot) || (nz>0 && (!z || !prez))) return error("out of memory");

    // open result file
    if (!(file = fopen(RESULT_FILE, "w"))) {
        printf("could not write %s because:\n", RESULT_FILE);
        printf("    %s\n", strerror(errno));
        free (x);
        free(xdot);
        free(z);
        free(prez);
        return 0; // failure
    }

    // setup the experiment, set the start time
    time = tStart;
    fmi2Flag = fmu->setupExperiment(c, toleranceDefined, tolerance, tStart, fmi2True, tEnd);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI setup experiment");
    }

    // initialize
    fmi2Flag = fmu->enterInitializationMode(c);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI enter initialization mode");
    }
    fmi2Flag = fmu->exitInitializationMode(c);
    if (fmi2Flag > fmi2Warning) {
        return error("could not initialize model; failed FMI exit initialization mode");
    }

    // event iteration
    eventInfo.newDiscreteStatesNeeded = fmi2True;
    eventInfo.terminateSimulation = fmi2False;
    while (eventInfo.newDiscreteStatesNeeded && !eventInfo.terminateSimulation) {
        // update discrete states
        fmi2Flag = fmu->newDiscreteStates(c, &eventInfo);
        if (fmi2Flag > fmi2Warning) return error("could not set a new discrete state");
    }

    if (eventInfo.terminateSimulation) {
        printf("model requested termination at t=%.16g\n", time);
    } else {
        // enter Continuous-Time Mode
        fmu->enterContinuousTimeMode(c);
        // output solution for time tStart
        outputRow(fmu, c, tStart, file, separator, fmi2True);  // output column names
        outputRow(fmu, c, tStart, file, separator, fmi2False); // output values

        // enter the simulation loop
        while (time < tEnd) {
            // get current state and derivatives
            fmi2Flag = fmu->getContinuousStates(c, x, nx);
            if (fmi2Flag > fmi2Warning) return error("could not retrieve states");
            fmi2Flag = fmu->getDerivatives(c, xdot, nx);
            if (fmi2Flag > fmi2Warning) return error("could not retrieve derivatives");

            // advance time
            tPre = time;
            time = min(time+h, tEnd);
            timeEvent = eventInfo.nextEventTimeDefined && eventInfo.nextEventTime <= time;
            if (timeEvent) time = eventInfo.nextEventTime;
            dt = time - tPre;
            fmi2Flag = fmu->setTime(c, time);
            if (fmi2Flag > fmi2Warning) error("could not set time");

            // perform one step
            for (i = 0; i < nx; i++) x[i] += dt * xdot[i]; // forward Euler method
            fmi2Flag = fmu->setContinuousStates(c, x, nx);
            if (fmi2Flag > fmi2Warning) return error("could not set states");
            if (loggingOn) printf("Step %d to t=%.16g\n", nSteps, time);

            // check for state event
            for (i = 0; i < nz; i++) prez[i] = z[i];
            fmi2Flag = fmu->getEventIndicators(c, z, nz);
            if (fmi2Flag > fmi2Warning) return error("could not retrieve event indicators");
            stateEvent = FALSE;
            for (i=0; i<nz; i++)
                stateEvent = stateEvent || (prez[i] * z[i] < 0);

            // check for step event, e.g. dynamic state selection
            fmi2Flag = fmu->completedIntegratorStep(c, fmi2True, &stepEvent, &terminateSimulation);
            if (fmi2Flag > fmi2Warning) return error("could not complete intgrator step");
            if (terminateSimulation) {
                printf("model requested termination at t=%.16g\n", time);
                break; // success
            }

            // handle events
            if (timeEvent || stateEvent || stepEvent) {
                fmu->enterEventMode(c);
                if (timeEvent) {
                    nTimeEvents++;
                    if (loggingOn) printf("time event at t=%.16g\n", time);
                }
                if (stateEvent) {
                    nStateEvents++;
                    if (loggingOn) for (i=0; i<nz; i++)
                        printf("state event %s z[%d] at t=%.16g\n",
                               (prez[i]>0 && z[i]<0) ? "-\\-" : "-/-", i, time);
                }
                if (stepEvent) {
                    nStepEvents++;
                    if (loggingOn) printf("step event at t=%.16g\n", time);
                }

                // event iteration in one step, ignoring intermediate results
                eventInfo.newDiscreteStatesNeeded = fmi2True;
                eventInfo.terminateSimulation = fmi2False;
                while (eventInfo.newDiscreteStatesNeeded && !eventInfo.terminateSimulation) {
                    // update discrete states
                    fmi2Flag = fmu->newDiscreteStates(c, &eventInfo);
                    if (fmi2Flag > fmi2Warning) return error("could not set a new discrete state");
                }
                if (eventInfo.terminateSimulation) {
                    printf("model requested termination at t=%.16g\n", time);
                    break; // success
                }

                // enter Continuous-Time Mode
                fmu->enterContinuousTimeMode(c);

                // check for change of value of states
                if (eventInfo.valuesOfContinuousStatesChanged && loggingOn) {
                    printf("continuous state values changed at t=%.16g\n", time);
                }

                if (eventInfo.nominalsOfContinuousStatesChanged && loggingOn){
                    printf("nominals of continuous state changed  at t=%.16g\n", time);
                }

            } // if event
            outputRow(fmu, c, time, file, separator, fmi2False); // output values for this step
            nSteps++;
        } // while
    }
    // cleanup
    fmu->terminate(c);
    fmu->freeInstance(c);
    fclose(file);
    if (x != NULL) free(x);
    if (xdot != NULL) free(xdot);
    if (z != NULL) free(z);
    if (prez != NULL) free(prez);

    // print simulation summary
    printf("Simulation from %g to %g terminated successful\n", tStart, tEnd);
    printf("  steps ............ %d\n", nSteps);
    printf("  fixed step size .. %g\n", h);
    printf("  time events ...... %d\n", nTimeEvents);
    printf("  state events ..... %d\n", nStateEvents);
    printf("  step events ...... %d\n", nStepEvents);

    return 1; // success
}
Esempio n. 8
0
// simulate the given FMU from tStart = 0 to tEnd.
static int simulate(FMU* fmu, double tEnd, double h, fmiBoolean loggingOn, char separator) {
    double time;
    double tStart = 0;               // start time
    const char* guid;                // global unique id of the fmu
    fmiComponent c;                  // instance of the fmu 
    fmiStatus fmiFlag;               // return code of the fmu functions
    char* fmuLocation = getTempFmuLocation(); // path to the fmu as URL, "file://C:\QTronic\sales"
    const char* mimeType = "application/x-fmu-sharedlibrary"; // denotes tool in case of tool coupling
    fmiReal timeout = 1000;          // wait period in milli seconds, 0 for unlimited wait period"
    fmiBoolean visible = fmiFalse;   // no simulator user interface
    fmiBoolean interactive = fmiFalse; // simulation run without user interaction
    fmiCallbackFunctions callbacks;  // called by the model during simulation
    ModelDescription* md;            // handle to the parsed XML file
    int nSteps = 0;
    FILE* file;

    // instantiate the fmu
    md = fmu->modelDescription;
    guid = getString(md, att_guid);
    callbacks.logger = fmuLogger;
    callbacks.allocateMemory = calloc;
    callbacks.freeMemory = free;
    callbacks.stepFinished = NULL; // fmiDoStep has to be carried out synchronously
    c = fmu->instantiateSlave(getModelIdentifier(md), guid, fmuLocation, mimeType,
                              timeout, visible, interactive, callbacks, loggingOn);
    free(fmuLocation);
    if (!c) return error("could not instantiate model");

    // open result file
    if (!(file=fopen(RESULT_FILE, "w"))) {
        printf("could not write %s because:\n", RESULT_FILE);
        printf("    %s\n", strerror(errno));
        return 0; // failure
    }

    // StopTimeDefined=fmiFalse means: ignore value of tEnd
    fmiFlag = fmu->initializeSlave(c, tStart, fmiTrue, tEnd);
    if (fmiFlag > fmiWarning)  return error("could not initialize model");
    
    // output solution for time t0
    outputRow(fmu, c, tStart, file, separator, fmiTrue);  // output column names
    outputRow(fmu, c, tStart, file, separator, fmiFalse); // output values

    // enter the simulation loop
    time = tStart;
    while (time < tEnd) {
        fmiFlag = fmu->doStep(c, time, h, fmiTrue);
        if (fmiFlag != fmiOK)  return error("could not complete simulation of the model");
        time += h;
        outputRow(fmu, c, time, file, separator, fmiFalse); // output values for this step
        nSteps++;
    }

    // end simulation
    fmiFlag = fmu->terminateSlave(c);
    fmu->freeSlaveInstance(c);
    fclose(file);

    // print simulation summary 
    printf("Simulation from %g to %g terminated successful\n", tStart, tEnd);
    printf("  steps ............ %d\n", nSteps);
    printf("  fixed step size .. %g\n", h);
    return 1; // success
}
Esempio n. 9
0
// simulate the given FMU using the forward euler method.
// time events are processed by reducing step size to exactly hit tNext.
// state events are checked and fired only at the end of an Euler step.
// the simulator may therefore miss state events and fires state events typically too late.
static int simulate(FMU* fmu, double tEnd, double h, fmiBoolean loggingOn, char separator) {
    int i, n;
    double dt, tPre;
    fmiBoolean timeEvent, stateEvent, stepEvent;
    double time;
    int nx;                          // number of state variables
    int nz;                          // number of state event indicators
    double *x;                       // continuous states
    double *xdot;                    // the crresponding derivatives in same order
    double *z = NULL;                // state event indicators
    double *prez = NULL;             // previous values of state event indicators
    fmiEventInfo eventInfo;          // updated by calls to initialize and eventUpdate
    ModelDescription* md;            // handle to the parsed XML file
    const char* guid;                // global unique id of the fmu
    fmiCallbackFunctions callbacks;  // called by the model during simulation
    fmiComponent c;                  // instance of the fmu
    fmiStatus fmiFlag;               // return code of the fmu functions
    fmiReal t0 = 0;                  // start time
    fmiBoolean toleranceControlled = fmiFalse;
    int nSteps = 0;
    int nTimeEvents = 0;
    int nStepEvents = 0;
    int nStateEvents = 0;
    FILE* file;

    // instantiate the fmu
    md = fmu->modelDescription;
    guid = getString(md, att_guid);
    callbacks.logger = fmuLogger;
    callbacks.allocateMemory = calloc;
    callbacks.freeMemory = free;
    c = fmu->instantiateModel(getModelIdentifier(md), guid, callbacks, loggingOn);
    if (!c) return error("could not instantiate model");

    // allocate memory
    nx = getNumberOfStates(md);
    nz = getNumberOfEventIndicators(md);
    x    = (double *) calloc(nx, sizeof(double));
    xdot = (double *) calloc(nx, sizeof(double));
    if (nz>0) {
        z    =  (double *) calloc(nz, sizeof(double));
        prez =  (double *) calloc(nz, sizeof(double));
    }
    if (!x || !xdot || nz>0 && (!z || !prez)) return error("out of memory");

    // open result file
    if (!(file=fopen(RESULT_FILE, "w"))) {
        printf("could not write %s because:\n", RESULT_FILE);
        printf("    %s\n", strerror(errno));
        return 0; // failure
    }

    // set the start time and initialize
    time = t0;
    fmiFlag =  fmu->setTime(c, t0);
    if (fmiFlag > fmiWarning) return error("could not set time");
    fmiFlag =  fmu->initialize(c, toleranceControlled, t0, &eventInfo);
    if (fmiFlag > fmiWarning)  error("could not initialize model");
    if (eventInfo.terminateSimulation) {
        printf("model requested termination at init");
        tEnd = time;
    }

    // output solution for time t0
    outputRow(fmu, c, t0, file, separator, TRUE);  // output column names
    outputRow(fmu, c, t0, file, separator, FALSE); // output values

    // enter the simulation loop
    while (time < tEnd) {
        // get current state and derivatives
        fmiFlag = fmu->getContinuousStates(c, x, nx);
        if (fmiFlag > fmiWarning) return error("could not retrieve states");
        fmiFlag = fmu->getDerivatives(c, xdot, nx);
        if (fmiFlag > fmiWarning) return error("could not retrieve derivatives");

        // advance time
        tPre = time;
        time = min(time+h, tEnd);
        timeEvent = eventInfo.upcomingTimeEvent && eventInfo.nextEventTime < time;
        if (timeEvent) time = eventInfo.nextEventTime;
        dt = time - tPre;
        fmiFlag = fmu->setTime(c, time);
        if (fmiFlag > fmiWarning) error("could not set time");

        // perform one step
        for (i=0; i<nx; i++) x[i] += dt*xdot[i]; // forward Euler method
        fmiFlag = fmu->setContinuousStates(c, x, nx);
        if (fmiFlag > fmiWarning) return error("could not set states");
        if (loggingOn) printf("Step %d to t=%.16g\n", nSteps, time);

        // Check for step event, e.g. dynamic state selection
        fmiFlag = fmu->completedIntegratorStep(c, &stepEvent);
        if (fmiFlag > fmiWarning) return error("could not complete intgrator step");

        // Check for state event
        for (i=0; i<nz; i++) prez[i] = z[i];
        fmiFlag = fmu->getEventIndicators(c, z, nz);
        if (fmiFlag > fmiWarning) return error("could not retrieve event indicators");
        stateEvent = FALSE;
        for (i=0; i<nz; i++)
            stateEvent = stateEvent || (prez[i] * z[i] < 0);

        // handle events
        if (timeEvent || stateEvent || stepEvent) {

            if (timeEvent) {
                nTimeEvents++;
                if (loggingOn) printf("time event at t=%.16g\n", time);
            }
            if (stateEvent) {
                nStateEvents++;
                if (loggingOn) for (i=0; i<nz; i++)
                        printf("state event %s z[%d] at t=%.16g\n",
                               (prez[i]>0 && z[i]<0) ? "-\\-" : "-/-", i, time);
            }
            if (stepEvent) {
                nStepEvents++;
                if (loggingOn) printf("step event at t=%.16g\n", time);
            }

            // event iteration in one step, ignoring intermediate results
            fmiFlag = fmu->eventUpdate(c, fmiFalse, &eventInfo);
            if (fmiFlag > fmiWarning) return error("could not perform event update");

            // terminate simulation, if requested by the model
            if (eventInfo.terminateSimulation) {
                printf("model requested termination at t=%.16g\n", time);
                break; // success
            }

            // check for change of value of states
            if (eventInfo.stateValuesChanged && loggingOn) {
                printf("state values changed at t=%.16g\n", time);
            }

            // check for selection of new state variables
            if (eventInfo.stateValueReferencesChanged && loggingOn) {
                printf("new state variables selected at t=%.16g\n", time);
            }

        } // if event
        outputRow(fmu, c, time, file, separator, FALSE); // output values for this step
        nSteps++;
    } // while

    // cleanup
    fclose(file);
    if (x!=NULL) free(x);
    if (xdot!= NULL) free(xdot);
    if (z!= NULL) free(z);
    if (prez!= NULL) free(prez);

    // print simulation summary
    printf("Simulation from %g to %g terminated successful\n", t0, tEnd);
    printf("  steps ............ %d\n", nSteps);
    printf("  fixed step size .. %g\n", h);
    printf("  time events ...... %d\n", nTimeEvents);
    printf("  state events ..... %d\n", nStateEvents);
    printf("  step events ...... %d\n", nStepEvents);

    return 1; // success
}