Skip to content

Commit

Permalink
bugfixes for FMI:
Browse files Browse the repository at this point in the history
  - added *_info.xml and *_init.xml to resoursses
    - therefore added default simulation options to translateFMU in CevalScript.mo

  - added support for dynamic state selection
    - added an event triggering equation to FMI import
    - added an addional flag to function stateSelect to be able switch states only in eventUpdate
 
  - added support for sample operator in FMU-import/-export
  - added some tests to testsuite



git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@15930 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
Willi Braun committed Apr 29, 2013
1 parent 1927fb6 commit 32c80fc
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 86 deletions.
5 changes: 3 additions & 2 deletions Compiler/Script/CevalScript.mo
Expand Up @@ -1171,10 +1171,11 @@ algorithm
then
(cache,ret_val,st_1);*/

case (cache,env,"translateModelFMU",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_)
case (cache,env,"translateModelFMU", vals as {Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_)
equation
filenameprefix = Util.stringReplaceChar(filenameprefix,".","_");
(cache,ret_val,st_1) = translateModelFMU(cache, env, className, st, filenameprefix, true, NONE());
simSettings = convertSimulationOptionsToSimCode(defaultSimulationOptions);
(cache,ret_val,st_1) = translateModelFMU(cache, env, className, st, filenameprefix, true, SOME(simSettings));
then
(cache,ret_val,st_1);

Expand Down
23 changes: 21 additions & 2 deletions Compiler/Template/CodegenFMU.tpl
Expand Up @@ -63,6 +63,7 @@ case SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
let()= textFile(recordsFile(fileNamePrefix, recordDecls), '<%fileNamePrefix%>_records.c')
let()= textFile(simulationHeaderFile(simCode,guid), '<%fileNamePrefix%>_model.h')
let()= textFile(simulationFile(simCode,guid), '<%fileNamePrefix%>.c')
let()= textFile(simulationInitFile(simCode,guid), '<%fileNamePrefix%>_init.xml')
let()= textFile(fmumodel_identifierFile(simCode,guid), '<%fileNamePrefix%>_FMU.c')
let()= textFile(fmuModelDescriptionFile(simCode,guid), 'modelDescription.xml')
let()= textFile(fmudeffile(simCode), '<%fileNamePrefix%>.def')
Expand Down Expand Up @@ -991,6 +992,8 @@ match platform
<%\t%> cp <%fileNamePrefix%>.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>.c
<%\t%> cp <%fileNamePrefix%>_model.h <%fileNamePrefix%>/sources/<%fileNamePrefix%>_model.h
<%\t%> cp <%fileNamePrefix%>_FMU.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>_FMU.c
<%\t%> cp <%fileNamePrefix%>_info.xml <%fileNamePrefix%>/sources/<%fileNamePrefix%>_info.xml
<%\t%> cp <%fileNamePrefix%>_init.xml <%fileNamePrefix%>/sources/<%fileNamePrefix%>_init.xml
<%\t%> cp <%fileNamePrefix%>_functions.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>_functions.c
<%\t%> cp <%fileNamePrefix%>_functions.h <%fileNamePrefix%>/sources/<%fileNamePrefix%>_functions.h
<%\t%> cp <%fileNamePrefix%>_records.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>_records.c
Expand Down Expand Up @@ -1023,6 +1026,8 @@ match platform
<%\t%> cp <%fileNamePrefix%>_FMU.libs <%fileNamePrefix%>/binaries/<%platform%>/
<%\t%> cp <%fileNamePrefix%>.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>.c
<%\t%> cp <%fileNamePrefix%>_model.h <%fileNamePrefix%>/sources/<%fileNamePrefix%>_model.h
<%\t%> cp <%fileNamePrefix%>_info.xml <%fileNamePrefix%>/sources/<%fileNamePrefix%>_info.xml
<%\t%> cp <%fileNamePrefix%>_init.xml <%fileNamePrefix%>/sources/<%fileNamePrefix%>_init.xml
<%\t%> cp <%fileNamePrefix%>_FMU.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>_FMU.c
<%\t%> cp <%fileNamePrefix%>_functions.c <%fileNamePrefix%>/sources/<%fileNamePrefix%>_functions.c
<%\t%> cp <%fileNamePrefix%>_functions.h <%fileNamePrefix%>/sources/<%fileNamePrefix%>_functions.h
Expand Down Expand Up @@ -1100,6 +1105,8 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
copy <%fileNamePrefix%>.c <%fileNamePrefix%>\sources\<%fileNamePrefix%>.c
copy <%fileNamePrefix%>_model.h <%fileNamePrefix%>\sources\<%fileNamePrefix%>_model.h
copy <%fileNamePrefix%>_FMU.c <%fileNamePrefix%>\sources\<%fileNamePrefix%>_FMU.c
copy <%fileNamePrefix%>_info.xml <%fileNamePrefix%>\sources\<%fileNamePrefix%>_info.xml
copy <%fileNamePrefix%>_init.xml <%fileNamePrefix%>\sources\<%fileNamePrefix%>_init.xml
copy <%fileNamePrefix%>_functions.c <%fileNamePrefix%>\sources\<%fileNamePrefix%>_functions.c
copy <%fileNamePrefix%>_functions.h <%fileNamePrefix%>\sources\<%fileNamePrefix%>_functions.h
copy <%fileNamePrefix%>_records.c <%fileNamePrefix%>\sources\<%fileNamePrefix%>_records.c
Expand Down Expand Up @@ -1274,6 +1281,8 @@ case FMIIMPORT(fmiInfo=INFO(__),fmiExperimentAnnotation=EXPERIMENTANNOTATION(__)
constant Boolean intermediateResults = false;
Boolean newStatesAvailable;
Integer fmi_status;
Real triggerDSSEvent;
Real nextEventTime;
initial algorithm
flowInstantiate := fmiFunctions.fmi1InstantiateModel(fmi, "<%fmiInfo.fmiModelIdentifier%>", debugLogging);
flowParamsStart := 0;
Expand All @@ -1296,18 +1305,20 @@ case FMIIMPORT(fmiInfo=INFO(__),fmiExperimentAnnotation=EXPERIMENTANNOTATION(__)
fmi_z_positive[i] = if not terminal() then fmi_z[i] > 0 else pre(fmi_z_positive[i]);
end for;
callEventUpdate = fmiFunctions.fmi1CompletedIntegratorStep(fmi, flowStatesInputs);
triggerDSSEvent = noEvent(if callEventUpdate then flowStatesInputs+1.0 else flowStatesInputs-1.0);
nextEventTime = fmiFunctions.fmi1nextEventTime(fmi, eventInfo, flowStatesInputs);
<%if not boolAnd(stringEq(realVariablesNames, ""), stringEq(realVariablesValueReferences, "")) then "{"+dumpRealVariablesName(fmiModelVariablesList)+"} = fmiFunctions.fmi1GetReal(fmi, {"+dumpRealVariablesVR(fmiModelVariablesList)+"}, flowStatesInputs);"%>
<%if not boolAnd(stringEq(integerVariablesNames, ""), stringEq(integerVariablesValueReferences, "")) then "{"+dumpIntegerVariablesName(fmiModelVariablesList)+"} = fmiFunctions.fmi1GetInteger(fmi, {"+dumpIntegerVariablesVR(fmiModelVariablesList)+"}, flowStatesInputs);"%>
<%if not boolAnd(stringEq(booleanVariablesNames, ""), stringEq(booleanVariablesValueReferences, "")) then "{"+dumpBooleanVariablesName(fmiModelVariablesList)+"} = fmiFunctions.fmi1GetBoolean(fmi, {"+dumpBooleanVariablesVR(fmiModelVariablesList)+"}, flowStatesInputs);"%>
<%if not boolAnd(stringEq(stringVariablesNames, ""), stringEq(stringVariablesValueReferences, "")) then "{"+dumpStringVariablesName(fmiModelVariablesList)+"} = fmiFunctions.fmi1GetString(fmi, {"+dumpStringVariablesVR(fmiModelVariablesList)+"}, flowStatesInputs);"%>
algorithm
<%if intGt(listLength(fmiInfo.fmiNumberOfEventIndicators), 0) then
<<
when (<%fmiInfo.fmiNumberOfEventIndicators |> eventIndicator => "change(fmi_z_positive["+eventIndicator+"])" ;separator=" or "%>) and not initial() then
when {(<%fmiInfo.fmiNumberOfEventIndicators |> eventIndicator => "change(fmi_z_positive["+eventIndicator+"])" ;separator=" or "%>) and not initial(),triggerDSSEvent > flowStatesInputs, nextEventTime < time} then
>>
else
<<
when not initial() then
when {not initial(), triggerDSSEvent > flowStatesInputs, nextEventTime < time} then
>>
%>
(newStatesAvailable) := fmiFunctions.fmi1EventUpdate(fmi, intermediateResults, eventInfo, flowStatesInputs);
Expand Down Expand Up @@ -1419,6 +1430,14 @@ case FMIIMPORT(fmiInfo=INFO(__),fmiExperimentAnnotation=EXPERIMENTANNOTATION(__)
external "C" outNewStatesAvailable = fmi1EventUpdate_OMC(fmi, intermediateResults, inEventInfo, inFlowStates) annotation(Library = {"OpenModelicaFMIRuntimeC", "fmilib"<%if stringEq(platform, "win32") then ", \"shlwapi\""%>});
end fmi1EventUpdate;

function fmi1nextEventTime
input fmi1ImportInstance fmi;
input fmi1EventInfo inEventInfo;
input Real inFlowStates;
output Real outNewnextTime;
external "C" outNewnextTime = fmi1nextEventTime_OMC(fmi, inEventInfo, inFlowStates) annotation(Library = {"OpenModelicaFMIRuntimeC", "fmilib"<%if stringEq(platform, "win32") then ", \"shlwapi\""%>});
end fmi1nextEventTime;

function fmi1CompletedIntegratorStep
input fmi1ImportInstance fmi;
input Real inFlowStates;
Expand Down
11 changes: 11 additions & 0 deletions SimulationRuntime/c/fmi/FMI1ModelExchange.c
Expand Up @@ -131,6 +131,17 @@ int fmi1EventUpdate_OMC(void* fmi, int intermediateResults, void* eventInfo, dou
return e->stateValuesChanged;
}

/*
* Wrapper for the FMI function fmiEventUpdate.
* parameter flowStates is dummy and is only used to run the equations in sequence.
* Returns FMI EventInfo nextEventTime
*/
double fmi1nextEventTime_OMC(void* fmi, void* eventInfo, double flowStates)
{
fmi1_event_info_t* e = (fmi1_event_info_t*)eventInfo;
return e->nextEventTime;
}

/*
* Wrapper for the FMI function fmiCompletedIntegratorStep.
*/
Expand Down
4 changes: 2 additions & 2 deletions SimulationRuntime/c/simulation/simulation_input_xml.cpp
Expand Up @@ -207,8 +207,7 @@ static void XMLCALL endElement(void *userData, const char *name)
* The textfile should be given as argument to the main function using
* the -f file flag.
*/
void read_input_xml(int argc, char **argv,
MODEL_DATA* modelData,
void read_input_xml(MODEL_DATA* modelData,
SIMULATION_INFO* simulationInfo)
{
omc_ModelInput mi;
Expand Down Expand Up @@ -1327,3 +1326,4 @@ void doOverride(omc_ModelInput& mi, MODEL_DATA* modelData, const char* override,
INFO(LOG_SOLVER, "NO override given on the command line.");
}
}

13 changes: 11 additions & 2 deletions SimulationRuntime/c/simulation/simulation_input_xml.h
Expand Up @@ -41,7 +41,16 @@

#include "simulation_runtime.h"

void read_input_xml(int argc, char **argv,
MODEL_DATA* modelData,
#ifdef __cplusplus
extern "C" {
#endif

void read_input_xml(MODEL_DATA* modelData,
SIMULATION_INFO* simulationData);

#ifdef __cplusplus
}
#endif


#endif
2 changes: 1 addition & 1 deletion SimulationRuntime/c/simulation/simulation_runtime.cpp
Expand Up @@ -818,7 +818,7 @@ int initRuntimeAndSimulation(int argc, char**argv, DATA *data)
data->simulationInfo.lsMethod = getlinearSolverMethod(argc, argv);

function_initMemoryState();
read_input_xml(argc, argv, &(data->modelData), &(data->simulationInfo));
read_input_xml(&(data->modelData), &(data->simulationInfo));
initializeOutputFilter(&(data->modelData), data->simulationInfo.variableFilter);

/* allocate memory for mixed system solvers */
Expand Down
Expand Up @@ -677,21 +677,21 @@ static int symbolic_initialization(DATA *data)
overwriteOldSimulationData(data);

/* do pivoting for dynamic state selection */
stateSelection(data,0);
stateSelection(data, 0, 1);
functionInitialEquations(data);

/* update saved value for
hysteresis relations */
updateHysteresis(data);

/* do pivoting for dynamic state selection if selection changed try again an */
if(stateSelection(data,1) == 1)
if(stateSelection(data, 1, 1) == 1)
{
functionInitialEquations(data);
updateHysteresis(data);

/* report a warning about strange start values */
if(stateSelection(data,1) == 1)
if(stateSelection(data, 1, 1) == 1)
WARNING(LOG_STDOUT, "Cannot initialize unique the dynamic state selection. Use -lv LOG_DSS to see the switching state set.");
}

Expand Down
5 changes: 4 additions & 1 deletion SimulationRuntime/c/simulation/solver/model_help.c
Expand Up @@ -634,8 +634,11 @@ void updateHysteresis(DATA* data){
*/
double getNextSampleTimeFMU(DATA *data)
{
if(0 < data->modelData.nSamples)
if(0 < data->modelData.nSamples){
INFO1(LOG_EVENTS, "Next event time = %f", data->simulationInfo.nextSampleEvent);
return data->simulationInfo.nextSampleEvent;
}


return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion SimulationRuntime/c/simulation/solver/solver_main.c
Expand Up @@ -538,7 +538,7 @@ if(omp_get_thread_num() == 0)
/***** End event handling *****/

/***** check state selection *****/
if(stateSelection(data, 1))
if(stateSelection(data, 1, 1))
{
/* if new set is calculated reinit the solver */
solverInfo->didEventStep = 1;
Expand Down
39 changes: 27 additions & 12 deletions SimulationRuntime/c/simulation/solver/stateset.c
Expand Up @@ -146,12 +146,14 @@ static void getAnalyticalJacobianSet(DATA* data, unsigned int index)
if(data->simulationInfo.analyticJacobians[jacIndex].sparsePattern.colorCols[ii]-1 == i)
data->simulationInfo.analyticJacobians[jacIndex].seedVars[ii] = 1;

/*
if(ACTIVE_STREAM(LOG_DSS_JAC))
{
INFO(LOG_DSS_JAC, "Caluculate one col:");
for(l=0; l < data->simulationInfo.analyticJacobians[jacIndex].sizeCols; l++)
INFO2(LOG_DSS_JAC, "seed: data->simulationInfo.analyticJacobians[index].seedVars[%d]= %f", l, data->simulationInfo.analyticJacobians[jacIndex].seedVars[l]);
}
*/

(data->simulationInfo.stateSetData[index].analyticalJacobianColumn)(data);

Expand All @@ -164,14 +166,14 @@ static void getAnalyticalJacobianSet(DATA* data, unsigned int index)
else
ii = data->simulationInfo.analyticJacobians[jacIndex].sparsePattern.leadindex[j-1];

INFO2(LOG_DSS_JAC, "take for %d -> %d\n", j, ii);
/* INFO2(LOG_DSS_JAC, "take for %d -> %d\n", j, ii); */

while(ii < data->simulationInfo.analyticJacobians[jacIndex].sparsePattern.leadindex[j])
{
l = data->simulationInfo.analyticJacobians[jacIndex].sparsePattern.index[ii];
k = j*data->simulationInfo.analyticJacobians[jacIndex].sizeRows + l;
jac[k] = data->simulationInfo.analyticJacobians[jacIndex].resultVars[l];
INFO7(LOG_DSS_JAC, "write %d. in jac[%d]-[%d, %d]=%f from col[%d]=%f", ii, k, l, j, jac[k], l, data->simulationInfo.analyticJacobians[jacIndex].resultVars[l]);
/* INFO7(LOG_DSS_JAC, "write %d. in jac[%d]-[%d, %d]=%f from col[%d]=%f", ii, k, l, j, jac[k], l, data->simulationInfo.analyticJacobians[jacIndex].resultVars[l]); */
ii++;
};
}
Expand All @@ -181,21 +183,23 @@ static void getAnalyticalJacobianSet(DATA* data, unsigned int index)
data->simulationInfo.analyticJacobians[jacIndex].seedVars[ii] = 0;
}

/*
if(ACTIVE_STREAM(LOG_DSS))
{
char buffer[4096];
DEBUG3(LOG_DSS, "jacobian %dx%d [id: %d]", data->simulationInfo.analyticJacobians[jacIndex].sizeRows, data->simulationInfo.analyticJacobians[jacIndex].sizeCols, jacIndex);
INFO3(LOG_DSS, "jacobian %dx%d [id: %d]", data->simulationInfo.analyticJacobians[jacIndex].sizeRows, data->simulationInfo.analyticJacobians[jacIndex].sizeCols, jacIndex);
INDENT(LOG_DSS);
for(i=0; i<data->simulationInfo.analyticJacobians[jacIndex].sizeRows; i++)
{
buffer[0] = 0;
for(j=0; j < data->simulationInfo.analyticJacobians[jacIndex].sizeCols; j++)
sprintf(buffer, "%s%.5e ", buffer, jac[i*data->simulationInfo.analyticJacobians[jacIndex].sizeCols+j]);
DEBUG1(LOG_DSS, "%s", buffer);
INFO1(LOG_DSS, "%s", buffer);
}
RELEASE(LOG_DSS);
}
*/
}

/*! \fn setAMatrix
Expand Down Expand Up @@ -255,7 +259,7 @@ static void setAMatrix(modelica_integer* newEnable, modelica_integer nCandidates
*
* \author ???
*/
static int comparePivot(modelica_integer *oldPivot, modelica_integer *newPivot, modelica_integer nCandidates, modelica_integer nDummyStates, modelica_integer nStates, VAR_INFO* A, VAR_INFO** states, VAR_INFO** statecandidates, DATA *data)
static int comparePivot(modelica_integer *oldPivot, modelica_integer *newPivot, modelica_integer nCandidates, modelica_integer nDummyStates, modelica_integer nStates, VAR_INFO* A, VAR_INFO** states, VAR_INFO** statecandidates, DATA *data, int switchStates)
{
modelica_integer i;
int ret = 0;
Expand All @@ -267,16 +271,18 @@ static int comparePivot(modelica_integer *oldPivot, modelica_integer *newPivot,
modelica_integer entry = (i < nDummyStates) ? 1: 2;
newEnable[ newPivot[i] ] = entry;
oldEnable[ oldPivot[i] ] = entry;
}
}

for (i=0; i<nCandidates; i++)
{
if(newEnable[i] != oldEnable[i])
{
INFO1(LOG_DSS, "select new states at time %f", data->localData[0]->timeValue);
INDENT(LOG_DSS);
setAMatrix(newEnable, nCandidates, nStates, A, states, statecandidates, data);
RELEASE(LOG_DSS);
if (switchStates){
INFO1(LOG_DSS, "select new states at time %f", data->localData[0]->timeValue);
INDENT(LOG_DSS);
setAMatrix(newEnable, nCandidates, nStates, A, states, statecandidates, data);
RELEASE(LOG_DSS);
}
ret = -1;
break;
}
Expand All @@ -293,11 +299,13 @@ static int comparePivot(modelica_integer *oldPivot, modelica_integer *newPivot,
* function to select the actual states
*
* \param [ref] [data]
* \param [char] [reportError]
* \param [int] [switchStates] flag for switch states, function does switch only if this switchStates = 1
* \return ???
*
* \author Frenkel TUD
*/
int stateSelection(DATA *data, char reportError)
int stateSelection(DATA *data, char reportError, int switchStates)
{
long i=0;
long j=0;
Expand All @@ -309,10 +317,12 @@ int stateSelection(DATA *data, char reportError)
int res=0;
STATE_SET_DATA *set = &(data->simulationInfo.stateSetData[i]);
modelica_integer* oldColPivot = (modelica_integer*) malloc(set->nCandidates * sizeof(modelica_integer));
modelica_integer* oldRowPivot = (modelica_integer*) malloc(set->nCandidates * sizeof(modelica_integer));
/* generate jacobian, stored in set->J */
getAnalyticalJacobianSet(data, i);
/* call pivoting function to select the states */
memcpy(oldColPivot, set->colPivot, set->nCandidates*sizeof(modelica_integer));
memcpy(oldRowPivot, set->rowPivot, set->nCandidates*sizeof(modelica_integer));
if((pivot(set->J, set->nDummyStates, set->nCandidates, set->rowPivot, set->colPivot) != 0) && reportError)
{
/* error, report the matrix and the time */
Expand All @@ -336,11 +346,16 @@ int stateSelection(DATA *data, char reportError)
}
/* if we have a new set throw event for reinitialization
and set the A matrix for set.x=A*(states) */
res = comparePivot(oldColPivot, set->colPivot, set->nCandidates, set->nDummyStates, set->nStates, set->A, set->states, set->statescandidates, data);
res = comparePivot(oldColPivot, set->colPivot, set->nCandidates, set->nDummyStates, set->nStates, set->A, set->states, set->statescandidates, data, switchStates);
if (!switchStates){
memcpy(set->colPivot, oldColPivot, set->nCandidates*sizeof(modelica_integer));
memcpy(set->rowPivot, oldRowPivot, set->nCandidates*sizeof(modelica_integer));
}
if(res)
globalres = 1;

free(oldColPivot);
free(oldRowPivot);
}
return globalres;
}
2 changes: 1 addition & 1 deletion SimulationRuntime/c/simulation/solver/stateset.h
Expand Up @@ -44,7 +44,7 @@ void initializeStateSetPivoting(DATA *data);
void freeStateSetData(DATA *data);

/* update the state selection */
int stateSelection(DATA *data, char reportError);
int stateSelection(DATA *data, char reportError, int switchStates);

/* do pivoting */
extern int pivot(double *A, modelica_integer n_rows, modelica_integer n_cols, modelica_integer *rowInd, modelica_integer *colInd);
Expand Down

0 comments on commit 32c80fc

Please sign in to comment.