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

Commit d316ab2

Browse files
rfrankeOpenModelica-Hudson
authored andcommitted
Add synchronous solver method ExplicitEuler, besides ImplicitEuler
1 parent c2a8668 commit d316ab2

File tree

1 file changed

+112
-24
lines changed

1 file changed

+112
-24
lines changed

Compiler/BackEnd/SynchronousFeatures.mo

Lines changed: 112 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,31 @@ algorithm
188188
BackendDAE.CLOCKED_PARTITION(idx) := syst.partitionKind;
189189
subPartition := shared.partitionsInfo.subPartitions[idx];
190190
solverMethod := BackendDump.optionString(subPartition.clock.solver);
191+
if stringLength(solverMethod) > 7 and substring(solverMethod, 1, 8) == "Explicit" then
192+
if solverMethod <> "ExplicitEuler" then
193+
Error.addCompilerWarning("Solving clocked continuous equations with " +
194+
"ExplicitEuler instead of specified " + solverMethod + ". "
195+
+ "Supporting ExplicitEuler and ImplicitEuler.");
196+
end if;
197+
for i in 1:BackendDAEUtil.equationArraySize(eqs) loop
198+
eq := BackendEquation.equationNth1(eqs, i);
199+
(_, derVars) := BackendEquation.traverseExpsOfEquation(eq, getDerVars1, derVars);
200+
end for;
201+
for i in 1:BackendDAEUtil.equationArraySize(eqs) loop
202+
eq := BackendEquation.equationNth1(eqs, i);
203+
(eq, _) := BackendEquation.traverseExpsOfEquation(eq, shiftDerVars1, derVars);
204+
eqs := BackendEquation.setAtIndex(eqs, i, eq);
205+
end for;
206+
elseif stringLength(solverMethod) > 0 and solverMethod <> "ImplicitEuler" then
207+
Error.addCompilerWarning("Solving clocked continuous equations with " +
208+
"ImplicitEuler instead of specified " + solverMethod + ". "
209+
+ "Supporting ExplicitEuler and ImplicitEuler.");
210+
end if;
191211
lstEqs := {};
212+
derVars := {};
192213
for i in 1:BackendDAEUtil.equationArraySize(eqs) loop
193214
eq := BackendEquation.equationNth1(eqs, i);
194-
(eq, (solverMethod, derVars)) := BackendEquation.traverseExpsOfEquation(eq, applySolverMethod1, (solverMethod, derVars));
215+
(eq, derVars) := BackendEquation.traverseExpsOfEquation(eq, applyEulerMethod1, derVars);
195216
lstEqs := eq::lstEqs;
196217
end for;
197218
syst.orderedEqs := BackendEquation.listEquation(listReverse(lstEqs));
@@ -203,53 +224,120 @@ algorithm
203224
outSysts := listReverse(outSysts);
204225
end treatClockedStates;
205226

206-
protected function applySolverMethod1 "helper to applySolverMethod"
227+
protected function getDerVars1 "helper to getDerVars"
207228
input DAE.Exp inExp;
208-
input tuple<String, list<DAE.ComponentRef>> inTpl;
229+
input list<DAE.ComponentRef> inDerVars;
209230
output DAE.Exp outExp;
210-
output tuple<String, list<DAE.ComponentRef>> outTpl;
231+
output list<DAE.ComponentRef> outDerVars;
211232
algorithm
212-
(outExp, outTpl) := Expression.traverseExpBottomUp(inExp, applySolverMethod, inTpl);
213-
end applySolverMethod1;
233+
(outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, getDerVars, inDerVars);
234+
end getDerVars1;
214235

215-
protected function applySolverMethod
216-
"Apply given solverMethod to convert continous-time to clocked expression.
217-
So far ImplicitEuler, replacing der(x) -> (x - previous(x))/interval().
236+
protected function getDerVars
237+
"Get all crefs that appear in a der() operator.
218238
author: rfranke"
219239
input DAE.Exp inExp;
220-
input tuple<String, list<DAE.ComponentRef>> inTpl;
240+
input list<DAE.ComponentRef> inDerVars;
241+
output DAE.Exp outExp = inExp;
242+
output list<DAE.ComponentRef> outDerVars;
243+
algorithm
244+
outDerVars := match inExp
245+
local
246+
DAE.ComponentRef x;
247+
case DAE.CALL(path = Absyn.IDENT(name = "der"),
248+
expLst = {DAE.CREF(componentRef = x)})
249+
then x :: inDerVars;
250+
else inDerVars;
251+
end match;
252+
end getDerVars;
253+
254+
protected function shiftDerVars1 "helper to shiftDerVars"
255+
input DAE.Exp inExp;
256+
input list<DAE.ComponentRef> inDerVars;
221257
output DAE.Exp outExp;
222-
output tuple<String, list<DAE.ComponentRef>> outTpl;
258+
output list<DAE.ComponentRef> outDerVars;
223259
algorithm
224-
(outExp, outTpl) := match inExp
260+
(outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, shiftDerVars, inDerVars);
261+
end shiftDerVars1;
262+
263+
protected function shiftDerVars
264+
"Apply previous() operator to all inDerVars.
265+
author: rfranke"
266+
input DAE.Exp inExp;
267+
input list<DAE.ComponentRef> inDerVars;
268+
output DAE.Exp outExp;
269+
output list<DAE.ComponentRef> outDerVars = inDerVars;
270+
algorithm
271+
outExp := match inExp
272+
local
273+
List<DAE.Exp> expLst;
274+
DAE.CallAttributes attr;
275+
DAE.ComponentRef x;
276+
DAE.Type ty;
277+
DAE.Exp exp;
278+
// introduce previous()
279+
case DAE.CREF(componentRef = x)
280+
guard ComponentReference.crefInLst(x, inDerVars)
281+
algorithm
282+
exp := DAE.CALL(Absyn.IDENT(name = "previous"), {inExp}, DAE.callAttrBuiltinImpureReal);
283+
then exp;
284+
// check for possibly introduced der(previous())
285+
case DAE.CALL(path = Absyn.IDENT(name = "der"),
286+
expLst = {DAE.CALL(path = Absyn.IDENT(name = "previous"), expLst = expLst)},
287+
attr = attr as DAE.CALL_ATTR(ty = ty))
288+
algorithm
289+
exp := DAE.CALL(Absyn.IDENT(name = "der"), expLst, attr);
290+
then exp;
291+
// check for possibly introduced previous(previous())
292+
case DAE.CALL(path = Absyn.IDENT(name = "previous"),
293+
expLst = {DAE.CALL(path = Absyn.IDENT(name = "previous"), expLst = expLst)},
294+
attr = attr as DAE.CALL_ATTR(ty = ty))
295+
algorithm
296+
exp := DAE.CALL(Absyn.IDENT(name = "previous"), expLst, attr);
297+
then exp;
298+
// do nothing per default
299+
else inExp;
300+
end match;
301+
end shiftDerVars;
302+
303+
protected function applyEulerMethod1 "helper to applyEulerMethod"
304+
input DAE.Exp inExp;
305+
input list<DAE.ComponentRef> inDerVars;
306+
output DAE.Exp outExp;
307+
output list<DAE.ComponentRef> outDerVars;
308+
algorithm
309+
(outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, applyEulerMethod, inDerVars);
310+
end applyEulerMethod1;
311+
312+
protected function applyEulerMethod
313+
"Convert continous-time to clocked expression by replacing
314+
der(x) -> (x - previous(x)) / interval().
315+
author: rfranke"
316+
input DAE.Exp inExp;
317+
input list<DAE.ComponentRef> inDerVars;
318+
output DAE.Exp outExp;
319+
output list<DAE.ComponentRef> outDerVars;
320+
algorithm
321+
(outExp, outDerVars) := match inExp
225322
local
226323
List<DAE.Exp> expLst;
227324
DAE.CallAttributes attr;
228325
DAE.ComponentRef x;
229326
DAE.Type ty;
230327
DAE.Exp exp;
231-
String inSolverMethod, outSolverMethod;
232-
list<DAE.ComponentRef> inDerVars;
233328
case DAE.CALL(path = Absyn.IDENT(name = "der"),
234329
expLst = expLst as {DAE.CREF(componentRef = x)},
235330
attr = attr as DAE.CALL_ATTR(ty = ty))
236331
algorithm
237-
(inSolverMethod, inDerVars) := inTpl;
238-
outSolverMethod := "ImplicitEuler";
239332
exp := DAE.CALL(Absyn.IDENT(name = "previous"), expLst, attr);
240333
exp := DAE.BINARY(DAE.CREF(x, ty), DAE.SUB(DAE.T_REAL_DEFAULT), exp);
241334
exp := DAE.BINARY(exp, DAE.DIV(DAE.T_REAL_DEFAULT),
242335
DAE.CALL(Absyn.IDENT(name = "interval"), {},
243336
DAE.callAttrBuiltinImpureReal));
244-
if outSolverMethod <> inSolverMethod then
245-
Error.addCompilerWarning("Solved clocked continuous equations with " +
246-
outSolverMethod + " instead of specified " +
247-
inSolverMethod + ".");
248-
end if;
249-
then (exp, (outSolverMethod, x :: inDerVars));
250-
else (inExp, inTpl);
337+
then (exp, x :: inDerVars);
338+
else (inExp, inDerVars);
251339
end match;
252-
end applySolverMethod;
340+
end applyEulerMethod;
253341

254342
protected function markClockedStates
255343
"Collect discrete states and mark them for further processing.

0 commit comments

Comments
 (0)