Skip to content

Commit

Permalink
- Implemented fmiGetTypesPlatform, fmiGetVersion, fmiInstantiate, fmi…
Browse files Browse the repository at this point in the history
…FreeInstance, fmiSetupExperiment, fmiEnterInitializationMode & fmiExitInitializationMode functions for FMI 2.0 export.

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@20888 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
adeas31 committed May 29, 2014
1 parent 8501fa3 commit f90dc5b
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 54 deletions.
8 changes: 4 additions & 4 deletions SimulationRuntime/fmi/export/fmi1/fmu1_model_interface.c
Expand Up @@ -529,8 +529,8 @@ fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_
* getEventIndicator(comp, eventIndicators); // to be implemented by the includer of this file */
eventIndicators[i] = comp->fmuData->simulationInfo.zeroCrossings[i];
if (comp->loggingOn){
comp->functions.logger(c, comp->instanceName, fmiOK, "log",
"fmiGetEventIndicators: z%d = %.16g", i, eventIndicators[i]);
comp->functions.logger(c, comp->instanceName, fmiOK, "log",
"fmiGetEventIndicators: z%d = %.16g", i, eventIndicators[i]);
}
}
#endif
Expand Down Expand Up @@ -631,7 +631,7 @@ fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEven
if (stateSelection(comp->fmuData, 1, 1))
{
if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log",
"fmiEventUpdate: Need to iterate state values changed!");
"fmiEventUpdate: Need to iterate state values changed!");
/* if new set is calculated reinit the solver */
eventInfo->stateValuesChanged = fmiTrue;
}
Expand Down Expand Up @@ -748,7 +748,7 @@ fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean* callEventUpdate
if (stateSelection(comp->fmuData,1, 0))
{
if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log",
"fmiEventUpdate: Need to iterate state values changed!");
"fmiEventUpdate: Need to iterate state values changed!");
/* if new set is calculated reinit the solver */
*callEventUpdate = fmiTrue;
}
Expand Down
24 changes: 12 additions & 12 deletions SimulationRuntime/fmi/export/fmi1/fmu1_model_interface.h
Expand Up @@ -45,24 +45,24 @@ extern "C" {
#define not_modelError (modelInstantiated|modelInitialized|modelTerminated)

typedef enum {
modelInstantiated = 1<<0,
modelInitialized = 1<<1,
modelTerminated = 1<<2,
modelError = 1<<3
modelInstantiated = 1<<0,
modelInitialized = 1<<1,
modelTerminated = 1<<2,
modelError = 1<<3
} ModelState;

typedef struct {
fmiString instanceName;
fmiString GUID;
fmiCallbackFunctions functions;
fmiBoolean loggingOn;
fmiEventInfo eventInfo;
ModelState state;
DATA* fmuData;
fmiString instanceName;
fmiString GUID;
fmiCallbackFunctions functions;
fmiBoolean loggingOn;
fmiEventInfo eventInfo;
ModelState state;
DATA* fmuData;
} ModelInstance;

fmiStatus setString(fmiComponent comp, fmiValueReference vr, fmiString value){
return fmiSetString(comp, &vr, 1, &value);
return fmiSetString(comp, &vr, 1, &value);
}

#ifdef __cplusplus
Expand Down
208 changes: 186 additions & 22 deletions SimulationRuntime/fmi/export/fmi2/fmu2_model_interface.c
Expand Up @@ -38,49 +38,80 @@
#include "simulation/simulation_info_xml.h"
#include "simulation/simulation_input_xml.h"

// macro to be used to log messages. The macro check if current
// log category is valid and, if true, call the logger provided by simulator.
#define FILTERED_LOG(instance, status, categoryIndex, message, ...) if (isCategoryLogged(instance, categoryIndex)) \
instance->functions->logger(instance->functions->componentEnvironment, instance->instanceName, status, \
logCategoriesNames[categoryIndex], message, ##__VA_ARGS__);

static fmiString logCategoriesNames[] = {"logAll", "logError", "logFmiCall", "logEvent"};

// array of value references of states
#if NUMBER_OF_STATES>0
#if NUMBER_OF_REALS>0
fmiValueReference vrStates[NUMBER_OF_STATES] = STATES;
fmiValueReference vrStatesDerivatives[NUMBER_OF_STATES] = STATESDERIVATIVES;
#endif

static fmiBoolean invalidNumber(ModelInstance* comp, const char* f, const char* arg, int n, int nExpected){
// ---------------------------------------------------------------------------
// Private helpers used below to validate function arguments
// ---------------------------------------------------------------------------
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);
FILTERED_LOG(comp, fmiError, LOG_ERROR, "%s: Invalid argument %s = %d. Expected %d.", f, arg, n, nExpected)
return fmiTrue;
}
return fmiFalse;
}

static fmiBoolean invalidState(ModelInstance* comp, const char* f, int statesExpected){
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. Expected State: %d.", f, statesExpected);
FILTERED_LOG(comp, fmiError, LOG_ERROR, "%s: Illegal call sequence.", f)
return fmiTrue;
}
return fmiFalse;
}

static fmiBoolean nullPointer(ModelInstance* comp, const char* f, const char* arg, const void* p){
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);
FILTERED_LOG(comp, fmiError, LOG_ERROR, "%s: Invalid argument %s = NULL.", f, arg)
return fmiTrue;
}
return fmiFalse;
}

static fmiBoolean vrOutOfRange(ModelInstance* comp, const char* f, fmiValueReference vr, unsigned int end) {
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;
FILTERED_LOG(comp, fmiError, LOG_ERROR, "%s: Illegal value reference %u.", f, vr)
return fmiTrue;
}
return fmiFalse;
}

static fmiStatus unsupportedFunction(fmiComponent c, const char *fName, int statesExpected) {
ModelInstance *comp = (ModelInstance *)c;
fmiCallbackLogger log = comp->functions->logger;
if (invalidState(comp, fName, statesExpected))
return fmiError;
if (comp->loggingOn) log(c, comp->instanceName, fmiOK, "log", fName);
FILTERED_LOG(comp, fmiError, LOG_ERROR, "%s: Function not implemented.", fName)
return fmiError;
}

fmiStatus setString(fmiComponent comp, fmiValueReference vr, fmiString value) {
return fmiSetString(comp, &vr, 1, &value);
}

// ---------------------------------------------------------------------------
// Private helpers logger
// ---------------------------------------------------------------------------
// return fmiTrue if logging category is on. Else return fmiFalse.
fmiBoolean isCategoryLogged(ModelInstance *comp, int categoryIndex) {
if (categoryIndex < NUMBER_OF_CATEGORIES && (comp->logCategories[categoryIndex] || comp->logCategories[LOG_ALL])) {
return fmiTrue;
}
return fmiFalse;
Expand All @@ -89,7 +120,6 @@ static fmiBoolean vrOutOfRange(ModelInstance* comp, const char* f, fmiValueRefer
/***************************************************
Common Functions
****************************************************/

const char* fmiGetTypesPlatform() {
return fmiTypesPlatform;
}
Expand All @@ -105,31 +135,165 @@ fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn, size_t nCateg

fmiComponent fmiInstantiate(fmiString instanceName, fmiType fmuType, fmiString fmuGUID, fmiString fmuResourceLocation, const fmiCallbackFunctions* functions,
fmiBoolean visible, fmiBoolean loggingOn) {
// TODO Write code here
return NULL;
// ignoring arguments: fmuResourceLocation, visible
ModelInstance *comp;
if (!functions->logger) {
return NULL;
}

if (!functions->allocateMemory || !functions->freeMemory) {
functions->logger(functions->componentEnvironment, instanceName, fmiError, "error", "fmiInstantiate: Missing callback function.");
return NULL;
}
if (!instanceName || strlen(instanceName) == 0) {
functions->logger(functions->componentEnvironment, instanceName, fmiError, "error", "fmiInstantiate: Missing instance name.");
return NULL;
}
if (strcmp(fmuGUID, MODEL_GUID)) {
functions->logger(functions->componentEnvironment, instanceName, fmiError, "error", "fmiInstantiate: Wrong GUID %s. Expected %s.", fmuGUID, MODEL_GUID);
return NULL;
}
comp = (ModelInstance *)functions->allocateMemory(1, sizeof(ModelInstance));
if (comp) {
comp->instanceName = functions->allocateMemory(1 + strlen(instanceName), sizeof(char));
comp->GUID = functions->allocateMemory(1 + strlen(fmuGUID), sizeof(char));
DATA* fmudata = (DATA *)functions->allocateMemory(1, sizeof(DATA));
threadData_t *threadData = (threadData_t *)functions->allocateMemory(1, sizeof(threadData));
fmudata->threadData = threadData;
comp->fmuData = fmudata;
if (!comp->fmuData) {
functions->logger(functions->componentEnvironment, instanceName, fmiError, "error", "fmiInstantiate: Could not initialize the global data structure file.");
return NULL;
}
// set all categories to on or off. fmiSetDebugLogging should be called to choose specific categories.
int i;
for (i = 0; i < NUMBER_OF_CATEGORIES; i++) {
comp->logCategories[i] = loggingOn;
}
}
if (!comp || !comp->instanceName || !comp->GUID || !comp->fmuData) {
functions->logger(functions->componentEnvironment, instanceName, fmiError, "error", "fmiInstantiate: Out of memory.");
return NULL;
}
strcpy(comp->instanceName, instanceName);
comp->type = fmuType;
strcpy(comp->GUID, fmuGUID);
comp->functions = functions;
comp->componentEnvironment = functions->componentEnvironment;
comp->loggingOn = loggingOn;
comp->state = modelInstantiated;
/* intialize modelData */
fmu2_model_interface_setupDataStruc(comp->fmuData);
initializeDataStruc(comp->fmuData);
/* setup model data with default start data */
setDefaultStartValues(comp);
setAllVarsToStart(comp->fmuData);
setAllParamsToStart(comp->fmuData);
read_input_xml(&(comp->fmuData->modelData), &(comp->fmuData->simulationInfo));
modelInfoXmlInit(&(comp->fmuData->modelData.modelDataXml));
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiInstantiate: GUID=%s", fmuGUID)
return comp;
}

void fmiFreeInstance(fmiComponent c) {
ModelInstance *comp = (ModelInstance *)c;
if (!comp) return;
if (invalidState(comp, "fmiFreeInstance", modelTerminated))
return;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiFreeInstance")

if (comp->instanceName) comp->functions->freeMemory(comp->instanceName);
if (comp->GUID) comp->functions->freeMemory(comp->GUID);
comp->functions->freeMemory(comp);
}

fmiStatus fmiSetupExperiment(fmiComponent c, fmiBoolean toleranceDefined, fmiReal tolerance, fmiReal startTime, fmiBoolean stopTimeDefined, fmiReal stopTime) {
// TODO Write code here
ModelInstance *comp = (ModelInstance *)c;
if (invalidState(comp, "fmiSetupExperiment", modelInstantiated))
return fmiError;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiSetupExperiment: toleranceDefined=%d tolerance=%g startTime=%g stopTimeDefined=%d stopTime=%g", toleranceDefined, tolerance,
startTime, stopTimeDefined, stopTime)

comp->toleranceDefined = toleranceDefined;
comp->tolerance = tolerance;
comp->startTime = startTime;
comp->stopTimeDefined = stopTimeDefined;
comp->stopTime = stopTime;
return fmiOK;
}

fmiStatus fmiEnterInitializationMode(fmiComponent c) {
// TODO Write code here
ModelInstance *comp = (ModelInstance *)c;
if (invalidState(comp, "fmiEnterInitializationMode", modelInstantiated))
return fmiError;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiEnterInitializationMode")
comp->state = modelInitializationMode;
/* set zero-crossing tolerance */
setZCtol(comp->tolerance);

setStartValues(comp);
copyStartValuestoInitValues(comp->fmuData);
/* read input vars */
//input_function(comp->fmuData);
/* initial sample and delay before initial the system */
comp->fmuData->callback->callExternalObjectConstructors(comp->fmuData);
/* allocate memory for non-linear system solvers */
allocateNonlinearSystem(comp->fmuData);
/* allocate memory for non-linear system solvers */
allocatelinearSystem(comp->fmuData);
/* allocate memory for mixed system solvers */
allocatemixedSystem(comp->fmuData);
/* allocate memory for state selection */
initializeStateSetJacobians(comp->fmuData);
if (initialization(comp->fmuData, "", "", "", 0.0, 5)) {
comp->state = modelError;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiEnterInitializationMode: failed")
}
else
{
comp->state = modelInitializationMode;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiEnterInitializationMode: succeed")
}
/*TODO: Simulation stop time is need to calculate in before hand all sample events
We shouldn't generate them all in beforehand */
initSample(comp->fmuData, comp->fmuData->localData[0]->timeValue, 100 /*should be stopTime*/);
initDelay(comp->fmuData, comp->fmuData->localData[0]->timeValue);

/* due to an event overwrite old values */
overwriteOldSimulationData(comp->fmuData);

comp->eventInfo.terminateSimulation = fmiFalse;
comp->eventInfo.valuesOfContinuousStatesChanged = fmiTrue;

/* Get next event time (sample calls)*/
double nextSampleEvent = 0;
nextSampleEvent = getNextSampleTimeFMU(comp->fmuData);
if (nextSampleEvent == -1){
comp->eventInfo.nextEventTimeDefined = fmiFalse;
}else{
comp->eventInfo.nextEventTimeDefined = fmiTrue;
comp->eventInfo.nextEventTime = nextSampleEvent;
//fmiEventUpdate(comp, fmiFalse, &(comp->eventInfo));
}
return fmiOK;
}

fmiStatus fmiExitInitializationMode(fmiComponent c) {
// TODO Write code here
ModelInstance *comp = (ModelInstance *)c;
if (invalidState(comp, "fmiExitInitializationMode", modelInitializationMode))
return fmiError;
FILTERED_LOG(comp, fmiOK, LOG_FMI_CALL, "fmiExitInitializationMode")

comp->state = modelInitialized;
return fmiOK;
}

fmiStatus fmiTerminate(fmiComponent c) {
// TODO Write code here
// ModelInstance* comp = (ModelInstance *)c;
// if (invalidState(comp, "fmiTerminate", modelInitialized))
// return fmiError;
// if (comp->loggingOn) comp->functions->logger(c, comp->instanceName, fmiOK, "log", "fmiTerminate");
// comp->state = modelTerminated;
return fmiOK;
}

Expand Down Expand Up @@ -329,7 +493,7 @@ fmiStatus fmiSetExternalFunction(fmiComponent c, fmiValueReference vr[], size_t
return fmiError;
if (nvr>0 && nullPointer(comp, "fmiSetExternalFunction", "value[]", value))
return fmiError;
if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log",
if (comp->loggingOn) comp->functions->logger(c, comp->instanceName, fmiOK, "log",
"fmiSetExternalFunction");
// no check wether setting the value is allowed in the current state
for (i=0; i<nvr; i++) {
Expand Down

0 comments on commit f90dc5b

Please sign in to comment.