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

Commit c2feb3f

Browse files
Willi BraunOpenModelica-Hudson
authored andcommitted
[DAEmode] improve event handling and discrete loops
Belonging to [master]: - #2291 - OpenModelica/OpenModelica-testsuite#884
1 parent 90be434 commit c2feb3f

File tree

4 files changed

+113
-42
lines changed

4 files changed

+113
-42
lines changed

Compiler/BackEnd/DAEMode.mo

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import BackendDAE;
4646
protected
4747

4848
import Absyn;
49+
import Array;
4950
import BackendDAEOptimize;
5051
import BackendDAEUtil;
5152
import BackendDAEFunc;
@@ -67,6 +68,7 @@ import Flags;
6768
import Global;
6869
import Initialization;
6970
import List;
71+
import Matching;
7072
import StackOverflow;
7173
import Util;
7274

@@ -196,6 +198,7 @@ uniontype TraverseEqnAryFold
196198
BackendDAE.Variables systemVars;
197199
DAE.FunctionTree functionTree;
198200
Boolean recursiveStrongComponentRun;
201+
BackendDAE.Shared shared;
199202
end TRAVERSER_CREATE_DAE;
200203
end TraverseEqnAryFold;
201204

@@ -221,7 +224,7 @@ algorithm
221224
systemSize := BackendDAEUtil.systemSize(syst);
222225
newDAEVars := BackendVariable.emptyVars();
223226
newDAEEquations := BackendEquation.emptyEqnsSized(systemSize);
224-
travArgs := TRAVERSER_CREATE_DAE(globalDAEData, newDAEVars, newDAEEquations, syst.orderedVars, shared.functionTree, false);
227+
travArgs := TRAVERSER_CREATE_DAE(globalDAEData, newDAEVars, newDAEEquations, syst.orderedVars, shared.functionTree, false, shared);
225228
if debug then BackendDump.printEqSystem(syst); end if;
226229
// for every equation create corresponding residiual variable(s)
227230
travArgs := BackendDAEUtil.traverseEqSystemStrongComponents(syst, traverserStrongComponents, travArgs);
@@ -269,8 +272,11 @@ algorithm
269272
(traverserArgs) :=
270273
matchcontinue(inEqns, traverserArgs.recursiveStrongComponentRun, isStateVarInvoled)
271274
local
275+
BackendDAE.EqSystem syst;
276+
BackendDAE.IncidenceMatrix adjMatrix;
277+
272278
list<BackendDAE.Equation> newResEqns;
273-
list<BackendDAE.Var> newResVars, newAuxVars;
279+
list<BackendDAE.Var> newResVars, newAuxVars, discVars, contVars;
274280
BackendDAE.Var var;
275281
BackendDAE.Variables systemVars;
276282
BackendDAE.Var dummyVar;
@@ -282,6 +288,8 @@ algorithm
282288
DAE.FunctionTree funcsTree;
283289
list<DAE.ComponentRef> crlst;
284290
Boolean b1, b2;
291+
list<BackendDAE.Equation> discEqns;
292+
list<BackendDAE.Equation> contEqns;
285293

286294
DAE.Algorithm alg;
287295
DAE.ElementSource source;
@@ -482,14 +490,26 @@ algorithm
482490

483491
case(_, false, _)
484492
algorithm
485-
vars := inVars;
486-
for e in inEqns loop
493+
494+
(discVars, contVars) := List.splitOnTrue(inVars, BackendVariable.isVarDiscrete);
495+
(discEqns, contEqns) := getDiscAndContEqns(inVars, inEqns, discVars, contVars, traverserArgs.shared.functionTree);
496+
497+
// create discrete
498+
for e in discEqns loop
499+
size := BackendEquation.equationSize(e);
500+
newAuxVars := List.firstN(discVars, size);
501+
traverserArgs := traverserStrongComponents({e}, newAuxVars, {}, {}, traverserArgs);
502+
discVars := List.stripN(discVars, size);
503+
end for;
504+
505+
// create continuous
506+
for e in contEqns loop
487507
size := BackendEquation.equationSize(e);
488-
newAuxVars := List.firstN(vars, size);
508+
newAuxVars := List.firstN(contVars, size);
489509
traverserArgs.recursiveStrongComponentRun := true;
490510
traverserArgs := traverserStrongComponents({e}, newAuxVars, {}, {}, traverserArgs);
491511
traverserArgs.recursiveStrongComponentRun := false;
492-
vars := List.stripN(vars, size);
512+
contVars := List.stripN(contVars, size);
493513
end for;
494514
then
495515
(traverserArgs);
@@ -504,6 +524,54 @@ algorithm
504524
end matchcontinue;
505525
end traverserStrongComponents;
506526

527+
function getDiscAndContEqns
528+
input list<BackendDAE.Var> inAllVars;
529+
input list<BackendDAE.Equation> inAllEqns;
530+
input list<BackendDAE.Var> inDiscVars;
531+
input list<BackendDAE.Var> inContVars;
532+
input DAE.FunctionTree functionTree;
533+
output list<BackendDAE.Equation> discEqns;
534+
output list<BackendDAE.Equation> contEqns;
535+
protected
536+
BackendDAE.EqSystem syst;
537+
BackendDAE.IncidenceMatrix adjMatrix;
538+
539+
list<Integer> varsIndex, eqnIndex;
540+
array<Integer> assignVarEqn "eqn := assignVarEqn[var]";
541+
array<Integer> assignEqnVar "var := assignEqnVar[eqn]";
542+
543+
array<Integer> mapEqnScalarArray;
544+
constant Boolean debug = false;
545+
algorithm
546+
try
547+
// create syst for a matching
548+
syst := BackendDAEUtil.createEqSystem(BackendVariable.listVar1(inAllVars), BackendEquation.listEquation(inAllEqns) );
549+
if debug then BackendDump.printEqSystem(syst); end if;
550+
(adjMatrix, _, _, mapEqnScalarArray) := BackendDAEUtil.incidenceMatrixScalar(syst, BackendDAE.NORMAL(), SOME(functionTree));
551+
if debug then BackendDump.dumpIncidenceMatrix(adjMatrix); end if;
552+
(assignVarEqn, assignEqnVar, true) := Matching.RegularMatching(adjMatrix, BackendDAEUtil.systemSize(syst), BackendDAEUtil.systemSize(syst));
553+
if debug then BackendDump.dumpMatching(assignVarEqn); end if;
554+
555+
// get discrete vars indexes and then the equations
556+
varsIndex := BackendVariable.getVarIndexFromVars(inDiscVars, syst.orderedVars);
557+
if debug then print("discVarsIndex: "); BackendDump.dumpIncidenceRow(varsIndex); end if;
558+
eqnIndex := List.map1(varsIndex, Array.getIndexFirst, assignVarEqn);
559+
if debug then print("discEqnIndex: "); BackendDump.dumpIncidenceRow(eqnIndex); end if;
560+
eqnIndex := List.unique(list(mapEqnScalarArray[i] for i in eqnIndex));
561+
discEqns := BackendEquation.getList(eqnIndex, syst.orderedEqs);
562+
if debug then BackendDump.equationListString(discEqns, "Discrete Equations"); end if;
563+
564+
// get continuous equations
565+
varsIndex := BackendVariable.getVarIndexFromVars(inContVars, syst.orderedVars);
566+
eqnIndex := List.map1(varsIndex, Array.getIndexFirst, assignVarEqn);
567+
eqnIndex := List.unique(list(mapEqnScalarArray[i] for i in eqnIndex));
568+
if debug then print("contEqnIndex: "); BackendDump.dumpIncidenceRow(eqnIndex); end if;
569+
contEqns := BackendEquation.getList(eqnIndex, syst.orderedEqs);
570+
if debug then BackendDump.equationListString(contEqns, "Continuous Equations"); end if;
571+
else
572+
fail();
573+
end try;
574+
end getDiscAndContEqns;
507575

508576
function addVarsGlobalData
509577
input output BackendDAE.BackendDAEModeData globalDAEData;
@@ -513,8 +581,6 @@ protected
513581
algorithm
514582
// prepare algebraic states
515583
vars := List.filterOnTrue(inVars, BackendVariable.isNonStateVar);
516-
// check for discrete vars
517-
{} := List.filterOnTrue(vars, BackendVariable.isVarDiscrete);
518584
vars := list(BackendVariable.setVarKind(v, BackendDAE.ALG_STATE()) for v in vars);
519585
//print("Alg vars: " + BackendDump.varListString(vars, "") + "\n");
520586
globalDAEData.algStateVars := listAppend(vars, globalDAEData.algStateVars);

SimulationRuntime/c/simulation/simulation_runtime.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ int startNonInteractiveSimulation(int argc, char**argv, DATA* data, threadData_t
455455
}
456456
/* if daeMode is turned on than use also the ida solver */
457457
if (omc_flag[FLAG_DAE_MODE] && std::string("ida") != data->simulationInfo->solverMethod) {
458-
data->simulationInfo->solverMethod = std::string("ida").c_str();
458+
data->simulationInfo->solverMethod = GC_strdup(std::string("ida").c_str());
459459
infoStreamPrint(LOG_SIMULATION, 0, "overwrite solver method: %s [DAEmode works only with IDA solver]", data->simulationInfo->solverMethod);
460460
}
461461

@@ -644,7 +644,7 @@ static int callSolver(DATA* simData, threadData_t *threadData, string init_initM
644644
/* if no states are present, then we can
645645
* use euler method, since it does nothing.
646646
*/
647-
if (simData->modelData->nStates < 1 && solverID != S_OPTIMIZATION && solverID != S_SYM_SOLVER) {
647+
if (simData->modelData->nStates < 1 && solverID != S_OPTIMIZATION && solverID != S_SYM_SOLVER && !compiledInDAEMode) {
648648
solverID = S_EULER;
649649
}
650650

SimulationRuntime/c/simulation/solver/ida_solver.c

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -555,22 +555,21 @@ ida_solver_initial(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo
555555
/* configure algebraic variables as such */
556556
if (idaData->daeMode)
557557
{
558-
if (!omc_flag[FLAG_NO_SUPPRESS_ALG])
558+
if (omc_flag[FLAG_NO_SUPPRESS_ALG])
559559
{
560560
flag = IDASetSuppressAlg(idaData->ida_mem, TRUE);
561561
if (checkIDAflag(flag)){
562562
throwStreamPrint(threadData, "##IDA## Suppress algebraic variables in the local error test failed");
563563
}
564+
}
565+
for(i=0; i<idaData->N; ++i)
566+
{
567+
tmp[i] = (i<data->modelData->nStates)? 1.0: 0.0;
568+
}
564569

565-
for(i=0; i<idaData->N; ++i)
566-
{
567-
tmp[i] = (i<data->modelData->nStates)? 1.0: 0.0;
568-
}
569-
570-
flag = IDASetId(idaData->ida_mem, N_VMake_Serial(idaData->N,tmp));
571-
if (checkIDAflag(flag)){
572-
throwStreamPrint(threadData, "##IDA## Mark algebraic variables as such failed!");
573-
}
570+
flag = IDASetId(idaData->ida_mem, N_VMake_Serial(idaData->N,tmp));
571+
if (checkIDAflag(flag)){
572+
throwStreamPrint(threadData, "##IDA## Mark algebraic variables as such failed!");
574573
}
575574
}
576575

@@ -703,6 +702,7 @@ ida_event_update(DATA* data, threadData_t *threadData)
703702
if (compiledInDAEMode == 3){
704703
if (initializedSolver){
705704

705+
data->simulationInfo->needToIterate = 0;
706706
/* get new values from data -> TODO: update all discrete */
707707
data->simulationInfo->discreteCall = 1;
708708

@@ -731,9 +731,9 @@ ida_event_update(DATA* data, threadData_t *threadData)
731731
}
732732

733733
/* increase limits of the non-linear solver */
734-
IDASetMaxNumStepsIC(idaData->ida_mem, 2*data->modelData->nStates*10);
735-
IDASetMaxNumJacsIC(idaData->ida_mem, 2*data->modelData->nStates*10);
736-
IDASetMaxNumItersIC(idaData->ida_mem, 2*data->modelData->nStates*10);
734+
IDASetMaxNumStepsIC(idaData->ida_mem, 2*idaData->N*10);
735+
IDASetMaxNumJacsIC(idaData->ida_mem, 2*idaData->N*10);
736+
IDASetMaxNumItersIC(idaData->ida_mem, 2*idaData->N*10);
737737
/* Calc Consistent y_algebraic and y_prime with current y */
738738
flag = IDACalcIC(idaData->ida_mem, IDA_YA_YDP_INIT, data->localData[0]->timeValue+init_h);
739739

@@ -1029,11 +1029,12 @@ ida_solver_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverInfo)
10291029
/* initialize states and der(states) */
10301030
if (idaData->daeMode)
10311031
{
1032-
idaData->residualFunction(data->localData[0]->timeValue, idaData->y, idaData->yp, idaData->newdelta, idaData);
10331032
memcpy(data->localData[0]->realVars, idaData->states, sizeof(double)*data->modelData->nStates);
10341033
// and also algebraic vars
10351034
data->simulationInfo->daeModeData->setAlgebraicDAEVars(data, threadData, idaData->states + data->modelData->nStates);
10361035
memcpy(data->localData[0]->realVars + data->modelData->nStates, idaData->statesDer, sizeof(double)*data->modelData->nStates);
1036+
sData->timeValue = solverInfo->currentTime;
1037+
idaData->residualFunction(sData->timeValue, idaData->y , idaData->yp, idaData->newdelta, idaData);
10371038
}
10381039

10391040
/* sensitivity mode */
@@ -1149,7 +1150,6 @@ int residualFunctionIDA(double time, N_Vector yy, N_Vector yp, N_Vector res, voi
11491150
{
11501151
setContext(data, &time, CONTEXT_ODE);
11511152
}
1152-
timeBackup = data->localData[0]->timeValue;
11531153
data->localData[0]->timeValue = time;
11541154

11551155
saveJumpState = threadData->currentErrorStage;
@@ -1233,8 +1233,6 @@ int residualFunctionIDA(double time, N_Vector yy, N_Vector yp, N_Vector res, voi
12331233

12341234
threadData->currentErrorStage = saveJumpState;
12351235

1236-
data->localData[0]->timeValue = timeBackup;
1237-
12381236
if (data->simulationInfo->currentContext == CONTEXT_ODE){
12391237
unsetContext(data);
12401238
}
@@ -1250,8 +1248,9 @@ int rootsFunctionIDA(double time, N_Vector yy, N_Vector yp, double *gout, void*
12501248
IDA_SOLVER* idaData = (IDA_SOLVER*)userData;
12511249
DATA* data = (DATA*)(((IDA_USERDATA*)idaData->simData)->data);
12521250
threadData_t* threadData = (threadData_t*)(((IDA_USERDATA*)((IDA_SOLVER*)userData)->simData)->threadData);
1251+
double *states = N_VGetArrayPointer(yy);
1252+
double *statesDer = N_VGetArrayPointer(yp);
12531253

1254-
double timeBackup;
12551254
int saveJumpState;
12561255

12571256
infoStreamPrint(LOG_SOLVER_V, 1, "### eval rootsFunctionIDA ###");
@@ -1270,21 +1269,24 @@ int rootsFunctionIDA(double time, N_Vector yy, N_Vector yp, double *gout, void*
12701269
saveJumpState = threadData->currentErrorStage;
12711270
threadData->currentErrorStage = ERROR_EVENTSEARCH;
12721271

1273-
timeBackup = data->localData[0]->timeValue;
1274-
data->localData[0]->timeValue = time;
1275-
12761272
if (idaData->daeMode)
12771273
{
1278-
memcpy(data->localData[0]->realVars, idaData->states, sizeof(double)*data->modelData->nStates);
1279-
data->simulationInfo->daeModeData->setAlgebraicDAEVars(data, threadData, idaData->states + data->modelData->nStates);
1280-
memcpy(data->localData[0]->realVars + data->modelData->nStates, idaData->statesDer, sizeof(double)*data->modelData->nStates);
1274+
memcpy(data->localData[0]->realVars, states, sizeof(double)*data->modelData->nStates);
1275+
data->simulationInfo->daeModeData->setAlgebraicDAEVars(data, threadData, states + data->modelData->nStates);
1276+
memcpy(data->localData[0]->realVars + data->modelData->nStates, statesDer, sizeof(double)*data->modelData->nStates);
12811277
}
12821278

1279+
data->localData[0]->timeValue = time;
1280+
12831281
/* read input vars */
12841282
externalInputUpdate(data);
12851283
data->callback->input_function(data, threadData);
12861284
/* eval needed equations*/
12871285
if (idaData->daeMode && compiledInDAEMode == 1){}
1286+
else if (idaData->daeMode && compiledInDAEMode == 3)
1287+
{
1288+
idaData->residualFunction(time, yy, yp, idaData->newdelta, idaData);
1289+
}
12881290
else
12891291
{
12901292
data->callback->function_ZeroCrossingsEquations(data, threadData);
@@ -1293,7 +1295,6 @@ int rootsFunctionIDA(double time, N_Vector yy, N_Vector yp, double *gout, void*
12931295
data->callback->function_ZeroCrossings(data, threadData, gout);
12941296

12951297
threadData->currentErrorStage = saveJumpState;
1296-
data->localData[0]->timeValue = timeBackup;
12971298

12981299
/* scale data again */
12991300
if (omc_flag[FLAG_IDA_SCALING])

SimulationRuntime/c/simulation/solver/solver_main.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -687,15 +687,19 @@ int solver_main(DATA* data, threadData_t *threadData, const char* init_initMetho
687687
externalInputallocate(data);
688688
/* set tolerance for ZeroCrossings */
689689
setZCtol(fmin(data->simulationInfo->stepSize, data->simulationInfo->tolerance));
690-
691-
omc_alloc_interface.collect_a_little();
692-
/* initialize all parts of the model */
693-
retVal = initializeModel(data, threadData, init_initMethod, init_file, init_time);
694690
omc_alloc_interface.collect_a_little();
695691

696-
if(0 == retVal) {
697-
retVal = initializeSolverData(data, threadData, &solverInfo);
698-
initSolverInfo = 1;
692+
/* initialize solver data */
693+
/* For the DAEmode we need to initialize solverData before the initialization,
694+
* since the solver is used to obtain consistent values also via updateDiscreteSystem
695+
*/
696+
retVal = initializeSolverData(data, threadData, &solverInfo);
697+
initSolverInfo = 1;
698+
699+
/* initialize all parts of the model */
700+
if (0 == retVal){
701+
retVal = initializeModel(data, threadData, init_initMethod, init_file, init_time);
702+
omc_alloc_interface.collect_a_little();
699703
}
700704

701705
#if !defined(OMC_MINIMAL_RUNTIME)

0 commit comments

Comments
 (0)