Skip to content

Commit

Permalink
Merge branch 'release/v2.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
t-sommer committed Sep 21, 2020
2 parents e653a8a + 71a2a6f commit d59271d
Show file tree
Hide file tree
Showing 17 changed files with 193 additions and 210 deletions.
2 changes: 1 addition & 1 deletion +FMIKit/minorVersion.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function v = minorVersion()
% FMIKit.minorVersion Get the minor version of FMI Kit

v = 8;
v = 9;

end
17 changes: 15 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# Changelog

## 2.8
## v2.9

This release resolves issues with the FMU export:

- Fix memory allocation and fmi2Reset() in rtwsfcnfmi.tlc (#31)
- Initialize model variables in fmi2Reset() in grtfmi.tlc (#211)
- Use 0-based indexing when exporting FMI 2.0 arrays in grtfmi.tlc and rtwsfcnfmi.tlc (#208)
- Add sources of referenced models in grtfmi.tlc
- Evaluate nextEventTimeDefined in Model Exchange (#209)
- Skip duplicate CGType indices in rtwsfcnfmi.tlc (#205)
- Escape special characters in input and output variables in grtfmi.tlc (#206)
- Fix loading of MEX S-functions in rtwsfcnfmi.tlc (#203)

## v2.8

This release improves the import of source code FMUs and fixes issues with export of FMUs.
The build system for the S-function based target has been changed to CMake for improved flexibility.
Expand All @@ -25,7 +38,7 @@ The build system for the S-function based target has been changed to CMake for i

- `new` build system changed to CMake (same as for grtfmi.tlc)

## 2.7
## v2.7

This release brings fixes and improvements for the import and export of FMUs.
It is now distributed as a ZIP archive (instead of a MATLAB App) for easier deployment.
Expand Down
4 changes: 1 addition & 3 deletions grtfmi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,12 @@ set(HEADERS ${HEADERS} ${MATLAB_HEADERS})
set(HEADERS ${HEADERS} ${SIMULINK_HEADERS})

FILE(GLOB RTW_SOURCES "${RTW_DIR}/*.c")
FILE(GLOB SHARED_SOURCES "${RTW_DIR}/../slprj/grtfmi/_sharedutils/*.c")
FILE(GLOB REFMODEL_SOURCES "${RTW_DIR}/../slprj/grtfmi/sldemo_mdlref_counter_bus/*.c")
FILE(GLOB SHARED_SOURCES "${RTW_DIR}/../slprj/grtfmi/*/*.c")

set(SOURCES
"${MATLAB_ROOT}/rtw/c/src/rt_matrx.c"
${RTW_SOURCES}
${SHARED_SOURCES}
${REFMODEL_SOURCES}
${RTW_DIR}/fmiwrapper.inc
${CMAKE_SOURCE_DIR}/fmi${FMI_VERSION}Functions.c
${CUSTOM_SOURCE}
Expand Down
2 changes: 2 additions & 0 deletions grtfmi/fmi2Functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ fmi2Status fmi2Reset(fmi2Component c) {
MODEL_INITIALIZE();
#endif

initializeModelVariables(instance->S, instance->modelVariables);

return fmi2OK;
}

Expand Down
1 change: 1 addition & 0 deletions grtfmi/grtfmi_xml_encode.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
string = strrep(string, '&', '&');
string = strrep(string, '<', '&lt;');
string = strrep(string, '>', '&gt;');
string = strrep(string, '"', '&quot;');
string = strrep(string, char(hex2dec('D')), ' '); % carriage return
string = strrep(string, char(hex2dec('A')), ' '); % line feed
string = strrep(string, char(hex2dec('9')), ' '); % tab
Expand Down
6 changes: 4 additions & 2 deletions grtfmi/grtfmilib.tlc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
%endfunction

%function VariableFMI2(record, variableName, dataName, vr, variableAttr, typeAttr) Output
%assign variableName = FEVAL("grtfmi_xml_encode", variableName)
%assign dataTypeName = SLibGetRecordDataTypeName(record, "")
%assign fmiType = GetFMIType(record)
%assign dtypeID = LibGetRecordContainerDataTypeId(record)
Expand Down Expand Up @@ -131,10 +132,10 @@
%foreach rowid = nRows
%if nCols > 1 && nRows > 1
%assign dataSubs = "[%<index>]"
%assign variableSubs = "[%<rowid+1>,%<colid+1>]"
%assign variableSubs = "[%<rowid>,%<colid>]"
%elseif width > 1
%assign dataSubs = "[%<index>]"
%assign variableSubs = "[%<index+1>]"
%assign variableSubs = "[%<index>]"
%else
%assign dataSubs = ""
%assign variableSubs = ""
Expand Down Expand Up @@ -194,6 +195,7 @@
%endfunction

%function VariableFMI3(record, variableName, dataName, vr, variableAttr, typeAttr) Output
%assign variableName = FEVAL("grtfmi_xml_encode", variableName)
%assign dataTypeName = SLibGetRecordDataTypeName(record, "")
%assign fmiType = GetFMI3Type(dataTypeName)
%assign dtypeID = LibGetRecordDataTypeId(record)
Expand Down
2 changes: 1 addition & 1 deletion grtfmi/grtfmixml.tlc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
instantiationToken="%<GUID>"
%endif
modelName="%<OrigName>"
generationTool="Simulink %<Version> with FMI Kit 2.8 (grtfmi.tlc, %<Solver>, %<FundamentalStepSize> s)"
generationTool="Simulink %<Version> with FMI Kit 2.9 (grtfmi.tlc, %<Solver>, %<FundamentalStepSize> s)"
%assign XMLdate = FEVAL("grtfmi_xml_datetime")
generationDateAndTime="%<XMLdate>"
%assign description = FEVAL("get_param", "%<OrigName>", "Description")
Expand Down
9 changes: 4 additions & 5 deletions include/sfun_fmu_fmi2_me.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* This file is part of FMIKit. See LICENSE.txt in the project *
* root for license information. *
*****************************************************************/

#include <stdarg.h>

#define S_FUNCTION_LEVEL 2
Expand Down Expand Up @@ -42,7 +42,7 @@ static void mdlStart(SimStruct *S) {

time_T startTime = ssGetT(S);
time_T stopTime = ssGetTFinal(S);

static fmi2CallbackFunctions callbacks = { logFMUMessage, calloc, free, NULL, NULL };

EVENT_INFO_PTR = calloc(1, sizeof(fmi2EventInfo));
Expand Down Expand Up @@ -79,12 +79,11 @@ static void mdlStart(SimStruct *S) {

static void update(SimStruct *S) {

fmi2Boolean timeEvent, stateEvent;
fmi2Boolean enterEventMode, terminateSimulation;
fmi2Boolean timeEvent, stateEvent, enterEventMode, terminateSimulation;
int i;

// Work around for the event handling in Dymola FMUs:
timeEvent = ssGetT(S) >= EVENT_INFO->nextEventTime;
timeEvent = EVENT_INFO->nextEventTimeDefined && ssGetT(S) >= EVENT_INFO->nextEventTime;

ASSERT_OK(fmi2CompletedIntegratorStep(COMPONENT, fmi2True, &enterEventMode, &terminateSimulation), "Completed integrator step failed")

Expand Down
8 changes: 6 additions & 2 deletions rtwsfcnfmi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,26 @@ target_include_directories(${SOLVER} PRIVATE
"${MATLAB_ROOT}/rtw/c/src"
)

set(MODEL_SOURCES
set(MODEL_SOURCES
../include/fmi2Functions.h
../include/fmi2FunctionTypes.h
../include/fmi2TypesPlatform.h
fmi2Functions.c
sfunction.h
sfunction.c
"${RTW_DIR}/sfcn_fmi.h"
"${RTW_DIR}/modelDescription.xml"
)

if (EXISTS "${RTW_DIR}/rt_zcfcn.c")
set (MODEL_SOURCES ${MODEL_SOURCES} "${RTW_DIR}/rt_zcfcn.c")
endif ()

if (NOT LOAD_MEX)
set (MODEL_SOURCES ${MODEL_SOURCES} "${MATLAB_ROOT}/rtw/c/src/rt_matrx.c")
endif ()

add_library(${MODEL_NAME} SHARED
"${MATLAB_ROOT}/rtw/c/src/rt_matrx.c"
${MODEL_SOURCES}
${CUSTOM_SOURCE}
)
Expand Down
75 changes: 39 additions & 36 deletions rtwsfcnfmi/fmi2Functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@
#include "model_interface.h"


typedef struct {
fmi2CallbackFunctions functions;
fmi2EventInfo eventInfo;
} UserData;


/* -------------- Macro to check if initialized -------------- */

#define CHECK_INITIALIZED(model, label) \
Expand Down Expand Up @@ -55,9 +49,9 @@ static void logMessage(Model *model, int status, const char *message, ...) {
vsnprintf(buf, 1024, message, args);
va_end(args);

UserData *userData = (UserData *)model->userData;
fmi2CallbackFunctions *functions = (fmi2CallbackFunctions *)model->userData;

userData->functions.logger(userData->functions.componentEnvironment, model->instanceName, status, "", buf);
functions->logger(functions->componentEnvironment, model->instanceName, status, "", buf);
}

/* Function for double precision comparison */
Expand Down Expand Up @@ -118,29 +112,29 @@ fmi2Component fmi2Instantiate(fmi2String instanceName,
{
/* The following arguments are ignored: fmuResourceLocation, visible */

// TODO: check GUID
///* verify GUID */
//if (strcmp(GUID, MODEL_GUID) != 0) {
// logMessage(model, fmi2Error, "Invalid GUID: %s, expected %s\n", GUID, MODEL_GUID);
// functions->freeMemory(model);
// return NULL;
//}
// check logger callback
if (!functions || !functions->logger) {
return NULL;
}

// TODO: check logger callback
/* verify GUID */
if (strcmp(GUID, MODEL_GUID) != 0) {
functions->logger(NULL, instanceName, fmi2Error, "logError", "Invalid GUID \"%s\", expected \"%s\".", GUID, MODEL_GUID);
return NULL;
}

UserData *userData = (UserData *)calloc(1, sizeof(UserData));
userData->functions = *functions;
fmi2CallbackFunctions *callbacks = (fmi2CallbackFunctions *)calloc(1, sizeof(fmi2CallbackFunctions));

memcpy(callbacks, functions, sizeof(fmi2CallbackFunctions));

Model *model = InstantiateModel(instanceName, logMessage, userData);
Model *model = InstantiateModel(instanceName, logMessage, fmuType == fmi2CoSimulation, callbacks);

initializeModelVariables(model->S, model->modelVariables);

model->isCoSim = fmi2False;
model->hasEnteredContMode = fmi2False;

if (fmuType == fmi2CoSimulation) {
model->isCoSim = fmi2True;
if (functions->stepFinished != NULL) {
logMessage(model, fmi2Warning, "fmi2Instantiate: Callback function stepFinished != NULL but asynchronous fmi2DoStep is not supported");

if (functions->stepFinished) {
logMessage(model, fmi2Warning, "Callback function stepFinished != NULL but asynchronous fmi2DoStep is not supported.");
}
}

Expand All @@ -149,9 +143,10 @@ fmi2Component fmi2Instantiate(fmi2String instanceName,

void fmi2FreeInstance(fmi2Component c)
{
Model* model = (Model*) c;
// TODO: fix this
//FreeModel(model);
Model* model = (Model*)c;
free(model->userData);
model->userData = NULL;
FreeModel(model);
}

fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time);
Expand Down Expand Up @@ -234,12 +229,13 @@ fmi2Status fmi2ExitInitializationMode(fmi2Component c)
{
Model* model = (Model*) c;
fmi2Status status = fmi2OK;
fmi2EventInfo eventInfo = { 0 };

model->status = modelEventMode;

if (model->isCoSim) {
/* Evaluate model at t=0 */
status = fmi2NewDiscreteStates(c, &(((UserData *)model->userData)->eventInfo));
status = fmi2NewDiscreteStates(c, &eventInfo);
if (status != fmi2OK) {
model->status = modelInstantiated;
return status;
Expand Down Expand Up @@ -270,11 +266,18 @@ fmi2Status fmi2Terminate(fmi2Component c)
fmi2Status fmi2Reset(fmi2Component c)
{
Model* model = (Model*) c;

Model *temp = (Model *)calloc(1, sizeof(Model));

memcpy(temp, model, sizeof(Model));

Model *new_model = InstantiateModel(model->instanceName, logMessage, model->isCoSim, model->userData);

initializeModelVariables(new_model->S, new_model->modelVariables);

ResetModel(model);
memcpy(model, new_model, sizeof(Model));

UserData *userData = (UserData *)model->userData;
memset(&(userData->eventInfo), 0, sizeof(fmi2EventInfo));
FreeModel(temp);

return fmi2OK;
}
Expand Down Expand Up @@ -925,8 +928,8 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2R
/* Extrapolate inputs */
extrapolateInputs(model, nextSolverTime);
/* Set sample hits and call mdlOutputs / mdlUpdate (always a discrete sample time = Fixed-step size) */
UserData *userData = (UserData *)model->userData;
fmi2NewDiscreteStates(c, &(userData->eventInfo));
fmi2EventInfo eventInfo = { 0 };
fmi2NewDiscreteStates(c, &eventInfo);
/* Update solver times */
lastSolverTime = nextSolverTime;
model->nbrSolverSteps++;
Expand Down Expand Up @@ -1020,8 +1023,8 @@ static void logger(fmi2Component c, fmi2String instanceName, fmi2Status status,
vsnprintf(buf, capacity, message, ap);
#endif
va_end(ap);
fmi2ComponentEnvironment componentEnvironment = ((UserData *)model->userData)->functions.componentEnvironment;
((UserData *)model->userData)->functions.logger(componentEnvironment, instanceName, status, category, buf);
fmi2CallbackFunctions *functions = (fmi2CallbackFunctions *)model->userData;
functions->logger(functions->componentEnvironment, instanceName, status, category, buf);
}

/* FMU mapping of ssPrintf for child C source S-functions (through rtPrintfNoOp) */
Expand Down
4 changes: 4 additions & 0 deletions rtwsfcnfmi/rtwsfcnfmi_make_rtw_hook.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ function rtwsfcnfmi_make_rtw_hook(hookMethod, modelName, rtwRoot, templateMakefi
for i = 1:numel(mex_functions)
copyfile(which(mex_functions{i}), fullfile('FMUArchive', 'binaries', fmi_platform));
end
load_mex = 'YES';
else
load_mex = 'NO';
end

% write the CMakeCache.txt file
Expand All @@ -99,6 +102,7 @@ function rtwsfcnfmi_make_rtw_hook(hookMethod, modelName, rtwRoot, templateMakefi
fprintf(fid, 'CUSTOM_INCLUDE:STRING=%s\n', custom_include);
fprintf(fid, 'CUSTOM_SOURCE:STRING=%s\n', custom_source);
fprintf(fid, 'CUSTOM_LIBRARY:STRING=%s\n', custom_library);
fprintf(fid, 'LOAD_MEX:BOOL=%s\n', load_mex);
fprintf(fid, 'BINARY_SFUNCTIONS:STRING=%s\n', cmake_list(mex_functions));
fprintf(fid, 'COMPILER_OPTIMIZATION_LEVEL:STRING=%s\n', get_param(modelName, 'CMakeCompilerOptimizationLevel'));
fprintf(fid, 'COMPILER_OPTIMIZATION_FLAGS:STRING=%s\n', get_param(modelName, 'CMakeCompilerOptimizationFlags'));
Expand Down
4 changes: 2 additions & 2 deletions rtwsfcnfmi/rtwsfcnfmilib.tlc
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@
%foreach rowid = nRows
%if nCols > 1 && nRows > 1
%assign dataSubs = "[%<index>]"
%assign variableSubs = "[%<rowid+1>,%<colid+1>]"
%assign variableSubs = "[%<rowid>,%<colid>]"
%elseif width > 1
%assign dataSubs = "[%<index>]"
%assign variableSubs = "[%<index+1>]"
%assign variableSubs = "[%<index>]"
%else
%assign dataSubs = ""
%assign variableSubs = ""
Expand Down
10 changes: 8 additions & 2 deletions rtwsfcnfmi/rtwsfcnfmixml.tlc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
%endif
modelName="%<OrigName>"
%if FMIType == "CoSimulation"
generationTool="Simulink %<Version> with FMI Kit 2.8 (rtwsfcnfmi.tlc, %<Solver>, %<FundamentalStepSize> s)"
generationTool="Simulink %<Version> with FMI Kit 2.9 (rtwsfcnfmi.tlc, %<Solver>, %<FundamentalStepSize> s)"
%else
generationTool="Simulink %<Version> with FMI Kit 2.8 (rtwsfcnfmi.tlc)"
generationTool="Simulink %<Version> with FMI Kit 2.9 (rtwsfcnfmi.tlc)"
%endif
%assign XMLdate = FEVAL("grtfmi_xml_datetime")
generationDateAndTime="%<XMLdate>"
Expand Down Expand Up @@ -106,12 +106,18 @@
#include "model_interface.h"


%assign CGTypIndices = []

size_t getCGTypeSize(int typeIndex) {

switch (typeIndex) {
%foreach dataTypeIdx = DataTypes.NumDataTypes
%assign dataType = DataTypes.DataType[dataTypeIdx]
%if FEVAL("ismember", dataType.CGTypeIdx, CGTypIndices)
%continue
%endif
case %<dataType.CGTypeIdx>: return %<dataType.Size>; /* %<dataType.Name> */
%assign CGTypIndices = CGTypIndices + dataType.CGTypeIdx
%endforeach
default: return 0; /* unknown type */
}
Expand Down
Loading

0 comments on commit d59271d

Please sign in to comment.