/*******************************************************//** * Loads the DLL. * * @return The DLL. *******************************************************/ int MainController::loadDll( ) { Logger::getInstance()->printDebug2 (_T("MainController::loadDll unzipFolderPath_: %s\n"), unzipFolderPath_); const char* modelId = getModelIdentifier(fmu_->modelDescription); int len = strlen(unzipFolderPath_) + strlen(DLL_DIR_STR) + strlen(modelId) + strlen(_T(".dll")) + 1; dllFilePath_ = (char *)calloc(sizeof(char), len); sprintf_s(dllFilePath_, len, _T("%s%s%s.dll"), unzipFolderPath_, DLL_DIR_STR, modelId ); if (dllFilePath_ == NULL){ Logger::getInstance()->printfError(_T("Failed to allocate memory for wText\n"), dllFilePath_); return 1; } Logger::getInstance()->printDebug2 (_T("dllFilePath_: %s \n"), dllFilePath_); HINSTANCE h; h = LoadLibrary(dllFilePath_); if(!h) { Logger::getInstance()->printfError(_T("Can not load %s\n"), dllFilePath_); exit(EXIT_FAILURE); } fmu_->dllHandle = h; fmu_->getVersion = (fGetVersion) getAdr("fmiGetVersion"); fmu_->instantiateSlave = (fInstantiateSlave) getAdr("fmiInstantiateSlave"); fmu_->freeSlaveInstance = (fFreeSlaveInstance) getAdr( "fmiFreeSlaveInstance"); fmu_->setDebugLogging = (fSetDebugLogging) getAdr( "fmiSetDebugLogging"); fmu_->setReal = (fSetReal) getAdr( "fmiSetReal"); fmu_->setInteger = (fSetInteger) getAdr( "fmiSetInteger"); fmu_->setBoolean = (fSetBoolean) getAdr( "fmiSetBoolean"); fmu_->setString = (fSetString) getAdr( "fmiSetString"); fmu_->initializeSlave = (fInitializeSlave) getAdr("fmiInitializeSlave"); fmu_->getReal = (fGetReal) getAdr( "fmiGetReal"); fmu_->getInteger = (fGetInteger) getAdr( "fmiGetInteger"); fmu_->getBoolean = (fGetBoolean) getAdr("fmiGetBoolean"); fmu_->getString = (fGetString) getAdr( "fmiGetString"); fmu_->doStep = (fDoStep) getAdr("fmiDoStep"); fmu_->terminateSlave = (fTerminateSlave) getAdr("fmiTerminateSlave"); //resetSlave does not seem to be implented fmu_->resetSlave = (fResetSlave) getAdr("fmiResetSlave"); setState_( simStateNative_3_init_dllLoaded ); return 0; }
static void* getAdr(FMU *fmu, const char* functionName) { char name[BUFSIZE]; void* fp; sprintf(name, "%s_%s", getModelIdentifier(fmu->modelDescription), functionName); fp = GetProcAddress(fmu->dllHandle, name); if (!fp) { printf ("error: Function %s not found in dll\n", name); } return fp; }
/////////////////////////////////////////////////////////////////////////////// /// Get address of specific function from specific dll /// ///\param fmu Name of dll file. ///\param funnam Function name . ///\return Address of the specific function. ////////////////////////////////////////////////////////////////////////////// static void* getAdr(FMU *fmu, const char* funNam){ char name[BUFSIZE]; void* fp; sprintf(name, "%s_%s", getModelIdentifier(fmu->modelDescription), funNam); // Zuo: adding the model name in front of funciton name fp = GetProcAddress(fmu->dllHandle, name); if (!fp) { printfError("Function %s not found in dll.\n", name); } return fp; }
/*******************************************************//** * Gets the address. * * @param funNam The fun nam. * * @return null if it fails, else the address. *******************************************************/ void* MainController::getAdr(const char* funNam){ char name[MSG_BUFFER_SIZE]; void* fp; sprintf_s(name, MSG_BUFFER_SIZE, _T("%s_%s"), getModelIdentifier(fmu_->modelDescription), funNam); // Zuo: adding the model name in front of function name fp = GetProcAddress(fmu_->dllHandle, name); if (!fp) { Logger::getInstance()->printfError(_T("Function %s not found in dll\n"), name); } return fp; }
/*******************************************************//** * Gets the instantiate slave. * * @return . *******************************************************/ int MainController::instantiateSlave_() { Logger::getInstance()->printDebug(_T("-=MainController::instantiateSlave_=-\n")); Logger::getInstance()->printDebug(_T("MainController::simulateHelperInit\n")); _TCHAR currentDirectory[MAX_PATH] = _T(""); _TCHAR currentDirectory2[MAX_PATH] = _T(""); _TCHAR exeDirectory[MAX_PATH] = _T(""); isLoggingEnabled_ = 1; const char* guid; // global unique id of the fmu const char* modelIdentifier; // fmiCallbackFunctions callbackFunctions; // called by the model during simulation fmiBoolean toleranceControlled = fmiFalse; nSteps_ = 0; fmiReal timeout = 100.0; fmiBoolean visible = false; fmiBoolean interactive = true; // Set the start time and initialize time_ = getStartTime(); GetCurrentDirectory(MAX_PATH, currentDirectory); Logger::getInstance()->printDebug2(_T("currentDirectory: %s\n"), currentDirectory); this->getModuleFolderPath(exeDirectory); callbackFunctions.logger = FMUlogger::log; callbackFunctions.allocateMemory = calloc; callbackFunctions.freeMemory = free; guid = getString(fmu_->modelDescription, att_guid); modelIdentifier = getModelIdentifier(fmu_->modelDescription); Logger::getInstance()->printDebug2(_T("exeDirectory: %s\n"), exeDirectory); Logger::getInstance()->printDebug2(_T("unzipFolderPath_%s\n"), unzipFolderPath_); Logger::getInstance()->printDebugDouble(_T("stepDelta: %s\n"), getStepDelta()); Logger::getInstance()->printDebugDouble(_T("time_: %s\n"), time_); Logger::getInstance()->printDebugDouble(_T("stopTime: %s\n"), getStopTime()); Logger::getInstance()->printDebug2(_T("instanceName is %s\n"), modelIdentifier); Logger::getInstance()->printDebug2(_T("GUID = %s!\n"), guid); BOOL isSet = SetCurrentDirectory(unzipFolderPath_); int bufferLength = GetCurrentDirectory(MAX_PATH, currentDirectory2); Logger::getInstance()->printDebug2(_T("currentDirectory2: %s\n"), currentDirectory2); fmiComponent_ = fmu_->instantiateSlave ( modelIdentifier, //fmiString instanceName guid, //fmiString fmuGUID "Model1", //fmuLocation "", //fmiString mimeType timeout, //fmiReal timeout visible, //fmiBoolean visible interactive, //fmiBoolean interactive callbackFunctions, isLoggingEnabled_ // ); if (!fmiComponent_) { setStateError_(_T("Could not instantiate slaves\n")); return 1; } else { Logger::getInstance()->printDebug(_T("Successfully instantiated one slave\n")); mainDataModel_->setFmiComponent(fmiComponent_); setState_( simStateNative_3_init_instantiatedSlaves ); return 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. int fmuSimulate(FMU* fmu, double tEnd, double h, fmiBoolean loggingOn, char separator, const char* resultFileName) { int i; double dt, tPre; fmiBoolean timeEvent, stateEvent, stepEvent; double simtime; 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 = 0; clock_t timing; // 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 fmuError("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 fmuError("out of memory"); // open result file if(resultFileName != 0) { if((strlen(resultFileName)==1) && (resultFileName[0]=='-') ) file = stdout; else { if (!(file=fopen(resultFileName, "w"))) { fprintf(stderr,"could not write %s\n", resultFileName); return 0; // failure } } } timing = clock(); fprintf(stderr,"timing start %ld\n", timing); // set the start time and initialize simtime = t0; fmiFlag = fmu->setTime(c, t0); if (fmiFlag > fmiWarning) return fmuError("could not set time"); fmiFlag = fmu->initialize(c, toleranceControlled, t0, &eventInfo); if (fmiFlag > fmiWarning) fmuError("could not initialize model"); if (eventInfo.terminateSimulation) { fprintf(stderr,"model requested termination at init"); tEnd = simtime; } // output solution for simtime t0 if(file) { outputRow(fmu, c, t0, file, separator, TRUE); // output column names outputRow(fmu, c, t0, file, separator, FALSE); // output values } // enter the simulation loop while (simtime < tEnd) { // get current state and derivatives fmiFlag = fmu->getContinuousStates(c, x, nx); if (fmiFlag > fmiWarning) return fmuError("could not retrieve states"); fmiFlag = fmu->getDerivatives(c, xdot, nx); if (fmiFlag > fmiWarning) return fmuError("could not retrieve derivatives"); // advance simtime tPre = simtime; simtime = min(simtime+h, tEnd); timeEvent = eventInfo.upcomingTimeEvent && eventInfo.nextEventTime < simtime; if (timeEvent) simtime = eventInfo.nextEventTime; dt = simtime - tPre; fmiFlag = fmu->setTime(c, simtime); if (fmiFlag > fmiWarning) fmuError("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 fmuError("could not set states"); if (loggingOn) fprintf(stderr,"Step %d to t=%.16g\n", nSteps, simtime); // Check for step event, e.g. dynamic state selection fmiFlag = fmu->completedIntegratorStep(c, &stepEvent); if (fmiFlag > fmiWarning) return fmuError("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 fmuError("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) fprintf(stderr,"time event at t=%.16g\n", simtime); } if (stateEvent) { nStateEvents++; if (loggingOn) for (i=0; i<nz; i++) fprintf(stderr,"state event %s z[%d] at t=%.16g\n", (prez[i]>0 && z[i]<0) ? "-\\-" : "-/-", i, simtime); } if (stepEvent) { nStepEvents++; if (loggingOn) fprintf(stderr,"step event at t=%.16g\n", simtime); } // event iteration in one step, ignoring intermediate results fmiFlag = fmu->eventUpdate(c, fmiFalse, &eventInfo); if (fmiFlag > fmiWarning) return fmuError("could not perform event update"); // terminate simulation, if requested by the model if (eventInfo.terminateSimulation) { fprintf(stderr,"model requested termination at t=%.16g\n", simtime); break; // success } // check for change of value of states if (eventInfo.stateValuesChanged && loggingOn) { fprintf(stderr,"state values changed at t=%.16g\n", simtime); } // check for selection of new state variables if (eventInfo.stateValueReferencesChanged && loggingOn) { fprintf(stderr,"new state variables selected at t=%.16g\n", simtime); } } // if event if(file) outputRow(fmu, c, simtime, file, separator, FALSE); // output values for this step nSteps++; } // while timing = clock() - timing; // cleanup fmu->freeModelInstance(c); if(file) 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 fprintf(stderr,"Simulation from %g to %g terminated successful\n", t0, tEnd); fprintf(stderr," steps ............ %d\n", nSteps); fprintf(stderr," fixed step size .. %g\n", h); fprintf(stderr," time events ...... %d\n", nTimeEvents); fprintf(stderr," state events ..... %d\n", nStateEvents); fprintf(stderr," step events ...... %d\n", nStepEvents); if(resultFileName && ((strlen(resultFileName)!=1) || (resultFileName[0] != '-'))) fprintf(stderr,"CSV file '%s' written.\n", resultFileName); fprintf(stderr," simultation time.. %g seconds (resolution %g sec) \n", ((double)timing * 1.0) / CLOCKS_PER_SEC, 1.0/CLOCKS_PER_SEC); return 1; // success }
/////////////////////////////////////////////////////////////////////////////// /// main routine of the demo code /// ///\param argc Number of arguments ///\param argv Arguments ///\return 0 if no error occurred /////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { const char* fmuFilNam; char* fmuPat; char* tmpPat; char* xmlPat; char* dllPat; // define default argument values double tEnd = 1.0; double h=0.1; int loggingOn = 0; char csv_separator = ','; // parse command line arguments if (argc>1) { fmuFilNam = argv[1]; if(!strcmp(fmuFilNam, "-h") | !strcmp(fmuFilNam, "--help")) { printHelp(argv[0]); return 0; } /*if(!strstr(fmuFilNam,"DoubleInputDoubleOutput.fmu")) { printf("Sorry, this demo only works with the FMU file DoubleInputDoubleOutput.fmu"); return 0; }*/ } else { printError("No fmu file.\n"); printHelp(argv[0]); exit(EXIT_FAILURE); } if (argc>2) { if (sscanf(argv[2],"%lf", &tEnd) != 1) { printfError("The given end time (%s) is not a number.\n", argv[2]); exit(EXIT_FAILURE); } } if (argc>3) { if (sscanf(argv[3],"%lf", &h) != 1) { printfError("The given stepsize (%s) is not a number.\n", argv[3]); exit(EXIT_FAILURE); } } if (argc>4) { if (sscanf(argv[4],"%d", &loggingOn) != 1 || loggingOn<0 || loggingOn>1) { printfError("The given logging flag (%s) is not boolean.\n", argv[4]); exit(EXIT_FAILURE); } if(loggingOn) setDebug(); } if (argc>5) { if (strlen(argv[5]) != 1) { printfError("The given CSV separator char (%s) is not valid.\n", argv[5]); exit(EXIT_FAILURE); } csv_separator = argv[5][0]; } if (argc>6) { printf("warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]); printHelp(argv[0]); } // Get absolute path to FMU, NULL if not found tmpPat = getTmpPath(fmuFilNam, strlen(fmuFilNam)-4); if(tmpPat==NULL){ printError("Cannot allocate temporary path.\n"); exit(EXIT_FAILURE); } // Unzip the FMU to the tmpPat directory if (unpack(fmuFilNam, tmpPat)) { printfError("Fail to unpack fmu \"%s\".\n", fmuFilNam); exit(EXIT_FAILURE); } printDebug("parse tmpPat\\modelDescription.xml.\n"); xmlPat = calloc(sizeof(char), strlen(tmpPat) + strlen(XML_FILE) + 1); sprintf(xmlPat, "%s%s", tmpPat, XML_FILE); // Parse only parses the model description and store in structure fmu.modelDescription fmu.modelDescription = parse(xmlPat); free(xmlPat); if (!fmu.modelDescription) exit(EXIT_FAILURE); // Allocate the memory for dllPat dllPat = calloc(sizeof(char), strlen(tmpPat) + strlen(DLL_DIR) + strlen( getModelIdentifier(fmu.modelDescription)) + strlen(".dll") + 1); sprintf(dllPat,"%s%s%s.dll", tmpPat, DLL_DIR, getModelIdentifier(fmu.modelDescription)); // Load the FMU dll if (loadDll(dllPat, &fmu)) exit(EXIT_FAILURE); printfDebug("Loaded \"%s\"\n", dllPat); free(dllPat); free(tmpPat); // Run the simulation printf("FMU Simulator: run '%s' from t=0..%g with step size h=%g, loggingOn=%d, csv separator='%c'\n", fmuFilNam, tEnd, h, loggingOn, csv_separator); if (simulate(&fmu, tEnd, h, loggingOn, csv_separator)){ printError("Simulation failed.\n"); exit(EXIT_FAILURE); } printf("CSV file '%s' written", RESULT_FILE); // Release FMU FreeLibrary(fmu.dllHandle); freeElement(fmu.modelDescription); return EXIT_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. /// ///\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 }
int main(int argc, char *argv[]) { const char* fmuFileName = 0; char* fmuPath = 0; char* tmpPath = 0; char* xmlPath = 0; char* dllPath = 0; char* cmd = 0; // define default argument values double tEnd = 1.0; double h=0.1; int loggingOn = 0; char csv_separator = ';'; const char* resultFileName = "-"; // parse command line arguments if (argc>1) { fmuFileName = argv[1]; } else { fprintf(stderr,"error: no fmu file\n"); printHelp(argv[0]); exit(EXIT_FAILURE); } if (argc>2) { if (sscanf(argv[2],"%lf", &tEnd) != 1) { fprintf(stderr,"error: The given end time (%s) is not a number\n", argv[2]); exit(EXIT_FAILURE); } } if (argc>3) { if (sscanf(argv[3],"%lf", &h) != 1) { fprintf(stderr,"error: The given stepsize (%s) is not a number\n", argv[3]); exit(EXIT_FAILURE); } } if (argc>4) { if (sscanf(argv[4],"%d", &loggingOn) != 1 || loggingOn<0 || loggingOn>1) { fprintf(stderr,"error: The given logging option (%s) must be 0 or 1\n", argv[4]); exit(EXIT_FAILURE); } } if (argc>5) { if (strlen(argv[5]) != 1) { fprintf(stderr,"error: The given CSV separator char (%s) is not valid\n", argv[5]); exit(EXIT_FAILURE); } csv_separator = argv[5][0]; } if (argc>6) { resultFileName = argv[6]; if(strlen(resultFileName)==0) resultFileName = 0; // no output } if (argc>7) { fprintf(stderr,"warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]); printHelp(argv[0]); } // get absolute path to FMU, NULL if not found fmuPath = getFmuPath(fmuFileName); if (!fmuPath) exit(EXIT_FAILURE); // unzip the FMU to the tmpPath directory tmpPath = getTmpPath(); if (!fmuUnzip(fmuPath, tmpPath)) exit(EXIT_FAILURE); // parse tmpPath\modelDescription.xml xmlPath = calloc(sizeof(char), strlen(tmpPath) + strlen(XML_FILE) + 1); sprintf(xmlPath, "%s%s", tmpPath, XML_FILE); fmu.modelDescription = parse(xmlPath); free(xmlPath); if (!fmu.modelDescription) exit(EXIT_FAILURE); // load the FMU dll dllPath = calloc(sizeof(char), strlen(tmpPath) + strlen(DLL_DIR) + strlen( getModelIdentifier(fmu.modelDescription)) + strlen(DLL_SUFFIX) + 1); sprintf(dllPath,"%s%s%s%s", tmpPath, DLL_DIR, getModelIdentifier(fmu.modelDescription), DLL_SUFFIX); if (!fmuLoadDll(dllPath, &fmu)) exit(EXIT_FAILURE); free(dllPath); free(fmuPath); // run the simulation fprintf(stderr,"FMU Simulator: run '%s' from t=0..%g with step size h=%g, loggingOn=%d, csv separator='%c'\n", fmuFileName, tEnd, h, loggingOn, csv_separator); if(resultFileName) if(strlen(resultFileName)==1 && resultFileName[0]=='-') fprintf(stderr, "Output will be written to standard output\n"); else fprintf(stderr, "Output will be written to file %s\n", resultFileName); else fprintf(stderr, "No output file will be produced\n"); fmuSimulate(&fmu, tEnd, h, loggingOn, csv_separator, resultFileName); #if WINDOWS /* Remove temp file directory? Not tested*/ cmd = calloc(sizeof(char), strlen(tmpPath)+20); sprintf(cmd, "rmdir %s /s /q", tmpPath); fprintf(stderr,"Removing %s\n", tmpPath); system(cmd); free(cmd); #else cmd = calloc(sizeof(char), strlen(tmpPath)+8); sprintf(cmd, "rm -rf %s", tmpPath); fprintf(stderr,"Removing %s\n", tmpPath); system(cmd); free(cmd); #endif free(tmpPath); // release FMU fmuFree(&fmu); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { const char* fmuFileName; char* fmuPath; char* tmpPath; char* xmlPath; char* dllPath; // define default argument values double tEnd = 1.0; double h=0.1; int loggingOn = 0; char csv_separator = ';'; // parse command line arguments if (argc>1) { fmuFileName = argv[1]; } else { printf("error: no fmu file\n"); printHelp(argv[0]); exit(EXIT_FAILURE); } if (argc>2) { if (sscanf(argv[2],"%lf", &tEnd) != 1) { printf("error: The given end time (%s) is not a number\n", argv[2]); exit(EXIT_FAILURE); } } if (argc>3) { if (sscanf(argv[3],"%lf", &h) != 1) { printf("error: The given stepsize (%s) is not a number\n", argv[3]); exit(EXIT_FAILURE); } } if (argc>4) { if (sscanf(argv[4],"%d", &loggingOn) != 1 || loggingOn<0 || loggingOn>1) { printf("error: The given logging flag (%s) is not boolean\n", argv[4]); exit(EXIT_FAILURE); } } if (argc>5) { if (strlen(argv[5]) != 1) { printf("error: The given CSV separator char (%s) is not valid\n", argv[5]); exit(EXIT_FAILURE); } csv_separator = argv[5][0]; } if (argc>6) { printf("warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]); printHelp(argv[0]); } // get absolute path to FMU, NULL if not found fmuPath = getFmuPath(fmuFileName); if (!fmuPath) exit(EXIT_FAILURE); // unzip the FMU to the tmpPath directory tmpPath = getTmpPath(); if (!unzip(fmuPath, tmpPath)) exit(EXIT_FAILURE); // parse tmpPath\modelDescription.xml xmlPath = calloc(sizeof(char), strlen(tmpPath) + strlen(XML_FILE) + 1); sprintf(xmlPath, "%s%s", tmpPath, XML_FILE); fmu.modelDescription = parse(xmlPath); free(xmlPath); if (!fmu.modelDescription) exit(EXIT_FAILURE); // load the FMU dll dllPath = calloc(sizeof(char), strlen(tmpPath) + strlen(DLL_DIR) + strlen( getModelIdentifier(fmu.modelDescription)) + strlen(".dll") + 1); sprintf(dllPath,"%s%s%s.dll", tmpPath, DLL_DIR, getModelIdentifier(fmu.modelDescription)); if (!loadDll(dllPath, &fmu)) exit(EXIT_FAILURE); free(dllPath); free(fmuPath); free(tmpPath); // run the simulation printf("FMU Simulator: run '%s' from t=0..%g with step size h=%g, loggingOn=%d, csv separator='%c'\n", fmuFileName, tEnd, h, loggingOn, csv_separator); simulate(&fmu, tEnd, h, loggingOn, csv_separator); printf("CSV file '%s' written", RESULT_FILE); // release FMU FreeLibrary(fmu.dllHandle); freeElement(fmu.modelDescription); return EXIT_SUCCESS; }