123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /* ---------------------------------------------------------------------------*
- * fmuTemplate.c
- * 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 2.0",
- * otherwise "FMI for Model Exchange 2.0".
- * The "FMI for Co-Simulation 2.0", implementation assumes that exactly the
- * following capability flags are set to fmi2True:
- * canHandleVariableCommunicationStepSize, i.e. fmi2DoStep step size can vary
- * and all other capability flags are set to default, i.e. to fmi2False or 0.
- *
- * Revision history
- * 07.03.2014 initial version released in FMU SDK 2.0.0
- * 02.04.2014 allow modules to request termination of simulation, better time
- * event handling, initialize() moved from fmi2EnterInitialization to
- * fmi2ExitInitialization, correct logging message format in fmi2DoStep.
- * 10.04.2014 use FMI 2.0 headers that prefix function and types names with 'fmi2'.
- * 13.06.2014 when fmi2setDebugLogging is called with 0 categories, set all
- * categories to loggingOn value.
- * 09.07.2014 track all states of Model-exchange and Co-simulation and check
- * the allowed calling sequences, explicit isTimeEvent parameter for
- * eventUpdate function of the model, lazy computation of computed values.
- *
- * Author: Adrian Tirea
- * Copyright QTronic GmbH. All rights reserved.
- * ---------------------------------------------------------------------------*/
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifndef max
- #define max(a,b) ((a)>(b) ? (a) : (b))
- #endif
- // ---------------------------------------------------------------------------
- // Private helpers used below to validate function arguments
- // ---------------------------------------------------------------------------
- static fmi2Boolean invalidNumber(ModelInstance *comp, const char *f, const char *arg, int n, int nExpected) {
- if (n != nExpected) {
- comp->state = modelError;
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "%s: Invalid argument %s = %d. Expected %d.", f, arg, n, nExpected)
- return fmi2True;
- }
- return fmi2False;
- }
- static fmi2Boolean invalidState(ModelInstance *comp, const char *f, int statesExpected) {
- if (!comp)
- return fmi2True;
- if (!(comp->state & statesExpected)) {
- comp->state = modelError;
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "%s: Illegal call sequence.", f)
- return fmi2True;
- }
- return fmi2False;
- }
- static fmi2Boolean nullPointer(ModelInstance* comp, const char *f, const char *arg, const void *p) {
- if (!p) {
- comp->state = modelError;
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "%s: Invalid argument %s = NULL.", f, arg)
- return fmi2True;
- }
- return fmi2False;
- }
- static fmi2Boolean vrOutOfRange(ModelInstance *comp, const char *f, fmi2ValueReference vr, int end) {
- if (vr >= end) {
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "%s: Illegal value reference %u.", f, vr)
- comp->state = modelError;
- return fmi2True;
- }
- return fmi2False;
- }
- static fmi2Status unsupportedFunction(fmi2Component c, const char *fName, int statesExpected) {
- ModelInstance *comp = (ModelInstance *)c;
- fmi2CallbackLogger log = comp->functions->logger;
- if (invalidState(comp, fName, statesExpected))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, fName);
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "%s: Function not implemented.", fName)
- return fmi2Error;
- }
- fmi2Status setString(fmi2Component comp, fmi2ValueReference vr, fmi2String value) {
- return fmi2SetString(comp, &vr, 1, &value);
- }
- // ---------------------------------------------------------------------------
- // Private helpers logger
- // ---------------------------------------------------------------------------
- // return fmi2True if logging category is on. Else return fmi2False.
- fmi2Boolean isCategoryLogged(ModelInstance *comp, int categoryIndex) {
- if (categoryIndex < NUMBER_OF_CATEGORIES
- && (comp->logCategories[categoryIndex] || comp->logCategories[LOG_ALL])) {
- return fmi2True;
- }
- return fmi2False;
- }
- // ---------------------------------------------------------------------------
- // FMI functions
- // ---------------------------------------------------------------------------
- fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
- fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
- fmi2Boolean visible, fmi2Boolean loggingOn) {
- // ignoring arguments: fmuResourceLocation, visible
- ModelInstance *comp;
- if (!functions->logger) {
- return NULL;
- }
- if (!functions->allocateMemory || !functions->freeMemory) {
- functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error",
- "fmi2Instantiate: Missing callback function.");
- return NULL;
- }
- if (!instanceName || strlen(instanceName) == 0) {
- functions->logger(functions->componentEnvironment, "?", fmi2Error, "error",
- "fmi2Instantiate: Missing instance name.");
- return NULL;
- }
- if (!fmuGUID || strlen(fmuGUID) == 0) {
- functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error",
- "fmi2Instantiate: Missing GUID.");
- return NULL;
- }
- if (strcmp(fmuGUID, MODEL_GUID)) {
- functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error",
- "fmi2Instantiate: Wrong GUID %s. Expected %s.", fmuGUID, MODEL_GUID);
- return NULL;
- }
- comp = (ModelInstance *)functions->allocateMemory(1, sizeof(ModelInstance));
- if (comp) {
- int i;
- comp->r = (fmi2Real *) functions->allocateMemory(NUMBER_OF_REALS, sizeof(fmi2Real));
- comp->i = (fmi2Integer *)functions->allocateMemory(NUMBER_OF_INTEGERS, sizeof(fmi2Integer));
- comp->b = (fmi2Boolean *)functions->allocateMemory(NUMBER_OF_BOOLEANS, sizeof(fmi2Boolean));
- comp->s = (fmi2String *) functions->allocateMemory(NUMBER_OF_STRINGS, sizeof(fmi2String));
- comp->isPositive = (fmi2Boolean *)functions->allocateMemory(NUMBER_OF_EVENT_INDICATORS,
- sizeof(fmi2Boolean));
- comp->instanceName = (char *)functions->allocateMemory(1 + strlen(instanceName), sizeof(char));
- comp->GUID = (char *)functions->allocateMemory(1 + strlen(fmuGUID), sizeof(char));
-
- // set all categories to on or off. fmi2SetDebugLogging should be called to choose specific categories.
- for (i = 0; i < NUMBER_OF_CATEGORIES; i++) {
- comp->logCategories[i] = loggingOn;
- }
- }
- if (!comp || !comp->r || !comp->i || !comp->b || !comp->s || !comp->isPositive
- || !comp->instanceName || !comp->GUID) {
- functions->logger(functions->componentEnvironment, instanceName, fmi2Error, "error",
- "fmi2Instantiate: Out of memory.");
- return NULL;
- }
- comp->time = 0; // overwrite in fmi2SetupExperiment, fmi2SetTime
- strcpy((char *)comp->instanceName, (char *)instanceName);
- comp->type = fmuType;
- strcpy((char *)comp->GUID, (char *)fmuGUID);
- comp->functions = functions;
- comp->componentEnvironment = functions->componentEnvironment;
- comp->loggingOn = loggingOn;
- comp->state = modelInstantiated;
- instantiate(comp); // to be implemented by the includer of this file
- setStartValues(comp); // to be implemented by the includer of this file
- comp->isDirtyValues = fmi2True; // because we just called setStartValues
- comp->isNewEventIteration = fmi2False;
-
- comp->eventInfo.newDiscreteStatesNeeded = fmi2False;
- comp->eventInfo.terminateSimulation = fmi2False;
- comp->eventInfo.nominalsOfContinuousStatesChanged = fmi2False;
- comp->eventInfo.valuesOfContinuousStatesChanged = fmi2False;
- comp->eventInfo.nextEventTimeDefined = fmi2False;
- comp->eventInfo.nextEventTime = 0;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2Instantiate: GUID=%s", fmuGUID)
- return comp;
- }
- fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
- fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
- // ignore arguments: stopTimeDefined, stopTime
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetupExperiment", MASK_fmi2SetupExperiment))
- return fmi2Error;
-
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, ">fmi2SetupExperiment: toleranceDefined=%d tolerance=%g",
- toleranceDefined, tolerance)
-
- fmi2Status status = setupExperiment(comp, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); // to be implemented by includer.
-
- comp->time = startTime;
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "<fmi2SetupExperiment",
- toleranceDefined, tolerance)
-
- return status;
- }
- fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2EnterInitializationMode", MASK_fmi2EnterInitializationMode))
- return fmi2Error;
-
- fmi2Status status = enterInitializationMode(comp); // to be implemented by includer.
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "fmi2EnterInitializationMode")
-
- comp->state = modelInitializationMode;
-
- return status;
- }
- fmi2Status fmi2ExitInitializationMode(fmi2Component c) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2ExitInitializationMode", MASK_fmi2ExitInitializationMode))
- return fmi2Error;
-
- fmi2Status status = exitInitializationMode(comp); // to be implemented by includer.
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "fmi2ExitInitializationMode")
- // if values were set and no fmi2GetXXX triggered update before,
- // ensure calculated values are updated now
- if (comp->isDirtyValues) {
- calculateValues(comp);
- comp->isDirtyValues = fmi2False;
- }
- if (comp->type == fmi2ModelExchange) {
- comp->state = modelEventMode;
- comp->isNewEventIteration = fmi2True;
- }
- else comp->state = modelStepComplete;
- return status;
- }
- fmi2Status fmi2Terminate(fmi2Component c) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2Terminate", MASK_fmi2Terminate))
- return fmi2Error;
-
- fmi2Status status = terminate(comp); // to be implemented by includer.
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "fmi2Terminate")
- comp->state = modelTerminated;
- return status;
- }
- fmi2Status fmi2Reset(fmi2Component c) {
- ModelInstance* comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2Reset", MASK_fmi2Reset))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2Reset")
- comp->state = modelInstantiated;
- fmi2Status status = reset(comp); // to be implemented by includer.
- setStartValues(comp); // to be implemented by the includer of this file
- comp->isDirtyValues = fmi2True; // because we just called setStartValues
- return status;
- }
- void fmi2FreeInstance(fmi2Component c) {
- ModelInstance *comp = (ModelInstance *)c;
- if (!comp) return;
- if (invalidState(comp, "fmi2FreeInstance", MASK_fmi2FreeInstance))
- return;
-
- fmi2Status status = freeInstance(comp);
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "fmi2FreeInstance")
-
- 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; i < NUMBER_OF_STRINGS; i++){
- if (comp->s[i]) comp->functions->freeMemory((void *)comp->s[i]);
- }
- comp->functions->freeMemory((void *)comp->s);
- }
- if (comp->isPositive) comp->functions->freeMemory(comp->isPositive);
- if (comp->instanceName) comp->functions->freeMemory((void *)comp->instanceName);
- if (comp->GUID) comp->functions->freeMemory((void *)comp->GUID);
- comp->functions->freeMemory(comp);
- }
- // ---------------------------------------------------------------------------
- // FMI functions: class methods not depending of a specific model instance
- // ---------------------------------------------------------------------------
- const char* fmi2GetVersion() {
- return fmi2Version;
- }
- const char* fmi2GetTypesPlatform() {
- return fmi2TypesPlatform;
- }
- // ---------------------------------------------------------------------------
- // FMI functions: logging control, setters and getters for Real, Integer,
- // Boolean, String
- // ---------------------------------------------------------------------------
- fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
- // ignore arguments: nCategories, categories
- int i, j;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetDebugLogging", MASK_fmi2SetDebugLogging))
- return fmi2Error;
- comp->loggingOn = loggingOn;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetDebugLogging")
-
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "Resetting all %u categories", nCategories)
- // reset all categories
- for (j = 0; j < NUMBER_OF_CATEGORIES; j++) {
- comp->logCategories[j] = fmi2False;
- }
-
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "Categories reset")
-
- if (nCategories == 0) {
- // no category specified, set all categories to have loggingOn value
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "No category specified, so all of the become active.")
-
- for (j = 0; j < NUMBER_OF_CATEGORIES; j++) {
- comp->logCategories[j] = loggingOn;
- }
- } else {
- // set specific categories on
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "Categories specified. Activating them.")
-
- for (i = 0; i < nCategories; i++) {
- fmi2Boolean categoryFound = fmi2False;
- for (j = 0; j < NUMBER_OF_CATEGORIES; j++) {
- if (strcmp(logCategoriesNames[j], categories[i]) == 0) {
- comp->logCategories[j] = loggingOn;
- categoryFound = fmi2True;
- break;
- }
- }
- if (!categoryFound) {
- comp->functions->logger(comp->componentEnvironment, comp->instanceName, fmi2Warning,
- logCategoriesNames[LOG_ERROR],
- "logging category '%s' is not supported by model", categories[i]);
- }
- }
- }
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetDebugLogging")
- return fmi2OK;
- }
- fmi2Status fmi2GetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetReal", MASK_fmi2GetReal))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetReal", "vr[]", vr))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetReal", "value[]", value))
- return fmi2Error;
- if (nvr > 0 && comp->isDirtyValues) {
- calculateValues(comp);
- comp->isDirtyValues = fmi2True;
- }
- #if NUMBER_OF_REALS > 0
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2GetReal", vr[i], NUMBER_OF_REALS))
- return fmi2Error;
- value[i] = getReal(comp, vr[i]); // to be implemented by the includer of this file
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2GetReal: #r%u# = %.16g", vr[i], value[i])
- }
- #endif
- return fmi2OK;
- }
- fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetInteger", MASK_fmi2GetInteger))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetInteger", "vr[]", vr))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetInteger", "value[]", value))
- return fmi2Error;
- if (nvr > 0 && comp->isDirtyValues) {
- calculateValues(comp);
- comp->isDirtyValues = fmi2False;
- }
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2GetInteger", vr[i], NUMBER_OF_INTEGERS))
- return fmi2Error;
- value[i] = comp->i[vr[i]];
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2GetInteger: #i%u# = %d", vr[i], value[i])
- }
- return fmi2OK;
- }
- fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetBoolean", MASK_fmi2GetBoolean))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetBoolean", "vr[]", vr))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2GetBoolean", "value[]", value))
- return fmi2Error;
- if (nvr > 0 && comp->isDirtyValues) {
- calculateValues(comp);
- comp->isDirtyValues = fmi2False;
- }
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2GetBoolean", vr[i], NUMBER_OF_BOOLEANS))
- return fmi2Error;
- value[i] = comp->b[vr[i]];
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2GetBoolean: #b%u# = %s", vr[i], value[i]? "true" : "false")
- }
- return fmi2OK;
- }
- fmi2Status fmi2GetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetString", MASK_fmi2GetString))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2GetString", "vr[]", vr))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2GetString", "value[]", value))
- return fmi2Error;
- if (nvr > 0 && comp->isDirtyValues) {
- calculateValues(comp);
- comp->isDirtyValues = fmi2False;
- }
- for (i=0; i<nvr; i++) {
- if (vrOutOfRange(comp, "fmi2GetString", vr[i], NUMBER_OF_STRINGS))
- return fmi2Error;
- value[i] = comp->s[vr[i]];
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2GetString: #s%u# = '%s'", vr[i], value[i])
- }
- return fmi2OK;
- }
- fmi2Status fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetReal", MASK_fmi2SetReal))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2SetReal", "vr[]", vr))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2SetReal", "value[]", value))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetReal: nvr = %d", nvr)
- // no check whether setting the value is allowed in the current state
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2SetReal", vr[i], NUMBER_OF_REALS))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetReal: #r%d# = %.16g", vr[i], value[i])
- comp->r[vr[i]] = value[i];
- }
- if (nvr > 0) comp->isDirtyValues = fmi2True;
- return fmi2OK;
- }
- fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetInteger", MASK_fmi2SetInteger))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2SetInteger", "vr[]", vr))
- return fmi2Error;
- if (nvr > 0 && nullPointer(comp, "fmi2SetInteger", "value[]", value))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetInteger: nvr = %d", nvr)
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2SetInteger", vr[i], NUMBER_OF_INTEGERS))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetInteger: #i%d# = %d", vr[i], value[i])
- comp->i[vr[i]] = value[i];
- }
- if (nvr > 0) comp->isDirtyValues = fmi2True;
- return fmi2OK;
- }
- fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetBoolean", MASK_fmi2SetBoolean))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2SetBoolean", "vr[]", vr))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2SetBoolean", "value[]", value))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetBoolean: nvr = %d", nvr)
- for (i = 0; i < nvr; i++) {
- if (vrOutOfRange(comp, "fmi2SetBoolean", vr[i], NUMBER_OF_BOOLEANS))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetBoolean: #b%d# = %s", vr[i], value[i] ? "true" : "false")
- comp->b[vr[i]] = value[i];
- }
- if (nvr > 0) comp->isDirtyValues = fmi2True;
- return fmi2OK;
- }
- fmi2Status fmi2SetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
- int i, n;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetString", MASK_fmi2SetString))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2SetString", "vr[]", vr))
- return fmi2Error;
- if (nvr>0 && nullPointer(comp, "fmi2SetString", "value[]", value))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetString: nvr = %d", nvr)
- for (i = 0; i < nvr; i++) {
- char *string = (char *)comp->s[vr[i]];
- if (vrOutOfRange(comp, "fmi2SetString", vr[i], NUMBER_OF_STRINGS))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetString: #s%d# = '%s'", vr[i], value[i])
- if (value[i] == NULL) {
- if (string) comp->functions->freeMemory(string);
- comp->s[vr[i]] = NULL;
- FILTERED_LOG(comp, fmi2Warning, LOG_ERROR, "fmi2SetString: string argument value[%d] = NULL.", i);
- } else {
- if (string == NULL || strlen(string) < strlen(value[i])) {
- if (string) comp->functions->freeMemory(string);
- comp->s[vr[i]] = (char *)comp->functions->allocateMemory(1 + strlen(value[i]), sizeof(char));
- if (!comp->s[vr[i]]) {
- comp->state = modelError;
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "fmi2SetString: Out of memory.")
- return fmi2Error;
- }
- }
- strcpy((char *)comp->s[vr[i]], (char *)value[i]);
- }
- }
- if (nvr > 0) comp->isDirtyValues = fmi2True;
- return fmi2OK;
- }
- fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
- return unsupportedFunction(c, "fmi2GetFMUstate", MASK_fmi2GetFMUstate);
- }
- fmi2Status fmi2SetFMUstate (fmi2Component c, fmi2FMUstate FMUstate) {
- return unsupportedFunction(c, "fmi2SetFMUstate", MASK_fmi2SetFMUstate);
- }
- fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
- return unsupportedFunction(c, "fmi2FreeFMUstate", MASK_fmi2FreeFMUstate);
- }
- fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) {
- return unsupportedFunction(c, "fmi2SerializedFMUstateSize", MASK_fmi2SerializedFMUstateSize);
- }
- fmi2Status fmi2SerializeFMUstate (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) {
- return unsupportedFunction(c, "fmi2SerializeFMUstate", MASK_fmi2SerializeFMUstate);
- }
- fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size,
- fmi2FMUstate* FMUstate) {
- return unsupportedFunction(c, "fmi2DeSerializeFMUstate", MASK_fmi2DeSerializeFMUstate);
- }
- fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
- const fmi2ValueReference vKnown_ref[] , size_t nKnown,
- const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
- return unsupportedFunction(c, "fmi2GetDirectionalDerivative", MASK_fmi2GetDirectionalDerivative);
- }
- // ---------------------------------------------------------------------------
- // Functions for FMI for Co-Simulation
- // ---------------------------------------------------------------------------
- #ifdef FMI_COSIMULATION
- /* Simulating the slave */
- fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
- const fmi2Integer order[], const fmi2Real value[]) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2SetRealInputDerivatives", MASK_fmi2SetRealInputDerivatives)) {
- return fmi2Error;
- }
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2SetRealInputDerivatives: nvr= %d", nvr)
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR, "fmi2SetRealInputDerivatives: ignoring function call."
- " This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\"")
- return fmi2Error;
- }
- fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
- const fmi2Integer order[], fmi2Real value[]) {
- int i;
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetRealOutputDerivatives", MASK_fmi2GetRealOutputDerivatives))
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2GetRealOutputDerivatives: nvr= %d", nvr)
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR,"fmi2GetRealOutputDerivatives: ignoring function call."
- " This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\"")
- for (i = 0; i < nvr; i++) value[i] = 0;
- return fmi2Error;
- }
- fmi2Status fmi2CancelStep(fmi2Component c) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2CancelStep", MASK_fmi2CancelStep)) {
- // always fmi2CancelStep is invalid, because model is never in modelStepInProgress state.
- return fmi2Error;
- }
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2CancelStep")
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR,"fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending."
- " This is not the case.");
- // comp->state = modelStepCanceled;
- return fmi2Error;
- }
- fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint,
- fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
- ModelInstance *comp = (ModelInstance *)c;
-
- if (invalidState(comp, "fmi2DoStep", MASK_fmi2DoStep))
- return fmi2Error;
- if (communicationStepSize <= 0) {
- FILTERED_LOG(comp, fmi2Error, LOG_ERROR,
- "fmi2DoStep: communication step size must be > 0. Fount %g.", communicationStepSize)
- comp->state = modelError;
- return fmi2Error;
- }
-
- fmi2Status status = doStep(comp, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint);
-
- FILTERED_LOG(comp, status, LOG_FMI_CALL, "fmi2DoStep: "
- "currentCommunicationPoint = %g, "
- "communicationStepSize = %g, "
- "noSetFMUStatePriorToCurrentPoint = fmi2%s",
- currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint ? "True" : "False")
-
- return fmi2OK;
- }
- /* Inquire slave status */
- static fmi2Status getStatus(char* fname, fmi2Component c, const fmi2StatusKind s) {
- const char *statusKind[3] = {"fmi2DoStepStatus","fmi2PendingStatus","fmi2LastSuccessfulTime"};
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, fname, MASK_fmi2GetStatus)) // all get status have the same MASK_fmi2GetStatus
- return fmi2Error;
- FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "$s: fmi2StatusKind = %s", fname, statusKind[s])
- switch(s) {
- case fmi2DoStepStatus: FILTERED_LOG(comp, fmi2Error, LOG_ERROR,
- "%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending."
- " This is not the case.", fname)
- break;
- case fmi2PendingStatus: FILTERED_LOG(comp, fmi2Error, LOG_ERROR,
- "%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending."
- " This is not the case.", fname)
- break;
- case fmi2LastSuccessfulTime: FILTERED_LOG(comp, fmi2Error, LOG_ERROR,
- "%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard."
- " This is not the case.", fname)
- break;
- case fmi2Terminated: FILTERED_LOG(comp, fmi2Error, LOG_ERROR,
- "%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard."
- " This is not the case.", fname)
- break;
- }
- return fmi2Discard;
- }
- fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) {
- return getStatus("fmi2GetStatus", c, s);
- }
- fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) {
- if (s == fmi2LastSuccessfulTime) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetRealStatus", MASK_fmi2GetRealStatus))
- return fmi2Error;
- *value = comp->time;
- return fmi2OK;
- }
- return getStatus("fmi2GetRealStatus", c, s);
- }
- fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) {
- return getStatus("fmi2GetIntegerStatus", c, s);
- }
- fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) {
- if (s == fmi2Terminated) {
- ModelInstance *comp = (ModelInstance *)c;
- if (invalidState(comp, "fmi2GetBooleanStatus", MASK_fmi2GetBooleanStatus))
- return fmi2Error;
- *value = comp->eventInfo.terminateSimulation;
- return fmi2OK;
- }
- return getStatus("fmi2GetBooleanStatus", c, s);
- }
- fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) {
- return getStatus("fmi2GetStringStatus", c, s);
- }
- #endif // Functions for Co-Simulation
- #ifdef __cplusplus
- } // closing brace for extern "C"
- #endif
|