/////////////////////////////////////////////////////////////////////////////// /// 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 }
// 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 }