/* ---------------------------------------------------------------------------* * Implementation of the FMI interface based on functions and macros to * be defined by the includer of this file. * If FMI_COSIMULATION is defined, this implements "FMI for Co-Simulation 1.0", * otherwise "FMI for Model Exchange 1.0". * The "FMI for Co-Simulation 1.0", implementation assumes that exactly the * following capability flags are set to fmiTrue: * canHandleVariableCommunicationStepSize, i.e. fmiDoStep step size can vary * canHandleEvents, i.e. fmiDoStep step size can be zero * and all other capability flags are set to default, i.e. to fmiFalse or 0. * * Revision history * 07.02.2010 initial version for "Model Exchange 1.0" released in FMU SDK 1.0 * 05.03.2010 bug fix: fmiSetString now copies the passed string argument * and fmiFreeModelInstance frees all string copies * 11.12.2010 replaced calloc by functions.allocateMemory in fmiInstantiateModel * 04.08.2011 added support for "FMI for Co-Simulation 1.0" * * (c) 2011 QTronic GmbH * ---------------------------------------------------------------------------*/ // array of value references of states #if NUMBER_OF_REALS>0 // Linux: declare vrStates to be static so that we get the local definition. static fmiValueReference vrStates[NUMBER_OF_STATES] = STATES; #endif #ifndef max #define max(a,b) ((a)>(b) ? (a) : (b)) #endif static fmiBoolean invalidState(ModelInstance* comp, const char* f, int statesExpected){ if (!comp) return fmiTrue; if (!(comp->state & statesExpected)) { comp->state = modelError; comp->functions.logger(comp, comp->instanceName, fmiError, "error", "%s: Illegal call sequence.", f); return fmiTrue; } return fmiFalse; } static fmiBoolean nullPointer(ModelInstance* comp, const char* f, const char* arg, const void* p){ if (!p) { comp->state = modelError; comp->functions.logger(comp, comp->instanceName, fmiError, "error", "%s: Invalid argument %s = NULL.", f, arg); return fmiTrue; } return fmiFalse; } static fmiBoolean vrOutOfRange(ModelInstance* comp, const char* f, fmiValueReference vr, int end) { if (vr >= end) { comp->functions.logger(comp, comp->instanceName, fmiError, "error", "%s: Illegal value reference %u.", f, vr); comp->state = modelError; return fmiTrue; } return fmiFalse; } // --------------------------------------------------------------------------- // Private helpers used below to implement functions // --------------------------------------------------------------------------- static fmiStatus setString(fmiComponent comp, fmiValueReference vr, fmiString value){ return fmiSetString(comp, &vr, 1, &value); } // fname is fmiInstantiateModel or fmiInstantiateSlave static fmiComponent instantiateModel(char* fname, fmiString instanceName, fmiString GUID, fmiCallbackFunctions functions, fmiBoolean loggingOn) { ModelInstance* comp; if (!functions.logger) return NULL; if (!functions.allocateMemory || !functions.freeMemory){ functions.logger(NULL, instanceName, fmiError, "error", "%s: Missing callback function.", fname); return NULL; } if (!instanceName || strlen(instanceName)==0) { functions.logger(NULL, instanceName, fmiError, "error", "%s: Missing instance name.", fname); return NULL; } if (strcmp(GUID, MODEL_GUID)) { functions.logger(NULL, instanceName, fmiError, "error", "%s: Wrong GUID %s. Expected %s.", fname, GUID, MODEL_GUID); return NULL; } comp = (ModelInstance *)functions.allocateMemory(1, sizeof(ModelInstance)); if (comp) { comp->r = functions.allocateMemory(NUMBER_OF_REALS, sizeof(fmiReal)); comp->i = functions.allocateMemory(NUMBER_OF_INTEGERS, sizeof(fmiInteger)); comp->b = functions.allocateMemory(NUMBER_OF_BOOLEANS, sizeof(fmiBoolean)); comp->s = functions.allocateMemory(NUMBER_OF_STRINGS, sizeof(fmiString)); comp->isPositive = functions.allocateMemory(NUMBER_OF_EVENT_INDICATORS, sizeof(fmiBoolean)); } if (!comp || !comp->r || !comp->i || !comp->b || !comp->s || !comp->isPositive) { functions.logger(NULL, instanceName, fmiError, "error", "%s: Out of memory.", fname); return NULL; } if (comp->loggingOn) comp->functions.logger(NULL, instanceName, fmiOK, "log", "%s: GUID=%s", fname, GUID); // fmiStrings must be duplicated. comp->instanceName = functions.allocateMemory(strlen(instanceName) + 1, sizeof(fmiString)); strcpy((char *)comp->instanceName, instanceName); comp->GUID = GUID; comp->functions = functions; comp->loggingOn = loggingOn; comp->state = modelInstantiated; setStartValues(comp); // to be implemented by the includer of this file return comp; } // fname is fmiInitialize or fmiInitializeSlave static fmiStatus init(char* fname, fmiComponent c, fmiBoolean toleranceControlled, fmiReal relativeTolerance, fmiEventInfo* eventInfo) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, fname, modelInstantiated)) return fmiError; if (nullPointer(comp, fname, "eventInfo", eventInfo)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "%s: toleranceControlled=%d relativeTolerance=%g", fname, toleranceControlled, relativeTolerance); eventInfo->iterationConverged = fmiTrue; eventInfo->stateValueReferencesChanged = fmiFalse; eventInfo->stateValuesChanged = fmiFalse; eventInfo->terminateSimulation = fmiFalse; eventInfo->upcomingTimeEvent = fmiFalse; initialize(comp, eventInfo); // to be implemented by the includer of this file comp->state = modelInitialized; return fmiOK; } // fname is fmiTerminate or fmiTerminateSlave static fmiStatus terminate(char* fname, fmiComponent c){ ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, fname, modelInitialized)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", fname); comp->state = modelTerminated; return fmiOK; } // fname is freeModelInstance of freeSlaveInstance void freeInstance(char* fname, fmiComponent c) { ModelInstance* comp = (ModelInstance *)c; if (!comp) return; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", fname); if (comp->r) comp->functions.freeMemory(comp->r); if (comp->i) comp->functions.freeMemory(comp->i); if (comp->b) comp->functions.freeMemory(comp->b); if (comp->s) { int i; for (i=0; is[i]) comp->functions.freeMemory((void*)comp->s[i]); } comp->functions.freeMemory(comp->s); } if (comp->isPositive) { comp->functions.freeMemory((void *)comp->isPositive); } if (comp->instanceName) { comp->functions.freeMemory((void *)comp->instanceName); } comp->functions.freeMemory(comp); } // --------------------------------------------------------------------------- // FMI functions: class methods not depending of a specific model instance // --------------------------------------------------------------------------- const char* fmiGetVersion() { return fmiVersion; } // --------------------------------------------------------------------------- // FMI functions: for FMI Model Exchange 1.0 and for FMI Co-Simulation 1.0 // logging control, setters and getters for Real, Integer, Boolean, String // --------------------------------------------------------------------------- fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetDebugLogging", not_modelError)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetDebugLogging: loggingOn=%d", loggingOn); comp->loggingOn = loggingOn; return fmiOK; } fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]){ int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetReal", modelInstantiated|modelInitialized)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetReal", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetReal", "value[]", value)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetReal: nvr = %d", nvr); // no check wether setting the value is allowed in the current state for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetReal: #r%d# = %.16g", vr[i], value[i]); comp->r[vr[i]] = value[i]; } return fmiOK; } fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]){ int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetInteger", modelInstantiated|modelInitialized)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetInteger", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetInteger", "value[]", value)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetInteger: nvr = %d", nvr); for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetInteger: #i%d# = %d", vr[i], value[i]); comp->i[vr[i]] = value[i]; } return fmiOK; } fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]){ int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetBoolean", modelInstantiated|modelInitialized)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetBoolean", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetBoolean", "value[]", value)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetBoolean: nvr = %d", nvr); for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetBoolean: #b%d# = %s", vr[i], value[i] ? "true" : "false"); comp->b[vr[i]] = value[i]; } return fmiOK; } fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]){ int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetString", modelInstantiated|modelInitialized)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetString", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiSetString", "value[]", value)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetString: nvr = %d", nvr); for (i=0; is[vr[i]]; if (vrOutOfRange(comp, "fmiSetString", vr[i], NUMBER_OF_STRINGS)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetString: #s%d# = '%s'", vr[i], value[i]); if (nullPointer(comp, "fmiSetString", "value[i]", value[i])) return fmiError; if (string==NULL || strlen(string) < strlen(value[i])) { if (string) comp->functions.freeMemory((void*)string); comp->s[vr[i]] = comp->functions.allocateMemory(1+strlen(value[i]), sizeof(char)); if (!comp->s[vr[i]]) { comp->state = modelError; comp->functions.logger(NULL, comp->instanceName, fmiError, "error", "fmiSetString: Out of memory."); return fmiError; } } strcpy((char*) comp->s[vr[i]], value[i]); } return fmiOK; } fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]) { #if NUMBER_OF_REALS>0 int i; #endif ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetReal", not_modelError)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetReal", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetReal", "value[]", value)) return fmiError; #if NUMBER_OF_REALS>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetReal: #r%u# = %.16g", vr[i], value[i]); } #endif return fmiOK; } fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]) { int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetInteger", not_modelError)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetInteger", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetInteger", "value[]", value)) return fmiError; for (i=0; ii[vr[i]]; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetInteger: #i%u# = %d", vr[i], value[i]); } return fmiOK; } fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]) { int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetBoolean", not_modelError)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetBoolean", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetBoolean", "value[]", value)) return fmiError; for (i=0; ib[vr[i]]; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetBoolean: #b%u# = %s", vr[i], value[i]? "true" : "false"); } return fmiOK; } fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]) { int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetString", not_modelError)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetString", "vr[]", vr)) return fmiError; if (nvr>0 && nullPointer(comp, "fmiGetString", "value[]", value)) return fmiError; for (i=0; is[vr[i]]; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetString: #s%u# = '%s'", vr[i], value[i]); } return fmiOK; } #ifdef FMI_COSIMULATION // --------------------------------------------------------------------------- // FMI functions: only for FMI Co-Simulation 1.0 // --------------------------------------------------------------------------- const char* fmiGetTypesPlatform() { return fmiPlatform; } fmiComponent fmiInstantiateSlave(fmiString instanceName, fmiString GUID, fmiString fmuLocation, fmiString mimeType, fmiReal timeout, fmiBoolean visible, fmiBoolean interactive, fmiCallbackFunctions functions, fmiBoolean loggingOn) { // ignoring arguments: fmuLocation, mimeType, timeout, visible, interactive return instantiateModel("fmiInstantiateSlave", instanceName, GUID, functions, loggingOn); } fmiStatus fmiInitializeSlave(fmiComponent c, fmiReal tStart, fmiBoolean StopTimeDefined, fmiReal tStop) { ModelInstance* comp = (ModelInstance *)c; fmiBoolean toleranceControlled = fmiFalse; fmiReal relativeTolerance = 0; fmiStatus flag = fmiOK; comp->eventInfo.iterationConverged = 0; while (flag==fmiOK && !comp->eventInfo.iterationConverged) { // ignoring arguments: tStart, StopTimeDefined, tStop flag = init("fmiInitializeSlave", c, toleranceControlled, relativeTolerance, &comp->eventInfo); } return flag; } fmiStatus fmiTerminateSlave(fmiComponent c) { return terminate("fmiTerminateSlave", c); } fmiStatus fmiResetSlave(fmiComponent c) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiResetSlave", modelInitialized)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiResetSlave"); comp->state = modelInstantiated; setStartValues(comp); // to be implemented by the includer of this file return fmiOK; } void fmiFreeSlaveInstance(fmiComponent c) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiFreeSlaveInstance", modelTerminated)) return; freeInstance("fmiFreeSlaveInstance", c); } fmiStatus fmiSetRealInputDerivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], const fmiReal value[]) { ModelInstance* comp = (ModelInstance *)c; fmiCallbackLogger log = comp->functions.logger; if (invalidState(comp, "fmiSetRealInputDerivatives", modelInitialized)) return fmiError; if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", "fmiSetRealInputDerivatives: nvr= %d", nvr); log(NULL, comp->instanceName, fmiError, "warning", "fmiSetRealInputDerivatives: ignoring function call." " This model cannot interpolate inputs: canInterpolateInputs=\"fmiFalse\""); return fmiWarning; } fmiStatus fmiGetRealOutputDerivatives(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger order[], fmiReal value[]) { int i; ModelInstance* comp = (ModelInstance *)c; fmiCallbackLogger log = comp->functions.logger; if (invalidState(comp, "fmiGetRealOutputDerivatives", modelInitialized)) return fmiError; if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", "fmiGetRealOutputDerivatives: nvr= %d", nvr); log(NULL, comp->instanceName, fmiError, "warning", "fmiGetRealOutputDerivatives: ignoring function call." " This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\""); for (i=0; ifunctions.logger; if (invalidState(comp, "fmiCancelStep", modelInitialized)) return fmiError; if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", "fmiCancelStep"); log(NULL, comp->instanceName, fmiError, "error", "fmiCancelStep: Can be called when fmiDoStep returned fmiPending." " This is not the case."); return fmiError; } fmiStatus fmiDoStep(fmiComponent c, fmiReal currentCommunicationPoint, fmiReal communicationStepSize, fmiBoolean newStep) { ModelInstance* comp = (ModelInstance *)c; fmiCallbackLogger log = comp->functions.logger; double h = communicationStepSize / 10; #if NUMBER_OF_EVENT_INDICATORS>0 || NUMBER_OF_REALS>0 int i; #endif int k; const int n = 10; // how many Euler steps to perform for one do step #if NUMBER_OF_REALS>0 double prevState[max(NUMBER_OF_STATES, 1)]; #endif #if NUMBER_OF_EVENT_INDICATORS>0 double prevEventIndicators[max(NUMBER_OF_EVENT_INDICATORS, 1)]; int stateEvent = 0; #endif if (invalidState(comp, "fmiDoStep", modelInitialized)) return fmiError; // FMUSDK 1.0.2 had a bug where there were commas after each // of the strings below. Under win32 with MSVC, this caused bad // values to be printed for currentCommunicationPoint and the // remaining strings not to be printed. if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", "fmiDoStep: " "currentCommunicationPoint = %g, " "communicationStepSize = %g, " "newStep = fmi%s" currentCommunicationPoint, communicationStepSize, newStep ? "True" : "False"); // Treat also case of zero step, i.e. during an event iteration if (communicationStepSize == 0) { return fmiOK; } #if NUMBER_OF_EVENT_INDICATORS>0 // initialize previous event indcators with current values for (i=0; itime = currentCommunicationPoint; for (k=0; ktime += h; #if NUMBER_OF_REALS>0 for (i=0; i0 // check for state event for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiDoStep: state event at %g, z%d crosses zero -%c-", comp->time, i, ei<0 ? '\\' : '/'); stateEvent++; } prevEventIndicators[i] = ei; } if (stateEvent) { eventUpdate(comp, &comp->eventInfo); stateEvent = 0; } #endif // check for time event if (comp->eventInfo.upcomingTimeEvent && comp->time > comp->eventInfo.nextEventTime) { if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiDoStep: time event detected at %g", comp->time); eventUpdate(comp, &comp->eventInfo); } // terminate simulation, if requested by the model if (comp->eventInfo.terminateSimulation) { comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiDoStep: model requested termination at t=%g", comp->time); return fmiError; // enforce termination of the simulation loop } } return fmiOK; } static fmiStatus getStatus(char* fname, fmiComponent c, const fmiStatusKind s) { const char* statusKind[3] = {"fmiDoStepStatus","fmiPendingStatus","fmiLastSuccessfulTime"}; ModelInstance* comp = (ModelInstance *)c; fmiCallbackLogger log = comp->functions.logger; if (invalidState(comp, fname, modelInstantiated|modelInitialized)) return fmiError; if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", "$s: fmiStatusKind = %s", fname, statusKind[s]); switch(s) { case fmiDoStepStatus: log(NULL, comp->instanceName, fmiError, "error", "%s: Can be called with fmiDoStepStatus when fmiDoStep returned fmiPending." " This is not the case.", fname); break; case fmiPendingStatus: log(NULL, comp->instanceName, fmiError, "error", "%s: Can be called with fmiPendingStatus when fmiDoStep returned fmiPending." " This is not the case.", fname); break; case fmiLastSuccessfulTime: log(NULL, comp->instanceName, fmiError, "error", "%s: Can be called with fmiLastSuccessfulTime when fmiDoStep returned fmiDiscard." " This is not the case.", fname); break; } return fmiError; } fmiStatus fmiGetStatus(fmiComponent c, const fmiStatusKind s, fmiStatus* value) { return getStatus("fmiGetStatus", c, s); } fmiStatus fmiGetRealStatus(fmiComponent c, const fmiStatusKind s, fmiReal* value){ return getStatus("fmiGetRealStatus", c, s); } fmiStatus fmiGetIntegerStatus(fmiComponent c, const fmiStatusKind s, fmiInteger* value){ return getStatus("fmiGetIntegerStatus", c, s); } fmiStatus fmiGetBooleanStatus(fmiComponent c, const fmiStatusKind s, fmiBoolean* value){ return getStatus("fmiGetBooleanStatus", c, s); } fmiStatus fmiGetStringStatus(fmiComponent c, const fmiStatusKind s, fmiString* value){ return getStatus("fmiGetStringStatus", c, s); } #else // --------------------------------------------------------------------------- // FMI functions: only for Model Exchange 1.0 // --------------------------------------------------------------------------- static fmiBoolean invalidNumber(ModelInstance* comp, const char* f, const char* arg, int n, int nExpected){ if (n != nExpected) { comp->state = modelError; comp->functions.logger(comp, comp->instanceName, fmiError, "error", "%s: Invalid argument %s = %d. Expected %d.", f, arg, n, nExpected); return fmiTrue; } return fmiFalse; } const char* fmiGetModelTypesPlatform() { return fmiModelTypesPlatform; } fmiComponent fmiInstantiateModel(fmiString instanceName, fmiString GUID, fmiCallbackFunctions functions, fmiBoolean loggingOn) { return instantiateModel("fmiInstantiateModel", instanceName, GUID, functions, loggingOn); } fmiStatus fmiInitialize(fmiComponent c, fmiBoolean toleranceControlled, fmiReal relativeTolerance, fmiEventInfo* eventInfo) { return init("fmiInitialize", c, toleranceControlled, relativeTolerance, eventInfo); } fmiStatus fmiSetTime(fmiComponent c, fmiReal time) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiSetTime", modelInstantiated|modelInitialized)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetTime: time=%.16g", time); comp->time = time; return fmiOK; } fmiStatus fmiSetContinuousStates(fmiComponent c, const fmiReal x[], size_t nx){ ModelInstance* comp = (ModelInstance *)c; #if NUMBER_OF_REALS>0 int i; #endif if (invalidState(comp, "fmiSetContinuousStates", modelInitialized)) return fmiError; if (invalidNumber(comp, "fmiSetContinuousStates", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiSetContinuousStates", "x[]", x)) return fmiError; #if NUMBER_OF_REALS>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetContinuousStates: #r%d#=%.16g", vr, x[i]); assert(vr>=0 && vrr[vr] = x[i]; } #endif return fmiOK; } fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo* eventInfo) { ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiEventUpdate", modelInitialized)) return fmiError; if (nullPointer(comp, "fmiEventUpdate", "eventInfo", eventInfo)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiEventUpdate: intermediateResults = %d", intermediateResults); eventInfo->iterationConverged = fmiTrue; eventInfo->stateValueReferencesChanged = fmiFalse; eventInfo->stateValuesChanged = fmiFalse; eventInfo->terminateSimulation = fmiFalse; eventInfo->upcomingTimeEvent = fmiFalse; eventUpdate(comp, eventInfo); // to be implemented by the includer of this file return fmiOK; } fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean* callEventUpdate){ ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiCompletedIntegratorStep", modelInitialized)) return fmiError; if (nullPointer(comp, "fmiCompletedIntegratorStep", "callEventUpdate", callEventUpdate)) return fmiError; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiCompletedIntegratorStep"); *callEventUpdate = fmiFalse; return fmiOK; } fmiStatus fmiGetStateValueReferences(fmiComponent c, fmiValueReference vrx[], size_t nx){ #if NUMBER_OF_REALS>0 int i; #endif ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetStateValueReferences", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetStateValueReferences", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiGetStateValueReferences", "vrx[]", vrx)) return fmiError; #if NUMBER_OF_REALS>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetStateValueReferences: vrx[%d] = %d", i, vrx[i]); } #endif return fmiOK; } fmiStatus fmiGetContinuousStates(fmiComponent c, fmiReal states[], size_t nx){ #if NUMBER_OF_REALS>0 int i; #endif ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetContinuousStates", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetContinuousStates", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiGetContinuousStates", "states[]", states)) return fmiError; #if NUMBER_OF_REALS>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetContinuousStates: #r%u# = %.16g", vr, states[i]); } #endif return fmiOK; } fmiStatus fmiGetNominalContinuousStates(fmiComponent c, fmiReal x_nominal[], size_t nx){ int i; ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetNominalContinuousStates", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetNominalContinuousStates", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiGetNominalContinuousStates", "x_nominal[]", x_nominal)) return fmiError; x_nominal[0] = 1; if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetNominalContinuousStates: x_nominal[0..%d] = 1.0", nx-1); for (i=0; i0 int i; #endif ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetDerivatives", not_modelError)) return fmiError; if (invalidNumber(c, "fmiGetDerivatives", "nx", nx, NUMBER_OF_STATES)) return fmiError; if (nullPointer(comp, "fmiGetDerivatives", "derivatives[]", derivatives)) return fmiError; #if NUMBER_OF_STATES>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetDerivatives: #r%d# = %.16g", vr, derivatives[i]); } #endif return fmiOK; } fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_t ni) { #if NUMBER_OF_EVENT_INDICATORS>0 int i; #endif ModelInstance* comp = (ModelInstance *)c; if (invalidState(comp, "fmiGetEventIndicators", not_modelError)) return fmiError; if (invalidNumber(comp, "fmiGetEventIndicators", "ni", ni, NUMBER_OF_EVENT_INDICATORS)) return fmiError; #if NUMBER_OF_EVENT_INDICATORS>0 for (i=0; iloggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiGetEventIndicators: z%d = %.16g", i, eventIndicators[i]); } #endif return fmiOK; } fmiStatus fmiTerminate(fmiComponent c){ return terminate("fmiTerminate", c); } void fmiFreeModelInstance(fmiComponent c) { freeInstance("fmiFreeModelInstance", c); } #endif // Model Exchange 1.0