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(); }
// 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 }
// 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 }