Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 008d2d2

Browse files
Willi BraunOpenModelica-Hudson
authored andcommitted
[FMI] fix directional derivatives in c fmu
- fixes ticket:4977 Belonging to [master]: - #2560
1 parent 2d1ed04 commit 008d2d2

File tree

2 files changed

+69
-20
lines changed

2 files changed

+69
-20
lines changed

Compiler/Template/CodegenFMU.tpl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ case SIMCODE(__) then
246246
fmi2String getString(ModelInstance* comp, const fmi2ValueReference vr);
247247
fmi2Status setString(ModelInstance* comp, const fmi2ValueReference vr, fmi2String value);
248248
fmi2Status setExternalFunction(ModelInstance* c, const fmi2ValueReference vr, const void* value);
249+
fmi2ValueReference mapInputReference2InputNumber(const fmi2ValueReference vr);
250+
fmi2ValueReference mapOutputReference2OutputNumber(const fmi2ValueReference vr);
249251
>>
250252
else
251253
<<
@@ -293,6 +295,7 @@ case SIMCODE(__) then
293295
<%getStringFunction2(simCode, modelInfo)%>
294296
<%setStringFunction2(simCode, modelInfo)%>
295297
<%setExternalFunction2(modelInfo)%>
298+
<%mapInputAndOutputs(simCode)%>
296299
>>
297300
else
298301
<<
@@ -1105,6 +1108,34 @@ match simVar
11051108
end match
11061109
end SwitchAliasVarsSet;
11071110

1111+
template mapInputAndOutputs(SimCode simCode)
1112+
""
1113+
::=
1114+
match simCode
1115+
case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(inputVars=inputVars, outputVars=outputVars))) then
1116+
<<
1117+
/* function maps input references to a input index used in partialDerivatives */
1118+
fmi2ValueReference mapInputReference2InputNumber(const fmi2ValueReference vr) {
1119+
switch (vr) {
1120+
<%inputVars |> var hasindex index0 => match var case SIMVAR(name=name, type_=T_REAL()) then
1121+
'case <%lookupVR(name, simCode)%>: return <%index0%>; break;' ;separator="\n"%>
1122+
default:
1123+
return -1;
1124+
}
1125+
}
1126+
/* function maps output references to a input index used in partialDerivatives */
1127+
fmi2ValueReference mapOutputReference2OutputNumber(const fmi2ValueReference vr) {
1128+
switch (vr) {
1129+
<%outputVars |> var hasindex index0 => match var case SIMVAR(name=name, type_=T_REAL()) then
1130+
'case <%lookupVR(name, simCode)%>: return <%index0%>; break;' ;separator="\n"%>
1131+
default:
1132+
return -1;
1133+
}
1134+
}
1135+
>>
1136+
end match
1137+
end mapInputAndOutputs;
1138+
11081139

11091140
template getPlatformString2(String modelNamePrefix, String platform, String fileNamePrefix, String fmuTargetName, String dirExtra, String libsPos1, String libsPos2, String omhome, String FMUVersion)
11101141
"returns compilation commands for the platform. "

SimulationRuntime/fmi/export/fmi2/fmu2_model_interface.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -483,13 +483,13 @@ fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2Str
483483
#endif
484484

485485
/* allocate memory for Jacobian */
486+
comp->_has_jacobian = 0;
487+
comp->fmiDerJac = NULL;
486488
if (comp->fmuData->callback->initialPartialFMIDER != NULL){
487-
comp->_has_jacobian = 1;
488-
comp->fmiDerJac = &(comp->fmuData->simulationInfo->analyticJacobians[comp->fmuData->callback->INDEX_JAC_FMIDER]);
489-
}
490-
else{
491-
comp->_has_jacobian = 0;
492-
comp->fmiDerJac = NULL;
489+
if (! comp->fmuData->callback->initialPartialFMIDER(comp->fmuData, comp->threadData)) {
490+
comp->_has_jacobian = 1;
491+
comp->fmiDerJac = &(comp->fmuData->simulationInfo->analyticJacobians[comp->fmuData->callback->INDEX_JAC_FMIDER]);
492+
}
493493
}
494494

495495
FILTERED_LOG(comp, fmi2OK, LOG_FMI2_CALL, "fmi2Instantiate: GUID=%s", fmuGUID)
@@ -960,7 +960,9 @@ fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedSta
960960
return unsupportedFunction(c, "fmi2DeSerializeFMUstate", modelInstantiated|modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
961961
}
962962

963-
fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, const fmi2ValueReference vKnown_ref[] , size_t nKnown,
963+
fmi2Status fmi2GetDirectionalDerivative(fmi2Component c,
964+
const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
965+
const fmi2ValueReference vKnown_ref[] , size_t nKnown,
964966
const fmi2Real dvKnown[], fmi2Real dvUnknown[])
965967
{
966968
ModelInstance *comp = (ModelInstance *)c;
@@ -980,20 +982,27 @@ fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReferenc
980982
if (!comp->_has_jacobian)
981983
return unsupportedFunction(c, "fmi2GetDirectionalDerivative", modelInitializationMode|modelEventMode|modelContinuousTimeMode|modelTerminated|modelError);
982984
/***************************************/
983-
// This code assumes that the FMU variables are always sorted,
984-
// states first and then derivatives.
985-
// This is true for the actual OMC FMUs.
986-
987-
/* TODO: Use the literal names instead of the data-> structure
988-
* Beware! This code assumes that the FMI variables are sorted putting
989-
* states first (0 to nStates-1) and state derivatives (nStates to 2*nStates-1) second. */
985+
/* This code assumes that the FMU variables are always sorted,
986+
states first and then derivatives.
987+
This is true for the actual OMC FMUs.
988+
The input values references are mapped with mapInputReference2InputNumber
989+
and mapOutputReference2OutputNumber functions
990+
*/
991+
/* clear out the seeds */
990992
for (i=0;i<independent; i++) {
991-
// Clear out the seeds
992993
comp->fmiDerJac->seedVars[i]=0;
993994
}
994-
for (i=0;i<nUnknown; i++) {
995+
for (i=0;i<nKnown; i++) {
996+
int idx = vKnown_ref[i];
997+
/* if idx is > nStates it's an input so we need a mapping */
998+
if (idx >= modelData->nStates){
999+
idx = mapInputReference2InputNumber(vKnown_ref[i]);
1000+
idx = modelData->nStates + idx;
1001+
}
1002+
if (vrOutOfRange(comp, "fmi2GetDirectionalDerivative input index", idx, independent))
1003+
return fmi2Error;
9951004
/* Put the supplied value in the seeds */
996-
comp->fmiDerJac->seedVars[vUnknown_ref[i]]=dvKnown[i];
1005+
comp->fmiDerJac->seedVars[idx]=dvKnown[i];
9971006
}
9981007
/* Call the Jacobian evaluation function. This function evaluates the whole column of the Jacobian.
9991008
* More efficient code could only evaluate the equations needed for the
@@ -1002,9 +1011,18 @@ fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReferenc
10021011
fmudata->callback->functionJacFMIDER_column(fmudata, td);
10031012
resetThreadData(comp);
10041013

1005-
// Write the results back to the array
1006-
for (i=0;i<nKnown; i++) {
1007-
dvUnknown[vKnown_ref[i]-dependent] = comp->fmiDerJac->resultVars[vKnown_ref[i]-dependent];
1014+
/* Write the results to dvUnknown array */
1015+
for (i=0;i<nUnknown; i++) {
1016+
/* derivatives are behind the states */
1017+
int idx = vUnknown_ref[i] - modelData->nStates;
1018+
/* if idx is > nStates it's an output so we need a mapping */
1019+
if (idx >= modelData->nStates){
1020+
idx = mapOutputReference2OutputNumber(vUnknown_ref[i]);
1021+
idx = modelData->nStates + idx;
1022+
}
1023+
if (vrOutOfRange(comp, "fmi2GetDirectionalDerivative output index", idx, dependent))
1024+
return fmi2Error;
1025+
dvUnknown[i] = comp->fmiDerJac->resultVars[idx];
10081026
}
10091027
/***************************************/
10101028
return fmi2OK;

0 commit comments

Comments
 (0)