/////////////////////////////////////////////////////////////////////////////////////// /// Callback functions called by the XML parser. It creates and push a new element node. /// This is the start handler of Parser. XML_Parse() starts from here. /// ///\param context ///\param elm The element ///\param attr The attributes /////////////////////////////////////////////////////////////////////////////////////// static void XMLCALL startElement(void *context, const char *elm, const char **attr) { Elm el; void* e; int size; el = checkElement(elm); //Get the index of element printfDebug("startElement():%s\n", elm); printfDebug("*** starting element %s\n", elmNames[el]); if (el==-1) { printDebug("Error!"); return; // error } skipData = (el != elm_Name); // skip element content for all elements but Name switch(getAstNodeType(el)){ case astElement: size = sizeof(Element); break; case astListElement: size = sizeof(ListElement); break; case astType: size = sizeof(Type); break; case astScalarVariable: size = sizeof(ScalarVariable); break; case astModelDescription: size = sizeof(ModelDescription); break; default: assert(0); // Error message if there is no matching element, } printfIntDebug("Start to created a new element with size: %d\n", size); e = newElement(el, size, attr); // Create a new element printDebug("Created a new element"); if(checkPointer(e)) assert(0); // Check the validity of the new element printDebug("startElement(): Start to stack push."); stackPush(stack, e); // Add the element to stack and grow the stack if necessary }
/////////////////////////////////////////////////////////////////////////////// /// Add Attributes to an given element. /// It copies the \c attr array and all values, /// replaces all attribute names by constant literal strings, /// converts the null-terminated array into an array of known size n. /// ///\param el The element. ///\param attr Attributes. ///\returns 0 if there is no error occurred. Otherwise, return 1 to indicate an error. /////////////////////////////////////////////////////////////////////////////// int addAttributes(Element* el, const char** attr) { int n, a; const char** att = NULL; for (n=0; attr[n]; n+=2); printDebug("\n"); printfIntDebug("addAttributes(): n = %d\n", n); if (n>0) { att = calloc(n, sizeof(char*)); if (checkPointer(att)) return 1; } printDebug("addAttributes(): allocated att"); for (n=0; attr[n]; n+=2) { char* value = strdup(attr[n+1]); //duplicate string attr[n+1] printfDebug("addAttributes(): value = %s\n", value); if (checkPointer(value)) return 1; a = checkAttribute(attr[n]); printfIntDebug("addAttributes(): index a = %d\n", a); if (a == -1) { printf("Illegal attribute in"); return 1; // illegal attribute error } att[n ] = attNames[a]; // no heap memory printfDebug("addAttributes(): attNames = %s\n", attNames[a]); att[n+1] = value; // heap memory printfDebug("addAttributes(): att[n+1] = %s\n", att[n+1] ); } el->attributes = att; // NULL if n=0 el->n = n; return 0; // success }
bool extgl_QueryExtension(const GLubyte*extensions, const char *name) { const GLubyte *start; GLubyte *where, *terminator; if (extensions == NULL) { printfDebug("NULL extension string\n"); return false; } /* Extension names should not have spaces. */ where = (GLubyte *) strchr(name, ' '); if (where || *name == '\0') return false; /* It takes a bit of care to be fool-proof about parsing the OpenGL extensions string. Don't be fooled by sub-strings, etc. */ start = extensions; for (;;) { where = (GLubyte *) strstr((const char *) start, name); if (!where) break; terminator = where + strlen(name); if (where == start || *(where - 1) == ' ') if (*terminator == ' ' || *terminator == '\0') { return true; } start = terminator; } return false; }
void *extgl_GetProcAddress(const char *name) { void *t = (void*)lwjgl_glXGetProcAddressARB((const GLubyte*)name); if (t == NULL) { t = dlsym(lib_gl_handle, name); if (t == NULL) { printfDebug("Could not locate symbol %s\n", name); } } return t; }
void *extgl_GetProcAddress(const char *name) { void *t = wglGetProcAddress(name); if (t == NULL) { t = GetProcAddress(lib_gl_handle, name); if (t == NULL) { printfDebug("Could not locate symbol %s\n", name); } } return t; }
void *extgl_GetProcAddress(const char *name) { void *t = eglGetProcAddress(name); if ( t == NULL ) { t = dlsym(lib_gl_handle, name); if ( t == NULL ) printfDebug("Could not locate symbol %s\n", name); } //if ( t != NULL ) //printfDebug("Located symbol %s\n", name); return t; }
/* * Register the LWJGL window class. * Returns true for success, or false for failure */ bool registerWindow(WNDPROC win_proc, LPCTSTR class_name) { WNDCLASS windowClass; memset(&windowClass, 0, sizeof(windowClass)); windowClass.style = CS_OWNDC; windowClass.lpfnWndProc = win_proc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = dll_handle; windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = NULL; windowClass.lpszMenuName = NULL; windowClass.lpszClassName = class_name; if (RegisterClass(&windowClass) == 0) { printfDebug("Failed to register window class\n"); return false; } return true; }
/////////////////////////////////////////////////////////////////////////////// /// 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 }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Pop the children from the stack and check for correct type and sequence of children /// This is the end handler of parser. The parser ends here. /// ///\param context ///\param elm ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void XMLCALL endElement(void *context, const char *elm) { Elm el; el = checkElement(elm); printfDebug(" **** ending element %s.\n", elmNames[el]); switch(el) { case elm_fmiModelDescription: { ModelDescription* md; ListElement** im = NULL; // NULL or list of CoSimulation_StandAlone under Implementation ListElement** ud = NULL; // NULL or list of BaseUnits under UnitDefinitions Type** td = NULL; // NULL or list of Types under TypeDefinitions Element* de = NULL; // NULL or DefaultExperiment ListElement** va = NULL; // NULL or list of Tools ScalarVariable** mv = NULL; // NULL or list of ScalarVariables under ModelVariables ListElement* child; printDebug("$$$$$ entered endElement 'elm_fmiModelDescription'\n"); child = checkPop(ANY_TYPE); // get a child from stack while (child && child->type != elm_fmiModelDescription) // add while-loop in case the elements in the random order { if (child->type == elm_VendorAnnotations){ va = (ListElement**)child->list; // VendorAnnotations (ListElement) contains Tool (ListElement)) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_DefaultExperiment){ de = (Element*)child; // DefaultExperiment (Element) with only attributes child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_TypeDefinitions){ td = (Type**)child->list; // TypeDefinitions (ListElement) contains Type (Type) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_UnitDefinitions){ ud = (ListElement**)child->list; // UnitDefinitions (ListElement) contains BaseUnit (ListElement) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_Implementation){ // Implementation is listElement, it can be treated the same as UnitDefinitions im = (ListElement**)child->list; // Implementation (Implementation) contains CoSimulation_StandAlone (ListElement) free(child); // Zuo: child = checkPop(ANY_TYPE); // Zuo: if (!child) return; // Zuo: } // Zuo: if (child->type == elm_ModelVariables){ mv = (ScalarVariable**)child->list; // ModelVariables (ListElement) contains ScalarVariable (ScalarVariable) free(child); child = checkPop(ANY_TYPE); if (!child) return; } } printDebug("$$$$$ checking element type \n"); if (checkElementType(child, elm_fmiModelDescription)) return; printDebug("$$$$$ checked element type \n"); md = (ModelDescription*)child; // the following build the link of elements for ModelDescriptions md->modelVariables = mv; md->implementation = im; // added M. Wetter md->vendorAnnotations = va; md->defaultExperiment = de; md->typeDefinitions = td; md->unitDefinitions = ud; printDebug("$$$$$ calling stackPush \n"); stackPush(stack, md); printDebug("$$$$$ called stackPush \n"); break; } case elm_Type: { Type* tp; Element* ts = checkPop(ANY_TYPE); if (!ts) return; // If there is no sub-element, return if (checkPeek(elm_Type)) return; // If the sub-element is not Type, return tp = (Type*)stackPeek(stack); // Get the element switch (ts->type) { case elm_RealType: case elm_IntegerType: case elm_BooleanType: case elm_EnumerationType: case elm_StringType: break; default: // Element type does not match logFatalTypeError("RealType or similar", ts->type); return; } tp->typeSpec = ts; // parent (tp) links to sub-element (ts) break; } case elm_ScalarVariable: { ScalarVariable* sv; Element** list = NULL; Element* child = checkPop(ANY_TYPE); if (!child) return; if (child->type==elm_DirectDependency){ list = ((ListElement*)child)->list; // DirectDependency is ListElement free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (checkPeek(elm_ScalarVariable)) return; // If next element is not ScalarVariable, return sv = (ScalarVariable*)stackPeek(stack); switch (child->type) { case elm_Real: case elm_Integer: case elm_Boolean: case elm_Enumeration: case elm_String: break; default: logFatalTypeError("Real or similar", child->type); return; } sv->directDependencies = list; sv->typeSpec = child; break; } case elm_Implementation: popList(elm_CoSimulation_StandAlone); break; // Needs to be modified if CoSimulation_Tool is added case elm_CoSimulation_StandAlone: popList(elm_Capabilities); break; // CoSimulation_StandAlone only has Capabilities case elm_ModelVariables: popList(elm_ScalarVariable); break; case elm_VendorAnnotations: popList(elm_Tool);break; case elm_Tool: popList(elm_Annotation); break; case elm_TypeDefinitions: popList(elm_Type); break; case elm_EnumerationType: popList(elm_Item); break; case elm_UnitDefinitions: popList(elm_BaseUnit); break; case elm_BaseUnit: popList(elm_DisplayUnitDefinition); break; case elm_DirectDependency: popList(elm_Name); break; case elm_Name: { // Exception: the name value is represented as element content. // All other values of the XML file are represented using attributes. Element* name = checkPop(elm_Name); if (!name) return; name->n = 2; name->attributes = malloc(2*sizeof(char*)); name->attributes[0] = attNames[att_input]; name->attributes[1] = data; data = NULL; skipData = 1; // stop recording element content stackPush(stack, name); break; } case -1: return; // illegal element error default: // must be a leaf Element printDebug("+++++++ got a leaf element\n"); assert(getAstNodeType(el)==astElement); break; } // All children of el removed from the stack. // The top element must be of type el now. checkPeek(el); }