Exemplo n.º 1
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
}
Exemplo n.º 2
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
}