Skip to content

Commit

Permalink
Implement fmi2GetDirectionalDerivative in Cpp runtime
Browse files Browse the repository at this point in the history
Belonging to [master]:
  - OpenModelica/OMCompiler#1954
  • Loading branch information
rfranke authored and OpenModelica-Hudson committed Oct 30, 2017
1 parent 6c0d7cf commit bf1eaeb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 4 deletions.
81 changes: 79 additions & 2 deletions Compiler/Template/CodegenFMUCpp.tpl
Expand Up @@ -187,6 +187,15 @@ case SIMCODE(modelInfo=MODELINFO(__)) then
virtual void setInteger(const unsigned int vr[], size_t nvr, const int value[]);
virtual void setBoolean(const unsigned int vr[], size_t nvr, const int value[]);
virtual void setString(const unsigned int vr[], size_t nvr, const string value[]);
// Jacobian
void getDirectionalDerivative(const unsigned int vrUnknown[], size_t nUnknown,
const unsigned int vrKnown[], size_t nKnown,
const double dvKnown[], double dvUnknown[]);
protected:
static unsigned int _inputRefs[]; ///< Value references of input variables
static unsigned int _outputRefs[]; ///< Value references of output variables
};

/// create instance of <%modelShortName%>FMU
Expand All @@ -198,7 +207,7 @@ template fmuModelCppFile(SimCode simCode,Text& extraFuncs,Text& extraFuncsDecl,T
"Generates code for FMU target."
::=
match simCode
case SIMCODE(modelInfo=MODELINFO(__)) then
case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(inputVars=inputVars, outputVars=outputVars))) then
let modelName = dotPath(modelInfo.name)
let modelShortName = lastIdentOfPath(modelInfo.name)
let modelLongName = System.stringReplace(modelName, ".", "_")
Expand Down Expand Up @@ -274,6 +283,12 @@ case SIMCODE(modelInfo=MODELINFO(__)) then
return new <%modelShortName%>FMU(globalSettings, simObjects);
}

// static model properties
unsigned int <%modelShortName%>FMU::_inputRefs[] = {<%inputVars |> var =>
match var case SIMVAR(name=name) then intSub(getVariableIndex(cref2simvar(name, simCode)), 1) ;separator=", "%>};
unsigned int <%modelShortName%>FMU::_outputRefs[] = {<%outputVars |> var =>
match var case SIMVAR(name=name) then intSub(getVariableIndex(cref2simvar(name, simCode)), 1) ;separator=", "%>};

// constructor
<%modelShortName%>FMU::<%modelShortName%>FMU(IGlobalSettings* globalSettings, shared_ptr<ISimObjects> simObjects)
: <%modelShortName%>Initialize(globalSettings, simObjects) {
Expand All @@ -285,13 +300,17 @@ case SIMCODE(modelInfo=MODELINFO(__)) then
<%modelShortName%>Initialize::initializeMemory();
<%modelShortName%>Initialize::initializeFreeVariables();
<%modelShortName%>Jacobian::initialize();
<%modelShortName%>Jacobian::initializeColoredJacobianA();
}

// getters
<%if isFMIVersion10(FMUVersion) then accessFunctionsFMU1(simCode, "get", modelShortName, modelInfo) else accessFunctionsFMU2(simCode, "get", modelShortName, modelInfo)%>

// setters
<%if isFMIVersion10(FMUVersion) then accessFunctionsFMU1(simCode, "set", modelShortName, modelInfo) else accessFunctionsFMU2(simCode, "set", modelShortName, modelInfo)%>

// Jacobian
<%directionalDerivativeFunction(simCode)%>

>>
// TODO:
// <%setDefaultStartValues(modelInfo)%>
Expand Down Expand Up @@ -635,6 +654,64 @@ match simVar
>>
end accessVecVarFMU2;

template directionalDerivativeFunction(SimCode simCode)
"Generates getDirectionalDerivative."
::=
match simCode
case SIMCODE(modelInfo=MODELINFO(varInfo=VARINFO(numInVars=numInVars, numOutVars=numOutVars))) then
let modelShortName = lastIdentOfPath(modelInfo.name)
<<
void <%modelShortName%>FMU::getDirectionalDerivative(
const unsigned int vrUnknown[], size_t nUnknown,
const unsigned int vrKnown[], size_t nKnown,
const double dvKnown[], double dvUnknown[])
{
<% if CodegenFMUCommon.providesDirectionalDerivative(simCode) then
<<
unsigned int idx, *ref_p, ref_1;
_FMIDERjac_x.clear();
ref_p = NULL;
for (size_t j = 0; j < nKnown; j++) {
idx = vrKnown[j];
if (idx >= _dimContinuousStates) {
// find input reference
if (ref_p == NULL || idx < ref_1)
ref_p = _inputRefs; // reset ref_p if vrKnown decreases
ref_p = std::find(ref_p, _inputRefs + <%numInVars%>, vrKnown[j]);
ref_1 = idx;
idx = _dimContinuousStates + (ref_p - _inputRefs);
}
if (idx >= _FMIDERjac_x.size())
throw std::invalid_argument("getDirectionalDerivative with wrong value reference of known " + omcpp::to_string(vrKnown[j]));
_FMIDERjac_x(idx) = dvKnown[j];
}
calcFMIDERJacobianColumn();
ref_p = NULL;
for (size_t i = 0; i < nUnknown; i++) {
idx = vrUnknown[i] - _dimContinuousStates; // derivatives behind states
if (idx >= _dimContinuousStates) {
// find output reference
if (ref_p == NULL || idx < ref_1)
ref_p = _outputRefs; // reset ref_p if vrUnknown decreases
ref_p = std::find(ref_p, _outputRefs + <%numOutVars%>, vrUnknown[i]);
ref_1 = idx;
idx = _dimContinuousStates + (ref_p - _outputRefs);
}
if (idx >= _FMIDERjac_y.size())
throw std::invalid_argument("getDirectionalDerivative with wrong value reference of unknown " + omcpp::to_string(vrUnknown[i]));
dvUnknown[i] = _FMIDERjac_y(idx);
}
>>
else
<<
throw ModelicaSimulationError(MATH_FUNCTION, "No derivative code, see flag disableDirectionalDerivatives");
>>
%>
}
>>
end directionalDerivativeFunction;

template fmuMakefile(String target, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, String FMUVersion, String additionalLinkerFlags_GCC,
String additionalLinkerFlags_MSVC, String additionalCFlags_GCC, String additionalCFlags_MSVC)
"Generates the contents of the makefile for the simulation case. Copy libexpat & correct linux fmu"
Expand Down
9 changes: 7 additions & 2 deletions SimulationRuntime/cpp/Include/FMU2/FMU2Interface.cpp
Expand Up @@ -406,8 +406,13 @@ extern "C"
fmi2Real dvUnknown[])
{
FMU2Wrapper *w = reinterpret_cast<FMU2Wrapper*>(c);
LOG_CALL(w, "fmi2GetDirectionalDerivative not implemented");
return fmi2Error;
LOG_CALL(w, "fmi2GetDirectionalDerivative(nUnknown = %d, nKnown = %d)", nUnknown, nKnown);
try {
return w->getDirectionalDerivative(vUnknown_ref, nUnknown,
vKnown_ref, nKnown, dvKnown,
dvUnknown);
}
CATCH_EXCEPTION(w);
}

// ---------------------------------------------------------------------------
Expand Down
15 changes: 15 additions & 0 deletions SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.cpp
Expand Up @@ -477,4 +477,19 @@ fmi2Status FMU2Wrapper::getNominalsOfContinuousStates(fmi2Real x_nominal[], size
return fmi2OK;
}

fmi2Status FMU2Wrapper::getDirectionalDerivative(const fmi2ValueReference vrUnknown[],
size_t nUnknown,
const fmi2ValueReference vrKnown[],
size_t nKnown,
const fmi2Real dvKnown[],
fmi2Real dvUnknown[])
{
if (_need_update)
updateModel();
_model->getDirectionalDerivative(vrUnknown, nUnknown,
vrKnown, nKnown, dvKnown,
dvUnknown);
return fmi2OK;
}

/** @} */ // end of fmu2
8 changes: 8 additions & 0 deletions SimulationRuntime/cpp/Include/FMU2/FMU2Wrapper.h
Expand Up @@ -162,6 +162,14 @@ class FMU2Wrapper
virtual fmi2Status getContinuousStates(fmi2Real states[], size_t nx);
virtual fmi2Status getNominalsOfContinuousStates(fmi2Real x_nominal[], size_t nx);

// Jacobian
fmi2Status getDirectionalDerivative(const fmi2ValueReference vrUnknown[],
size_t nUnknown,
const fmi2ValueReference vrKnown[],
size_t nKnown,
const fmi2Real dvKnown[],
fmi2Real dvUnknown[]);

private:
FMU2GlobalSettings _global_settings;
Logger *_logger;
Expand Down

0 comments on commit bf1eaeb

Please sign in to comment.