Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 78.7% 448 / 0 / 569
Functions: -% 0 / 1 / 1
Branches: 77.0% 208 / 0 / 270

OMCompiler/Compiler/BackEnd/ExpressionSolve.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package ExpressionSolve
37 " file: ExpressionSolve.mo
38 package: ExpressionSolve
39 description: ExpressionSolve
40
41
42 This file contains the module ExpressionSolve, which contains functions
43 to solve a DAE.Exp for a DAE.Exp"
44
45 // public imports
46 public import Absyn;
47 public import AbsynUtil;
48 public import DAE;
49
50 // protected imports
51 protected import ComponentReference;
52 protected import ComponentReferenceBasics;
53 protected import Debug;
54 protected import Differentiate;
55 protected import ElementSource;
56 protected import Ceval;
57 protected import Expression;
58 protected import ExpressionBasics;
59 protected import ExpressionDump;
60 protected import ExpressionSimplify;
61 protected import Flags;
62 protected import Global;
63 protected import List;
64 protected import Inline;
65 protected import BackendDAE;
66 protected import BackendDAEUtil;
67 protected import BackendEquation;
68 protected import BackendVariable;
69 protected import Types;
70
71 // =============================================================================
72 // section for postOptModule >>solveSimpleEquations<<
73 //
74 // solve simple equations otherwise detect EQUATIONSYSTEM
75 // =============================================================================
76
77 public function solveSimpleEquations
78 input output BackendDAE.BackendDAE dae;
79 protected
80 list<BackendDAE.EqSystem> systs;
81 BackendDAE.Shared shared;
82 algorithm
83 3936 (systs, shared) := List.mapFold(dae.eqs, solveSimpleEquationsSyst, dae.shared);
84 3936 dae := BackendDAE.DAE(systs, shared);
85 end solveSimpleEquations;
86
87 protected function solveSimpleEquationsSyst
88 input output BackendDAE.EqSystem syst;
89 input output BackendDAE.Shared shared;
90 protected
91 BackendDAE.StrongComponents comps = {}, oldComps;
92 BackendDAE.StrongComponent tmpComp;
93 array<Integer> ass1, ass2;
94 BackendDAE.Equation eqn;
95 BackendDAE.Var var;
96 Integer eindex, vindx;
97 Boolean solved;
98 algorithm
99 () := match syst
100 case BackendDAE.EQSYSTEM(matching = BackendDAE.MATCHING(ass1 = ass1, ass2 = ass2, comps = oldComps))
101 algorithm
102
2/2
✓ Branch 0 taken 160390 times.
✓ Branch 1 taken 53246 times.
213636 for comp in oldComps loop
103 tmpComp := comp;
104
2/2
✓ Branch 1 taken 156026 times.
✓ Branch 2 taken 4364 times.
160390 if isSingleEquation(comp) then
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156026 times.
156026 BackendDAE.SINGLEEQUATION(eqn=eindex, var=vindx) := comp;
106 156026 eqn := BackendEquation.get(syst.orderedEqs, eindex);
107
2/2
✓ Branch 1 taken 155777 times.
✓ Branch 2 taken 249 times.
156026 if BackendEquation.isEquation(eqn) then
108 155777 var := BackendVariable.getVarAt(syst.orderedVars, vindx);
109 155777 (eqn, shared, solved) := solveSimpleEquation(eqn, var, shared);
110 155777 syst.orderedEqs := BackendEquation.setAtIndex(syst.orderedEqs, eindex, eqn);
111
2/2
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 155419 times.
155777 if not solved then
112 358 tmpComp := BackendDAE.EQUATIONSYSTEM({eindex}, {vindx}, BackendDAE.EMPTY_JACOBIAN(), BackendDAE.JAC_NONLINEAR(), false);
113 end if;
114 end if;
115 end if;
116 comps := tmpComp :: comps;
117 end for;
118 106492 syst.matching := BackendDAE.MATCHING(ass1, ass2, listReverse(comps));
119 then ();
120
121 else ();
122 end match;
123 end solveSimpleEquationsSyst;
124
125 protected function isSingleEquation
126 input BackendDAE.StrongComponent comp;
127 output Boolean b;
128 algorithm
129 b := match comp
130 case BackendDAE.SINGLEEQUATION() then true;
131 else false;
132 end match;
133 end isSingleEquation;
134
135 protected function solveSimpleEquation
136 input output BackendDAE.Equation eqn;
137 input BackendDAE.Var var "solve eqn with respect to var";
138 input output BackendDAE.Shared shared;
139 output Boolean solved;
140 protected
141 DAE.ComponentRef cr;
142 DAE.Exp lhs,rhs,e1,e2,varexp,e;
143 BackendDAE.EquationAttributes attr;
144 DAE.ElementSource source;
145 Boolean isContinuousIntegration = BackendDAEUtil.isSimulationDAE(shared);
146 algorithm
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 155777 times.
155777 BackendDAE.EQUATION(exp=lhs, scalar=rhs, source=source, attr=attr) := eqn;
148 155777 (e1, e2) := (lhs, rhs);
149 155777 BackendDAE.VAR(varName = cr) := var;
150 155777 varexp := Expression.crefExp(cr);
151
2/2
✓ Branch 1 taken 3530 times.
✓ Branch 2 taken 152247 times.
155777 if BackendVariable.isStateVar(var) then
152 3530 varexp := Expression.expDer(varexp);
153 3530 cr := ComponentReference.crefPrefixDer(cr);
154 end if;
155
156 // phi: aren't the types of e1 and e2 the same? Can we make the equation have a type?
157
3/4
✓ Branch 2 taken 151345 times.
✓ Branch 3 taken 4432 times.
✓ Branch 6 taken 151345 times.
✗ Branch 7 not taken.
155777 if (Types.isIntegerOrRealOrSubTypeOfEither(Expression.typeof(e1)) and Types.isIntegerOrRealOrSubTypeOfEither(Expression.typeof(e2))) then
158 151345 (e1, e2) := preprocessingSolve(e1, e2, varexp, NONE(), SOME(shared.functionTree), NONE(), 0, false);
159 end if;
160
161 try
162 155777 e := solve2(e1, e2, varexp, SOME(shared.functionTree), NONE(), false, isContinuousIntegration);
163 155419 source := ElementSource.addSymbolicTransformationSolve(true, source, cr, e1, e2, e, {});
164 155419 eqn := BackendEquation.generateEquation(varexp, e, source, attr);
165 solved := true;
166 else
167 // only return new eqn if it can be solved explicitely because intermediate results can be numerically bad
168 // solves ticket #4293
169 // ToDo: do other preprocessing like multiplying by divisors?
170 solved := false;
171 end try;
172
173
4/4
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 155419 times.
✓ Branch 3 taken 144158 times.
✓ Branch 4 taken 11261 times.
155777 if solved and not isSolvedFor(lhs, rhs, varexp) then
174 11261 shared := checkSolveCoefficient(lhs, rhs, cr, source, shared);
175 end if;
176 end solveSimpleEquation;
177
178 protected function isSolvedFor
179 "Whether lhs = rhs already has the form x = f(..) for varexp, up to a sign."
180 input DAE.Exp lhs;
181 input DAE.Exp rhs;
182 input DAE.Exp varexp;
183 output Boolean b = true;
184 algorithm
185 try
186 155419 solveSimple(lhs, rhs, varexp, 0);
187 else
188 try
189 16019 solveSimple(rhs, lhs, varexp, 0);
190 else
191 b := false;
192 end try;
193 end try;
194 end isSolvedFor;
195
196 protected function checkSolveCoefficient
197 "Checks the coefficient that solving lhs = rhs for cr divides by. If it only
198 depends on parameters and is zero for their compile-time values, the
199 parameters are added to Global.structuralParameters, so that translateModel
200 evaluates them and translates the model again. Otherwise an assert that the
201 coefficient stays nonzero is added to the parameter asserts."
202 input DAE.Exp lhs;
203 input DAE.Exp rhs;
204 input DAE.ComponentRef cr "$DER-prefixed for a state";
205 input DAE.ElementSource source;
206 input output BackendDAE.Shared shared;
207 protected
208 DAE.Exp coef, value, cond;
209 list<DAE.ComponentRef> params, zeroParams;
210 list<String> names;
211 BackendDAE.Var v;
212 DAE.Type ty;
213 String msg;
214 DAE.Statement stmt;
215 algorithm
216 try
217 11261 coef := Differentiate.differentiateExpSolve(Expression.replaceDerOpInExp(Expression.expSub(lhs, rhs)), cr, SOME(shared.functionTree));
218 11259 (coef, _) := ExpressionSimplify.simplify(coef);
219
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 11259 times.
11259 false := Types.isArray(Expression.typeof(coef));
220 11259 params := List.uniqueOnTrue(Expression.extractCrefsFromExp(coef), ComponentReferenceBasics.crefEqual);
221
2/2
✓ Branch 0 taken 7994 times.
✓ Branch 1 taken 3265 times.
11259 false := listEmpty(params);
222
2/2
✓ Branch 0 taken 4165 times.
✓ Branch 1 taken 1767 times.
5932 for p in params loop
223
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3257 times.
4165 (v :: _, _) := BackendVariable.getVar(p, shared.globalKnownVars);
224
4/4
✓ Branch 1 taken 2741 times.
✓ Branch 2 taken 516 times.
✓ Branch 4 taken 2667 times.
✓ Branch 5 taken 74 times.
3257 true := BackendVariable.isParam(v) and BackendVariable.varFixed(v);
225 end for;
226 1767 value := evaluateParameterExp(coef, shared.globalKnownVars);
227
2/2
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 1482 times.
1767 true := Expression.isConst(value);
228 else
229 9779 return;
230 end try;
231
232
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1480 times.
1482 if Expression.isZero(value) then
233
5/6
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
4 zeroParams := list(p for p guard Expression.isZero(evaluateParameterExp(Expression.crefExp(p), shared.globalKnownVars)) in params);
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if listEmpty(zeroParams) then
235 zeroParams := params;
236 end if;
237 2 names := getGlobalRoot(Global.structuralParameters);
238
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for p in zeroParams loop
239 2 names := List.unionElt(ComponentReferenceBasics.printComponentRefStr(ComponentReference.crefStripSubs(p)), names);
240 end for;
241 2 setGlobalRoot(Global.structuralParameters, names);
242 else
243 1480 ty := Expression.typeof(coef);
244 1480 cond := DAE.RELATION(coef, DAE.NEQUAL(ty), Expression.makeConstZero(ty), -1, NONE());
245
2/2
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 1141 times.
1480 msg := if Expression.isCref(coef)
246 then "Parameter " + ExpressionBasics.printExpStr(coef) + " cannot be set to zero at run time, because that causes a structural change in the equations; set " + ExpressionBasics.printExpStr(coef) + " = 0 in the model and recompile it."
247 else "The parameters in " + ExpressionBasics.printExpStr(coef) + " cannot be set so that it is zero at run time, because that causes a structural change in the equations; set their values in the model and recompile it.";
248 1480 stmt := DAE.STMT_ASSERT(cond, DAE.SCONST(msg), DAE.ASSERTIONLEVEL_ERROR, source);
249
2/2
✓ Branch 3 taken 256 times.
✓ Branch 4 taken 1224 times.
1480 if not List.any(shared.parameterAsserts, function assertCondEqual(stmt2 = stmt)) then
250 2448 shared.parameterAsserts := stmt :: shared.parameterAsserts;
251 end if;
252 end if;
253 end checkSolveCoefficient;
254
255 protected function evaluateParameterExp
256 input DAE.Exp exp;
257 input BackendDAE.Variables globalKnownVars;
258 output DAE.Exp value;
259 algorithm
260 1769 (value, _) := Expression.traverseExpBottomUp(exp, BackendDAEUtil.replaceVarWithValue, globalKnownVars);
261 1769 (value, _) := ExpressionSimplify.simplify(value);
262 end evaluateParameterExp;
263
264 public function assertCondEqual
265 input DAE.Statement stmt1;
266 input DAE.Statement stmt2;
267 output Boolean b;
268 algorithm
269 b := match (stmt1, stmt2)
270 10103 case (DAE.STMT_ASSERT(), DAE.STMT_ASSERT()) then ExpressionBasics.expEqual(stmt1.cond, stmt2.cond);
271 else false;
272 end match;
273 end assertCondEqual;
274
275 protected function printTryToSolve
276 "for debugging"
277 input String instanceName "getInstanceName from caller";
278 input DAE.Exp inExp1 "lhs";
279 input DAE.Exp inExp2 "rhs";
280 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
281 algorithm
282 ✗ print(instanceName + " tries to solve: " +
283 ExpressionBasics.printExpStr(inExp1) + " = " + ExpressionBasics.printExpStr(inExp2) +
284 "\nwith respect to: " + ExpressionBasics.printExpStr(inExp3) + "\n");
285 end printTryToSolve;
286
287 public function solve
288 "Solves an equation consisting of a right hand side (rhs) and a
289 left hand side (lhs), with respect to the expression given as
290 third argument, usually a variable."
291 input DAE.Exp inExp1 "lhs";
292 input DAE.Exp inExp2 "rhs";
293 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
294 input Option<AvlTreePathFunction.Tree> functions = NONE() "need for solve modelica functions";
295 output DAE.Exp outExp;
296 output list<DAE.Statement> outAsserts;
297 protected
298 list<BackendDAE.Equation> dummy1;
299 list<DAE.ComponentRef> dummy2;
300 Integer dummyI;
301 algorithm
302 //printTryToSolve(getInstanceName(), inExp1, inExp2, inExp3);
303
304 (outExp,outAsserts,dummy1, dummy2, dummyI) := matchcontinue inExp1
305 92325 case _ then solveSimple(inExp1, inExp2, inExp3, 0);
306 11593 case _ then solveSimple(inExp2, inExp1, inExp3, 0);
307 10513 case _ then solveWork(inExp1, inExp2, inExp3, NONE(), functions, NONE(), 0, false, false);
308 else algorithm
309
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3774 times.
3775 if Flags.isSet(Flags.FAILTRACE) then
310 1 Error.addInternalError("Failed to solve \"" + ExpressionBasics.printExpStr(inExp1) + " = " + ExpressionBasics.printExpStr(inExp2) + "\" w.r.t. \"" + ExpressionBasics.printExpStr(inExp3) + "\"", sourceInfo());
311 end if;
312 3775 then fail();
313 end matchcontinue;
314
315 88550 (outExp,_) := ExpressionSimplify.simplify1(outExp);
316 end solve;
317
318
319 public function solve2
320 "Solves an equation with modelica function consisting of a right hand side (rhs) and a
321 left hand side (lhs), with respect to the expression given as
322 third argument, usually a variable.
323 "
324 input DAE.Exp inExp1 "lhs";
325 input DAE.Exp inExp2 "rhs";
326 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
327 input Option<AvlTreePathFunction.Tree> functions "need for solve modelica functions";
328 input Option<Integer> uniqueEqIndex "offset for tmp vars";
329 input Boolean doInline = true;
330 input Boolean isContinuousIntegration = false;
331 output DAE.Exp outExp;
332 output list<DAE.Statement> outAsserts;
333 output list<BackendDAE.Equation> eqnForNewVars "eqn for tmp vars";
334 output list<DAE.ComponentRef> newVarsCrefs;
335 protected
336 Integer dummyI;
337 algorithm
338 //printTryToSolve(getInstanceName(), inExp1, inExp2, inExp3);
339
340 (outExp,outAsserts,eqnForNewVars,newVarsCrefs,dummyI) := matchcontinue inExp1
341 340479 case _ then solveSimple(inExp1, inExp2, inExp3, 0);
342 13476 case _ then solveSimple(inExp2, inExp1, inExp3, 0);
343 12775 case _ then solveWork(inExp1, inExp2, inExp3, NONE(), functions, uniqueEqIndex, 0, doInline, isContinuousIntegration);
344 else algorithm
345
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 628 times.
632 if Flags.isSet(Flags.FAILTRACE) then
346 4 Error.addInternalError("Failed to solve \"" + ExpressionBasics.printExpStr(inExp1) + " = " + ExpressionBasics.printExpStr(inExp2) + "\" w.r.t. \"" + ExpressionBasics.printExpStr(inExp3) + "\"", sourceInfo());
347 end if;
348 632 then fail();
349 end matchcontinue;
350 end solve2;
351
352
353 protected function solveWork
354 input DAE.Exp inExp1 "lhs";
355 input DAE.Exp inExp2 "rhs";
356 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
357 input Option<DAE.Exp> optCond "condition from an if expression";
358 input Option<AvlTreePathFunction.Tree> functions;
359 input Option<Integer> uniqueEqIndex "offset for tmp vars";
360 input Integer idepth;
361 input Boolean doInline;
362 input Boolean isContinuousIntegration;
363 output DAE.Exp outExp;
364 output list<DAE.Statement> outAsserts;
365 output list<BackendDAE.Equation> eqnForNewVars "eqn for tmp vars";
366 output list<DAE.ComponentRef> newVarsCrefs;
367 output Integer depth;
368 protected
369 DAE.Exp e1, e2;
370 list<BackendDAE.Equation> eqnForNewVars1, eqnForNewVars2;
371 list<DAE.ComponentRef> newVarsCrefs1, newVarsCrefs2;
372 algorithm
373 (e1, e2, eqnForNewVars1, newVarsCrefs1, depth) := matchcontinue inExp1
374 23932 case _ then preprocessingSolve(inExp1, inExp2, inExp3, optCond, functions, uniqueEqIndex, idepth, doInline);
375 else
376 algorithm
377
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if Flags.isSet(Flags.FAILTRACE) then
378 ✗ Debug.trace("\n-ExpressionSolve.preprocessingSolve failed:\n");
379 ✗ Debug.trace(ExpressionBasics.printExpStr(inExp1) + " = " + ExpressionBasics.printExpStr(inExp2));
380 ✗ Debug.trace(" with respect to: " + ExpressionBasics.printExpStr(inExp3));
381 end if;
382 21 then (inExp1,inExp2,{},{}, idepth);
383 end matchcontinue;
384
385 (outExp, outAsserts, eqnForNewVars2, newVarsCrefs2, depth) := matchcontinue e1
386 23932 case _ then solveIfExp(e1, e2, inExp3, optCond, functions, uniqueEqIndex, depth, doInline, isContinuousIntegration);
387 23685 case _ then solveSimple(e1, e2, inExp3, depth);
388 4606 case _ then solveLinearSystem(e1, e2, inExp3, functions, depth);
389 end matchcontinue;
390
391 19427 eqnForNewVars := listAppend(eqnForNewVars1, eqnForNewVars2);
392 19427 newVarsCrefs := listAppend(newVarsCrefs1, newVarsCrefs2);
393 end solveWork;
394
395 protected function solveSimple
396 "Solves simple equations like
397 a = f(..)
398 der(a) = f(..)
399 -a = f(..)
400 -der(a) = f(..)"
401 input DAE.Exp inExp1 "lhs";
402 input DAE.Exp inExp2 "rhs";
403 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
404 input Integer idepth;
405 output DAE.Exp outExp;
406 output list<DAE.Statement> outAsserts;
407 output list<BackendDAE.Equation> eqnForNewVars = {} "eqn for tmp vars";
408 output list<DAE.ComponentRef> newVarsCrefs = {};
409 output Integer odepth = idepth;
410
411 algorithm
412 //printTryToSolve(getInstanceName(), inExp1, inExp2, inExp3);
413
414 (outExp,outAsserts) := match (inExp1, inExp3)
415 local
416 DAE.ComponentRef cr,cr1;
417 DAE.Type tp;
418 list<DAE.Statement> asserts;
419
420 // special case when already solved, cr1 = rhs, otherwise division by zero when dividing with derivative
421 case (DAE.CREF(componentRef = cr1), DAE.CREF(componentRef = cr))
422 guard ComponentReferenceBasics.crefEqual(cr, cr1) and (not Expression.expHasCrefNoPreOrStart(inExp2, cr))
423 then
424 (inExp2,{});
425 case (DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr1)}), DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr)}))
426 guard ComponentReferenceBasics.crefEqual(cr, cr1) and (not Expression.expHasDerCref(inExp2, cr))
427 then
428 (inExp2,{});
429
430 // -cr = exp
431 case (DAE.UNARY(operator = DAE.UMINUS(), exp = DAE.CREF(componentRef = cr1)), DAE.CREF(componentRef = cr))
432 guard ComponentReferenceBasics.crefEqual(cr1,cr) and (not Expression.expHasCrefNoPreOrStart(inExp2,cr))
433 4523 then
434 (Expression.negate(inExp2),{});
435 case (DAE.UNARY(operator = DAE.UMINUS_ARR(), exp = DAE.CREF(componentRef = cr1)), DAE.CREF(componentRef = cr))
436 guard ComponentReferenceBasics.crefEqual(cr1,cr) and (not Expression.expHasCrefNoPreOrStart(inExp2,cr)) // cr not in e2
437 ✗ then
438 (Expression.negate(inExp2),{});
439 case (DAE.UNARY(operator = DAE.UMINUS(), exp = DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr1)})), DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr)}))
440 guard ComponentReferenceBasics.crefEqual(cr1,cr) and (not Expression.expHasDerCref(inExp2,cr)) // cr not in e2
441 2 then
442 (Expression.negate(inExp2),{});
443 case (DAE.UNARY(operator = DAE.UMINUS_ARR(), exp = DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr1)})), DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr)}))
444 guard ComponentReferenceBasics.crefEqual(cr1,cr) and (not Expression.expHasDerCref(inExp2,cr))
445 ✗ then
446 (Expression.negate(inExp2),{});
447
448 // !cr = exp
449 case (DAE.LUNARY(operator = DAE.NOT(), exp = DAE.CREF(componentRef = cr1)), DAE.CREF(componentRef = cr))
450 guard ComponentReferenceBasics.crefEqual(cr1,cr) and (not Expression.expHasCrefNoPreOrStart(inExp2,cr))
451 266 then
452 (Expression.negate(inExp2),{});
453
454 // Integer(enumcr) = ...
455 case (DAE.CALL(path = Absyn.IDENT(name = "Integer"),expLst={DAE.CREF(componentRef = cr1)}), DAE.CREF(componentRef = cr,ty=tp))
456 guard ComponentReferenceBasics.crefEqual(cr, cr1) and (not Expression.expHasCrefNoPreorDer(inExp2,cr))
457 algorithm
458 ✗ asserts := generateAssertType(tp,cr,inExp3,{});
459 ✗ then (DAE.CAST(tp,inExp2),asserts);
460 else fail();
461 end match;
462 end solveSimple;
463
464 protected function generateAssertType
465 input DAE.Type tp;
466 input DAE.ComponentRef cr;
467 input DAE.Exp iExp;
468 input list<DAE.Statement> inAsserts;
469 output list<DAE.Statement> outAsserts;
470 algorithm
471 outAsserts := match tp
472 local
473 Absyn.Path path,p1,pn;
474 list<String> names;
475 Integer n;
476 DAE.Exp e1,en,e,es;
477 String s1,sn,estr,crstr;
478 case DAE.T_ENUMERATION(path=path,names=names)
479 algorithm
480 ✗ p1 := AbsynUtil.suffixPath(path,listHead(names));
481 ✗ e1 := DAE.ENUM_LITERAL(p1,1);
482 ✗ n := listLength(names);
483 ✗ pn := AbsynUtil.suffixPath(path,listGet(names,n));
484 ✗ en := DAE.ENUM_LITERAL(p1,n);
485 ✗ s1 := AbsynUtil.pathString(p1);
486 ✗ sn := AbsynUtil.pathString(pn);
487 ✗ crstr := ComponentReferenceBasics.printComponentRefStr(cr);
488 ✗ estr := "Expression for " + crstr + " out of min(" + s1 + ")/max(" + sn + ") = ";
489 // iExp >= e1 and iExp <= en
490 ✗ e := DAE.LBINARY(DAE.RELATION(iExp,DAE.GREATEREQ(DAE.T_INTEGER_DEFAULT),e1,-1,NONE()),DAE.AND(DAE.T_BOOL_DEFAULT),
491 DAE.RELATION(iExp,DAE.LESSEQ(DAE.T_INTEGER_DEFAULT),en,-1,NONE()));
492 ✗ es := Expression.makePureBuiltinCall("String", {iExp,DAE.SCONST("d")}, DAE.T_STRING_DEFAULT);
493 ✗ es := DAE.BINARY(DAE.SCONST(estr),DAE.ADD(DAE.T_STRING_DEFAULT),es);
494 ✗ then
495 DAE.STMT_ASSERT(e,es,DAE.ASSERTIONLEVEL_ERROR,DAE.emptyElementSource)::inAsserts;
496 else inAsserts;
497 end match;
498 end generateAssertType;
499
500 public function preprocessingSolve
501 "
502 preprocessing for solve1,
503 sorting and split terms , with respect to the expression given as
504 third argument.
505
506 {f(x,y), g(x,y),x} -> {h(x), k(y)}
507
508 author: Vitalij Ruge
509 "
510
511 input output DAE.Exp x "lhs";
512 input output DAE.Exp y "rhs";
513 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
514 input Option<DAE.Exp> optCond "condition from an if expression";
515 input Option<AvlTreePathFunction.Tree> functions;
516 input Option<Integer> uniqueEqIndex "offset for tmp vars";
517 input Integer idepth;
518 input Boolean doInline;
519 output list<BackendDAE.Equation> eqnForNewVars = {} "eqn for tmp vars";
520 output list<DAE.ComponentRef> newVarsCrefs = {};
521 output Integer depth = idepth;
522
523 protected
524 DAE.Exp lhsX, rhsX, lhsY, rhsY, N;
525 Boolean con, new_x, inlineFun = true;
526 Integer iter;
527 Integer numSimplifed = 0 ;
528 algorithm
529 // split and sort
530 175277 (lhsX, lhsY) := preprocessingSolve5(x, inExp3,true);
531 175277 (rhsX, rhsY) := preprocessingSolve5(y, inExp3,true);
532 175277 x := Expression.expSub(lhsX, rhsX);
533 175277 y := Expression.expSub(rhsY, lhsY);
534
535 175256 con := not Expression.isCref(x);
536 iter := 0;
537
2/2
✓ Branch 0 taken 35531 times.
✓ Branch 1 taken 139725 times.
175256 if con then
538 35531 x := unifyFunCalls(x, inExp3);
539 end if;
540
4/4
✓ Branch 0 taken 41373 times.
✓ Branch 1 taken 148693 times.
✓ Branch 3 taken 40759 times.
✓ Branch 4 taken 614 times.
190066 while con and iter < 1000 and (not Expression.isCref(x)) loop
541 40759 (x, y, con) := preprocessingSolve2(x,y, inExp3);
542 40759 (x, y, new_x) := preprocessingSolve3(x,y, inExp3);
543
4/4
✓ Branch 0 taken 10154 times.
✓ Branch 1 taken 30605 times.
✓ Branch 2 taken 10121 times.
✓ Branch 3 taken 33 times.
50880 con := con or new_x;
544
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 40759 times.
40820 while new_x loop
545 61 (x, y, new_x) := preprocessingSolve3(x,y, inExp3);
546 end while;
547
548
2/2
✓ Branch 1 taken 14810 times.
✓ Branch 2 taken 25949 times.
40759 if Expression.isCref(x) then
549 break;
550 end if;
551 14810 (x, y, new_x) := removeSimpleCalls(x,y, inExp3);
552
4/4
✓ Branch 0 taken 10121 times.
✓ Branch 1 taken 4689 times.
✓ Branch 2 taken 10070 times.
✓ Branch 3 taken 51 times.
14810 con := con or new_x;
553 14810 (x, y, new_x) := preprocessingSolve4(x,y, inExp3);
554
4/4
✓ Branch 0 taken 14803 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 10063 times.
✓ Branch 3 taken 4740 times.
14810 con := new_x or con;
555 // TODO: use new defined function, which missing in the cpp runtime
556
7/8
✗ Branch 0 not taken.
✓ Branch 1 taken 14810 times.
✓ Branch 2 taken 1821 times.
✓ Branch 3 taken 12989 times.
✓ Branch 5 taken 70 times.
✓ Branch 6 taken 1751 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 68 times.
14810 if isSome(uniqueEqIndex) and not stringEqual(Config.simCodeTarget(), "Cpp") then
557 1753 (x, y, new_x, eqnForNewVars, newVarsCrefs, depth) := preprocessingSolveTmpVars(x, y, inExp3, optCond, Util.getOption(uniqueEqIndex), eqnForNewVars, newVarsCrefs, depth);
558
4/4
✓ Branch 0 taken 1494 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 962 times.
✓ Branch 3 taken 532 times.
2715 con := new_x or con;
559 end if;
560
561
2/2
✓ Branch 0 taken 9887 times.
✓ Branch 1 taken 4923 times.
14810 if (not con) then
562
2/2
✓ Branch 0 taken 9821 times.
✓ Branch 1 taken 66 times.
9887 if (numSimplifed < 3) then
563 9821 (x, con) := ExpressionSimplify.simplify(x);
564 9821 numSimplifed := numSimplifed + 1;
565 end if;
566 // Z/N = rhs -> Z = rhs*N
567 9887 (x,N) := Expression.makeFraction(x);
568
2/2
✓ Branch 1 taken 279 times.
✓ Branch 2 taken 9608 times.
9887 if not Expression.isOne(N) then
569 //print("\nx ");print(ExpressionBasics.printExpStr(x));print("\nN ");print(ExpressionBasics.printExpStr(N));
570 279 new_x := true;
571 279 y := Expression.expMul(y,N);
572 end if;
573
574
4/4
✓ Branch 0 taken 9608 times.
✓ Branch 1 taken 279 times.
✓ Branch 2 taken 8999 times.
✓ Branch 3 taken 609 times.
18886 con := new_x or con;
575 end if;
576
577
2/2
✓ Branch 0 taken 5811 times.
✓ Branch 1 taken 8999 times.
14810 if con then
578 5811 (lhsX, lhsY) := preprocessingSolve5(x, inExp3, true);
579 5811 (rhsX, rhsY) := preprocessingSolve5(y, inExp3, false);
580 5811 x := Expression.expSub(lhsX, rhsX);
581 5811 y := Expression.expSub(rhsY, lhsY);
582 elseif doInline and inlineFun then
583 507 iter := iter + 50;
584 if inlineFun then
585 507 (x,con) := solveFunCalls(x, inExp3, functions);
586 inlineFun := false;
587
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 476 times.
507 if con then
588 numSimplifed := 0;
589 end if;
590 end if;
591 end if;
592
593 14810 iter := iter + 1;
594 //print("\nx ");print(ExpressionBasics.printExpStr(x));print("\ny ");print(ExpressionBasics.printExpStr(y));
595 end while;
596
597 175256 y := ExpressionSimplify.simplify1(y);
598 end preprocessingSolve;
599
600 protected function preprocessingSolve2
601 "
602 helprer function for preprocessingSolve
603 e.g.
604 x/(x+c1) = -c2 --> x + (x+c1)*c2 = 0
605
606 author: Vitalij Ruge
607 "
608 input DAE.Exp inExp1 "lhs";
609 input DAE.Exp inExp2 "rhs";
610 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
611
612 output DAE.Exp olhs;
613 output DAE.Exp orhs;
614 output Boolean con "continue";
615
616 algorithm
617
618 (olhs, orhs, con) := match inExp1
619 local
620 DAE.Exp e,b, fa, ga, lhs;
621 DAE.Type tp;
622 list<DAE.Exp> eWithX, factorWithX, factorWithoutX;
623 DAE.Exp pWithX, pWithoutX;
624
625 // -f(a) = b => f(a) = -b
626 case DAE.UNARY(DAE.UMINUS(), fa)
627 guard expHasCref(fa, inExp3) and not expHasCref(inExp2, inExp3)
628 algorithm
629 18529 b := Expression.negate(inExp2);
630 then (fa, b, true);
631
632 case DAE.UNARY(DAE.UMINUS_ARR(), fa)
633 guard expHasCref(fa, inExp3) and not expHasCref(inExp2, inExp3)
634 algorithm
635 ✗ b := Expression.negate(inExp2);
636 then (fa, b, true);
637
638 // b/f(a) = rhs => f(a) = b/rhs solve for a
639 case DAE.BINARY(b,DAE.DIV(_),fa)
640 guard expHasCref(fa, inExp3) and (not expHasCref(b, inExp3)) and (not expHasCref(inExp2, inExp3))
641 algorithm
642 31 e := Expression.makeDiv(b, inExp2);
643 then(fa, e, true);
644
645 // b*f(a) = rhs => f(a) = rhs/b solve for a
646 case DAE.BINARY(b, DAE.MUL(_), fa)
647 guard expHasCref(fa, inExp3) and (not expHasCref(b, inExp3)) and (not expHasCref(inExp2, inExp3))
648 algorithm
649
650 11166 eWithX := Expression.expandFactors(inExp1);
651 11166 (factorWithX, factorWithoutX) := List.split1OnTrue(eWithX, expHasCref, inExp3);
652 11166 pWithX := makeProductLstSort(factorWithX);
653 11166 pWithoutX := makeProductLstSort(factorWithoutX);
654
655 11166 e := Expression.makeDiv(inExp2, pWithoutX);
656
657 then(pWithX, e, true);
658
659 // b*a = rhs => a = rhs/b solve for a
660 case DAE.BINARY(b, DAE.MUL(_), fa)
661 guard expHasCref(fa, inExp3) and (not expHasCref(b, inExp3)) and (not expHasCref(inExp2, inExp3))
662 algorithm
663 ✗ e := Expression.makeDiv(inExp2, b);
664 then(fa, e, true);
665
666 // a*b = rhs => a = rhs/b solve for a
667 case DAE.BINARY(fa, DAE.MUL(_), b)
668 guard expHasCref(fa, inExp3) and (not expHasCref(b, inExp3)) and (not expHasCref(inExp2, inExp3))
669 algorithm
670 ✗ e := Expression.makeDiv(inExp2, b);
671 then(fa, e, true);
672
673 // f(a)/b = rhs => f(a) = rhs*b solve for a
674 case DAE.BINARY(fa, DAE.DIV(_), b)
675 guard expHasCref(fa, inExp3) and (not expHasCref(b, inExp3)) and (not expHasCref(inExp2, inExp3))
676 algorithm
677 869 e := Expression.expMul(inExp2, b);
678 then (fa, e, true);
679
680 // g(a)/f(a) = rhs => rhs*f(a) - g(a) = 0 solve for a
681 case DAE.BINARY(ga, DAE.DIV(tp), fa)
682 guard expHasCref(fa, inExp3) and expHasCref(ga, inExp3) and (not expHasCref(inExp2, inExp3))
683 algorithm
684
685 10 e := Expression.expMul(inExp2, fa);
686 10 lhs := Expression.expSub(e, ga);
687 10 e := Expression.makeConstZero(tp);
688
689 then(lhs, e, true);
690
691 else (inExp1, inExp2, false);
692
693 end match;
694
695 end preprocessingSolve2;
696
697 protected function preprocessingSolve3
698 "
699 helprer function for preprocessingSolve
700
701 (r1)^f(a) = r2 => f(a) = ln(r2)/ln(r1)
702 f(a)^b = 0 => f(a) = 0
703 f(a)^n = c => f(a) = c^(1/n)
704 abs(x) = 0
705 author: Vitalij Ruge
706 "
707 input DAE.Exp inExp1 "lhs";
708 input DAE.Exp inExp2 "rhs";
709 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
710
711 output DAE.Exp olhs;
712 output DAE.Exp orhs;
713 output Boolean con "continue";
714
715 algorithm
716 (olhs, orhs, con) := match(inExp1, inExp2)
717 local
718 Real r, r1, r2;
719 DAE.Exp e1, e2, res;
720
721 // (r1)^f(a) = r2 => f(a) = ln(r2)/ln(r1)
722 case (DAE.BINARY(e1 as DAE.RCONST(r1),DAE.POW(_),e2), DAE.RCONST(r2))
723 guard r2 > 0.0 and r1 > 0.0 and (not Expression.isConstOne(e1)) and expHasCref(e2, inExp3)
724 algorithm
725 ✗ r := log(r2) / log(r1);
726 ✗ res := DAE.RCONST(r);
727 then
728 (e2, res, true);
729
730 // f(a)^b = 0 => f(a) = 0
731 case (DAE.BINARY(e1,DAE.POW(_),e2), DAE.RCONST(real = 0.0))
732 guard expHasCref(e1, inExp3) and (not expHasCref(e2, inExp3))
733 then
734 (e1, inExp2, true);
735
736 // f(a)^n = c => f(a) = c^(1/n)
737 // where n is odd
738 case (DAE.BINARY(e1,DAE.POW(_),e2 as DAE.RCONST(r)), _)
739 guard (not expHasCref(inExp2, inExp3)) and expHasCref(e1, inExp3) and (1.0 == realMod(r,2.0))
740 algorithm
741 40 res := Expression.makeDiv(DAE.RCONST(1.0),e2);
742 40 res := Expression.expPow(inExp2,res);
743 then
744 (e1, res, true);
745
746 // sqrt(f(a)) = f(a)^n = c => f(a) = c^(1/n)
747 case (DAE.BINARY(e1,DAE.POW(_),DAE.RCONST(0.5)), _)
748 guard not expHasCref(inExp2, inExp3) and expHasCref(e1, inExp3)
749 algorithm
750 4 res := Expression.expPow(inExp2,DAE.RCONST(2.0));
751 then
752 (e1, res, true);
753
754 // abs(x) = 0
755 case (DAE.CALL(path = Absyn.IDENT(name = "abs"),expLst = {e1}), DAE.RCONST(0.0))
756 then (e1,inExp2,true);
757
758 // sign(x) = 0
759 case (DAE.CALL(path = Absyn.IDENT(name = "sign"),expLst = {e1}), DAE.RCONST(0.0))
760 then (e1,inExp2,true);
761
762
763 else (inExp1, inExp2, false);
764
765 end match;
766
767
768 end preprocessingSolve3;
769
770
771 protected function preprocessingSolve4
772
773 "
774 helprer function for preprocessingSolve
775
776 e.g.
777 sqrt(f(x)) - sqrt(g(x))) = 0 = f(x) - g(x)
778 exp(f(x)) - exp(g(x))) = 0 = f(x) - g(x)
779
780 author: Vitalij Ruge
781 "
782
783 input DAE.Exp inExp1;
784 input DAE.Exp inExp2;
785 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
786 output DAE.Exp oExp1;
787 output DAE.Exp oExp2;
788 output Boolean newX;
789
790 algorithm
791
792 (oExp1, oExp2, newX) := match(inExp1, inExp2)
793 local
794 DAE.Exp e1,e2,e3,e4, e, e_1, e_2;
795 DAE.Type tp;
796
797 // exp(f(x)) - exp(g(x)) = 0
798 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("exp"), expLst={e1}), DAE.SUB(_),
799 DAE.CALL(path = Absyn.IDENT("exp"), expLst={e2})), DAE.RCONST(0.0))
800 then (e1, e2, true);
801
802 // log(f(x)) - log(g(x)) = 0
803 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("log"), expLst={e1}), DAE.SUB(_),
804 DAE.CALL(path = Absyn.IDENT("log"), expLst={e2})), DAE.RCONST(0.0))
805 then (e1, e2, true);
806
807 // log10(f(x)) - log10(g(x)) = 0
808 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("log10"), expLst={e1}), DAE.SUB(_),
809 DAE.CALL(path = Absyn.IDENT("log10"), expLst={e2})), DAE.RCONST(0.0))
810 then (e1, e2, true);
811
812 // sinh(f(x)) - sinh(g(x)) = 0
813 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e1}), DAE.SUB(_),
814 DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e2})), DAE.RCONST(0.0))
815 then (e1, e2, true);
816
817 // tanh(f(x)) - tanh(g(x)) = 0
818 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("tanh"), expLst={e1}), DAE.SUB(_),
819 DAE.CALL(path = Absyn.IDENT("tanh"), expLst={e2})), DAE.RCONST(0.0))
820 then (e1, e2, true);
821
822 // sqrt(f(x)) - sqrt(g(x)) = 0
823 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e1}), DAE.SUB(_),
824 DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e2})), DAE.RCONST(0.0))
825 then (e1, e2, true);
826
827 // sinh(f(x)) - cosh(g(x)) = 0
828 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e1}), DAE.SUB(_),
829 DAE.CALL(path = Absyn.IDENT("cosh"), expLst={e2})), DAE.RCONST(0.0))
830 guard ExpressionBasics.expEqual(e1,e2)
831 then (e1, inExp2, true);
832
833 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("cosh"), expLst={e1}), DAE.SUB(_),
834 DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e2})), DAE.RCONST(0.0))
835 guard ExpressionBasics.expEqual(e1,e2)
836 then (e1, inExp2, true);
837
838
839 // y*sinh(x) - z*cosh(x) = 0
840 case(DAE.BINARY(DAE.BINARY(e3,DAE.MUL(),DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e1})), DAE.SUB(tp),
841 DAE.BINARY(e4,DAE.MUL(),DAE.CALL(path = Absyn.IDENT("cosh"), expLst={e2}))), DAE.RCONST(0.0))
842 guard ExpressionBasics.expEqual(e1,e2)
843 algorithm
844 2 e := Expression.makePureBuiltinCall("tanh",{e1},tp);
845 2 then (Expression.expMul(e3,e), e4, true);
846
847 case(DAE.BINARY(DAE.BINARY(e4,DAE.MUL(),DAE.CALL(path = Absyn.IDENT("cosh"), expLst={e2})), DAE.SUB(tp),
848 DAE.BINARY(e3,DAE.MUL(),DAE.CALL(path = Absyn.IDENT("sinh"), expLst={e1}))), DAE.RCONST(0.0))
849 guard ExpressionBasics.expEqual(e1,e2)
850 algorithm
851 ✗ e := Expression.makePureBuiltinCall("tanh",{e1},tp);
852 ✗ then (Expression.expMul(e3,e), e4, true);
853
854
855
856 // sqrt(x) - x = 0 -> x = x^2
857 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e1}), DAE.SUB(_),e2), DAE.RCONST(0.0))
858 ✗ then (e1, Expression.expPow(e2, DAE.RCONST(2.0)), true);
859
860 case(DAE.BINARY(e2, DAE.SUB(_),DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e1})), DAE.RCONST(0.0))
861 1 then (e1, Expression.expPow(e2, DAE.RCONST(2.0)), true);
862
863 // f(x)^n - g(x)^n = 0 -> (f(x)/g(x))^n = 1
864 case(DAE.BINARY(DAE.BINARY(e1, DAE.POW(), e2), DAE.SUB(tp), DAE.BINARY(e3, DAE.POW(), e4)), DAE.RCONST(0.0))
865 guard ExpressionBasics.expEqual(e2,e4) and expHasCref(e1,inExp3) and expHasCref(e3,inExp3)
866 algorithm
867 2 e := Expression.expPow(Expression.makeDiv(e1,e3),e2);
868 2 (e_1, e_2, _) := preprocessingSolve3(e, Expression.makeConstOne(tp), inExp3);
869 2 then (e_1, e_2, true);
870
871 else (inExp1, inExp2, false);
872
873 end match;
874
875
876 end preprocessingSolve4;
877
878 protected function expAddX
879 "
880 helprer function for preprocessingSolve
881
882 if(y,g(x),h(x)) + x => if(y, g(x) + x, h(x) + x)
883 a*f(x) + b*f(x) = (a+b)*f(x)
884 author: Vitalij Ruge
885 "
886 input DAE.Exp inExp1 "lhs";
887 input DAE.Exp inExp2 "rhs";
888 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
889
890 output DAE.Exp ores;
891
892 algorithm
893 ores := matchcontinue(inExp1, inExp2)
894 local
895 DAE.Exp e, e1, e2, e3, e4, res;
896
897 case(DAE.IFEXP(e,e1,e2), _)
898 guard expHasCref(e1, inExp3) and expHasCref(e2, inExp3) and (not expHasCref(e, inExp3))
899 algorithm
900 1036 e3 := expAddX(inExp2, e1, inExp3);
901 1036 e4 := expAddX(inExp2, e2, inExp3);
902
903 1036 res := DAE.IFEXP(e, e3, e4);
904 then res;
905
906 case(_, DAE.IFEXP(e,e1,e2))
907 guard expHasCref(e1, inExp3) and expHasCref(e2, inExp3) and (not expHasCref(e, inExp3))
908 algorithm
909 476 e3 := expAddX(inExp1, e1, inExp3);
910 476 e4 := expAddX(inExp1, e2, inExp3);
911
912 476 res := DAE.IFEXP(e, e3, e4);
913 then res;
914
915 else
916 algorithm
917 365202 res := expAddX2(inExp1, inExp2, inExp3);
918 then res;
919
920 end matchcontinue;
921
922 end expAddX;
923
924 protected function expAddX2
925 "
926 helprer function for preprocessingSolve
927 a*f(x) + b*f(x) = (a+b)*f(x)
928 author: Vitalij Ruge
929 "
930 input DAE.Exp inExp1 "lhs";
931 input DAE.Exp inExp2 "rhs";
932 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
933
934 output DAE.Exp ores;
935
936 protected
937 list<DAE.Exp> f1, f2;
938 DAE.Exp e0,e1,e2;
939 Boolean neg;
940 list<DAE.Exp> factorWithX1, factorWithoutX1, factorWithX2, factorWithoutX2;
941 DAE.Exp pWithX1, pWithoutX1, pWithX2, pWithoutX2;
942
943 algorithm
944 (e0, e1, neg) := match inExp1
945 local DAE.Exp ee1, ee2;
946 case DAE.BINARY(ee1,DAE.ADD(),ee2)
947 then(ee1, ee2, false);
948 case DAE.BINARY(ee1,DAE.SUB(),ee2)
949 then(ee1, ee2, true);
950 else
951 then(DAE.RCONST(0.0), inExp1, false);
952 end match;
953
954 365202 f1 := Expression.expandFactors(e1);
955 365202 (factorWithX1, factorWithoutX1) := List.split1OnTrue(f1, expHasCref, inExp3);
956 365202 pWithX1 := makeProductLstSort(factorWithX1);
957 365202 pWithoutX1 := makeProductLstSort(factorWithoutX1);
958 365202 f2 := Expression.expandFactors(inExp2);
959 365202 (factorWithX2, factorWithoutX2) := List.split1OnTrue(f2, expHasCref, inExp3);
960 365202 (pWithX2,_) := ExpressionSimplify.simplify1(makeProductLstSort(factorWithX2));
961 365202 pWithoutX2 := makeProductLstSort(factorWithoutX2);
962 //print("\nf1 =");print(ExpressionDump.printExpListStr(f1));
963 //print("\nf2 =");print(ExpressionDump.printExpListStr(f2));
964
965
2/2
✓ Branch 1 taken 3530 times.
✓ Branch 2 taken 361672 times.
365202 if ExpressionBasics.expEqual(pWithX2,pWithX1) then
966 // e0 + a*x + b*x -> e0 + (a+b)*x
967
2/2
✓ Branch 0 taken 3525 times.
✓ Branch 1 taken 5 times.
3530 if not neg then
968 3525 ores := Expression.expAdd(pWithoutX1, pWithoutX2);
969 else
970 // e0 - a*x + b*x -> e0 + (b-a)*x
971 5 ores := Expression.expSub(pWithoutX2, pWithoutX1);
972 end if;
973 3530 ores := Expression.expMul(ores, pWithX2);
974 elseif ExpressionBasics.expEqual(pWithX2, Expression.negate(pWithX1)) then
975 // e0 + a*(-x) + b*x -> e0 + (b-a)*x
976 ✗ if not neg then
977 ✗ ores := Expression.expSub(pWithoutX2, pWithoutX1);
978 else
979 // e0 - a*(-x) + b*x -> e0 + (b-a)*x
980 ✗ ores := Expression.expAdd(pWithoutX1, pWithoutX2);
981 end if;
982 ✗ ores := Expression.expMul(ores, pWithX2);
983 else
984 361672 e1 := Expression.expMul(pWithoutX1, pWithX1);
985 361672 e2 := Expression.expMul(pWithoutX2, pWithX2);
986 361672 ores := Expression.expAdd(e1,e2);
987 end if;
988
989 365202 ores := Expression.expAdd(e0,ores);
990
991 end expAddX2;
992
993 public function collectX
994 input DAE.Exp inExp1 "lhs";
995 input DAE.Exp inExp3 "DAE.CREF";
996 input Boolean expand = true;
997 output DAE.Exp outLhs;
998 output DAE.Exp outRhs;
999 algorithm
1000 15 (outLhs, outRhs) := preprocessingSolve5(inExp1, inExp3, expand);
1001 end collectX;
1002
1003 protected function preprocessingSolve5
1004 "
1005 helprer function for preprocessingSolve
1006 split and sort with respect to x
1007 where x = cref
1008
1009 f(x,y) = {h(y)*g(x,y), k(y)}
1010
1011 author: Vitalij Ruge
1012 "
1013 input DAE.Exp inExp1 "lhs";
1014 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1015 input Boolean expand;
1016 output DAE.Exp outLhs;
1017 output DAE.Exp outRhs;
1018
1019 protected
1020 list<DAE.Exp> lhs, rhs;
1021 DAE.Exp tmpLhs, e1;
1022 Boolean b;
1023 DAE.ComponentRef cr;
1024 algorithm
1025
1026
2/2
✓ Branch 1 taken 180230 times.
✓ Branch 2 taken 181961 times.
362191 if expHasCref(inExp1, inExp3) then
1027
1028
2/2
✓ Branch 0 taken 180167 times.
✓ Branch 1 taken 63 times.
180230 if expand then
1029 180167 (cr, b) := Expression.expOrDerCref(inExp3);
1030
2/2
✓ Branch 0 taken 5052 times.
✓ Branch 1 taken 175115 times.
180167 if b then
1031 5052 (lhs, rhs) := Expression.allTermsForCref(inExp1, cr, Expression.expHasDerCref);
1032 else
1033 175115 (lhs, rhs) := Expression.allTermsForCref(inExp1, cr, Expression.expHasCrefNoPreOrStart);
1034 end if;
1035 else
1036 63 (lhs, rhs) := List.split1OnTrue(Expression.terms(inExp1), expHasCref, inExp3);
1037 end if;
1038
1039 // sort
1040 // a*f(x)*b -> c*f(x)
1041 outLhs := DAE.RCONST(0.0);
1042 tmpLhs := DAE.RCONST(0.0);
1043
2/2
✓ Branch 0 taken 183460 times.
✓ Branch 1 taken 180230 times.
363690 for e in lhs loop
1044
2/2
✓ Branch 1 taken 10645 times.
✓ Branch 2 taken 172815 times.
183460 if Expression.isNegativeUnary(e) then
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10645 times.
10645 DAE.UNARY(exp = e1) := e;
1046 10645 tmpLhs := expAddX(e1, tmpLhs, inExp3); // special add
1047 else
1048 172815 outLhs := expAddX(e, outLhs, inExp3); // special add
1049 end if;
1050 end for;
1051 180230 outLhs := expAddX(outLhs, Expression.negate(tmpLhs), inExp3);
1052 //rhs
1053 180230 outRhs := Expression.makeSum1(rhs);
1054 180230 (outRhs,_) := ExpressionSimplify.simplify1(outRhs);
1055 180230 (outLhs,_) := ExpressionSimplify.simplify1(outLhs);
1056
1057 else
1058 outLhs := DAE.RCONST(0.0);
1059 outRhs := inExp1;
1060 end if;
1061
1062 end preprocessingSolve5;
1063
1064 protected function unifyFunCalls
1065 "
1066 e.g.
1067 semiLinear() -> if
1068 author: Vitalij Ruge
1069 "
1070 input DAE.Exp inExp1 "lhs";
1071 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1072 output DAE.Exp oExp;
1073 output Boolean newX;
1074 algorithm
1075 35531 (oExp,_) := Expression.traverseExpTopDown(inExp1, unifyFunCallsWork, (inExp3));
1076 35531 newX := ExpressionBasics.expEqual(oExp, inExp1);
1077 end unifyFunCalls;
1078
1079 protected function unifyFunCallsWork
1080 input DAE.Exp inExp;
1081 input DAE.Exp iT;
1082 output DAE.Exp outExp;
1083 output Boolean cont;
1084 output DAE.Exp oT;
1085 algorithm
1086 (outExp,cont,oT) := match(inExp, iT)
1087 local
1088 DAE.Exp e, e1,e2,e3, X;
1089 DAE.Type tp;
1090 /*
1091 case(DAE.CALL(path = Absyn.IDENT(name = "smooth"), expLst = {_, e}),X)
1092 guard expHasCref(e, X)
1093 then (e, true, iT);
1094
1095 case(DAE.CALL(path = Absyn.IDENT(name = "noEvent"), expLst = {e}),X)
1096 guard expHasCref(e, X)
1097 then (e, true, iT);
1098 */
1099 case(DAE.CALL(path = Absyn.IDENT(name = "semiLinear"),expLst = {e1, e2, e3}),_)
1100 guard not Expression.isZero(e1)
1101 algorithm
1102 21 tp := Expression.typeof(e1);
1103 21 e := DAE.IFEXP(DAE.RELATION(e1,DAE.GREATEREQ(tp), Expression.makeConstZero(tp),-1,NONE()),Expression.expMul(e1,e2), Expression.expMul(e1,e3));
1104 then (e,true, iT);
1105
1106 // df_der(x) = (x-old(x))/dt
1107 case(DAE.CALL(path = Absyn.IDENT(name = "$_DF$DER"),expLst = {e1}),X)
1108 guard expHasCref(e1, X)
1109 algorithm
1110 ✗ tp := Expression.typeof(e1);
1111 ✗ e2 := Expression.crefExp(ComponentReferenceBasics.makeCrefIdent(BackendDAE.symSolverDT, DAE.T_REAL_DEFAULT, {}));
1112 ✗ e3 := Expression.makePureBuiltinCall("pre", {e1}, tp);
1113 ✗ e3 := Expression.expSub(e1,e3);
1114 ✗ e := Expression.expDiv(e3,e2);
1115 then (e,true, iT);
1116
1117 else (inExp, true, iT);
1118 end match;
1119
1120 end unifyFunCallsWork;
1121
1122
1123 protected function solveFunCalls
1124 "
1125 - inline modelica functions
1126 - TODO: support annotation inverse
1127 author: Vitalij Ruge
1128 "
1129 input DAE.Exp inExp1 "lhs";
1130 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1131 input Option<AvlTreePathFunction.Tree> functions;
1132 output DAE.Exp x;
1133 output Boolean con;
1134 algorithm
1135 (x,con) := matchcontinue inExp1
1136 local DAE.Exp funX; Boolean b;
1137 case _
1138 algorithm
1139 507 (funX,_) := Expression.traverseExpTopDown(inExp1, inlineCallX, (inExp3, functions));
1140 507 b := not ExpressionBasics.expEqual(funX, inExp1);
1141 then (funX, b);
1142 else (inExp1, false);
1143 end matchcontinue;
1144 end solveFunCalls;
1145
1146 protected function removeSimpleCalls
1147 "
1148 helprer function for preprocessingSolve
1149
1150 solve e.g.
1151 exp(x) = y
1152 log(x) = y
1153 "
1154 input DAE.Exp inExp1 "lhs";
1155 input DAE.Exp inExp2 "rhs";
1156 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1157
1158 output DAE.Exp outLhs;
1159 output DAE.Exp outRhs;
1160 output Boolean con "continue";
1161 algorithm
1162 (outLhs, outRhs, con) := match inExp1
1163 9224 case DAE.CALL() then removeSimpleCalls2(inExp1, inExp2, inExp3);
1164 5586 else (inExp1, inExp2, false);
1165 end match;
1166 end removeSimpleCalls;
1167
1168
1169 protected function removeSimpleCalls2
1170 "
1171 helprer function for preprocessingSolve
1172
1173 solve e.g.
1174 exp(x) = y
1175 log(x) = y
1176 "
1177 input DAE.Exp inExp1 "lhs";
1178 input DAE.Exp inExp2 "rhs";
1179 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1180
1181 output DAE.Exp outLhs;
1182 output DAE.Exp outRhs;
1183 output Boolean con "continue";
1184 algorithm
1185 (outLhs, outRhs, con) := matchcontinue (inExp1, inExp2)
1186 local
1187 DAE.Exp e1, e2, e3;
1188
1189
1190 //tanh(x) =y -> x = 1/2 * ln((1+y)/(1-y))
1191 case (DAE.CALL(path = Absyn.IDENT(name = "tanh"),expLst = {e1}), _)
1192 algorithm
1193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 true := expHasCref(e1, inExp3);
1194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 false := expHasCref(inExp2, inExp3);
1195
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
12 true := not(Expression.isCref(inExp2) or Expression.isConst(inExp2));
1196 12 e2 := Expression.expAdd(DAE.RCONST(1.0), inExp2);
1197 12 e3 := Expression.expSub(DAE.RCONST(1.0), inExp2);
1198 12 e2 := Expression.makeDiv(e2, e3);
1199 12 e2 := Expression.makePureBuiltinCall("log",{e2},DAE.T_REAL_DEFAULT);
1200 12 e2 := Expression.expMul(DAE.RCONST(0.5), e2);
1201 then (e1, e2, true);
1202 // sinh(x) -> ln(y+(sqrt(1+y^2))
1203 case (DAE.CALL(path = Absyn.IDENT(name = "sinh"),expLst = {e1}), _)
1204 algorithm
1205 ✗ true := expHasCref(e1, inExp3);
1206 ✗ false := expHasCref(inExp2, inExp3);
1207 ✗ true := not(Expression.isCref(inExp2) or Expression.isConst(inExp2));
1208 ✗ e2 := Expression.expPow(inExp2, DAE.RCONST(2.0));
1209 ✗ e3 := Expression.expAdd(e2,DAE.RCONST(1.0));
1210 ✗ e2 := Expression.makePureBuiltinCall("sqrt",{e3},DAE.T_REAL_DEFAULT);
1211 ✗ e3 := Expression.expAdd(inExp2, e2);
1212 ✗ e2 := Expression.makePureBuiltinCall("log",{e3},DAE.T_REAL_DEFAULT);
1213 then (e1,e2,true);
1214
1215 // log10(f(a)) = g(b) => f(a) = 10^(g(b))
1216 case (DAE.CALL(path = Absyn.IDENT(name = "log10"),expLst = {e1}), _)
1217 algorithm
1218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 true := expHasCref(e1, inExp3);
1219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 false := expHasCref(inExp2, inExp3);
1220 6 e2 := Expression.expPow(DAE.RCONST(10.0), inExp2);
1221 then (e1, e2, true);
1222 // log(f(a)) = g(b) => f(a) = exp(g(b))
1223 case (DAE.CALL(path = Absyn.IDENT(name = "log"),expLst = {e1}), _)
1224 algorithm
1225
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 true := expHasCref(e1, inExp3);
1226
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 false := expHasCref(inExp2, inExp3);
1227 43 e2 := Expression.makePureBuiltinCall("exp",{inExp2},DAE.T_REAL_DEFAULT);
1228 then (e1, e2, true);
1229 // exp(f(a)) = g(b) => f(a) = log(g(b))
1230 case (DAE.CALL(path = Absyn.IDENT(name = "exp"),expLst = {e1}), _)
1231 algorithm
1232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 true := expHasCref(e1, inExp3);
1233
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 false := expHasCref(inExp2, inExp3);
1234 30 e2 := Expression.makePureBuiltinCall("log",{inExp2},DAE.T_REAL_DEFAULT);
1235 then (e1, e2, true);
1236 // sqrt(f(a)) = g(b) => f(a) = (g(b))^2
1237 case (DAE.CALL(path = Absyn.IDENT(name = "sqrt"),expLst = {e1}), _)
1238 algorithm
1239
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 true := expHasCref(e1, inExp3);
1240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 false := expHasCref(inExp2, inExp3);
1241 e2 := DAE.RCONST(2.0);
1242 26 e2 := Expression.expPow(inExp2,e2);
1243 then (e1, e2, true);
1244 // semiLinear(0, a, b) = 0 => a = b // rule 1
1245 case (DAE.CALL(path = Absyn.IDENT(name = "semiLinear"),expLst = {DAE.RCONST(real = 0.0), e1, e2}), DAE.RCONST(real = 0.0))
1246 then (e1,e2,true);
1247 // smooth(i,f(a)) = rhs -> f(a) = rhs
1248 //case (DAE.CALL(path = Absyn.IDENT(name = "smooth"),expLst = {_, e2}),_,_)
1249 // then (e2, inExp2, true);
1250 // noEvent(f(a)) = rhs -> f(a) = rhs
1251 //case (DAE.CALL(path = Absyn.IDENT(name = "noEvent"),expLst = {e2}),_,_)
1252 // then (e2, inExp2, true);
1253
1254 else (inExp1, inExp2, false);
1255 end matchcontinue;
1256 end removeSimpleCalls2;
1257
1258 protected function inlineCallX
1259 "
1260 inline function call if depends on X where X is cref or der(cref)
1261 DAE.Exp inExp2 DAE.CREF or 'der(DAE.CREF())'
1262 author: vitalij
1263 "
1264 input DAE.Exp inExp;
1265 input tuple<DAE.Exp, Option<AvlTreePathFunction.Tree>> iT;
1266 output DAE.Exp outExp;
1267 output Boolean cont;
1268 output tuple<DAE.Exp, Option<AvlTreePathFunction.Tree>> oT;
1269 algorithm
1270 (outExp,cont,oT) := matchcontinue(inExp, iT)
1271 local
1272 DAE.Exp e, X;
1273 Option<AvlTreePathFunction.Tree> functions;
1274 Boolean b;
1275
1276 case(DAE.CALL(),(X, functions))
1277 guard expHasCref(inExp, X)
1278 algorithm
1279 //print("\nfIn: ");print(ExpressionBasics.printExpStr(inExp));
1280 372 (e,_,b) := Inline.forceInlineExp(inExp,(functions,{DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}),DAE.emptyElementSource,Ceval.cevalSimpleWithFunctionTreeReturnExp);
1281 //print("\nfOut: ");print(ExpressionBasics.printExpStr(e));
1282 372 then (e, not b, iT);
1283 else (inExp, true, iT);
1284 end matchcontinue;
1285 end inlineCallX;
1286
1287 protected function preprocessingSolveTmpVars
1288 "
1289 helper function for solveWork
1290 creat tmp vars if needed!
1291 e.g. for solve abs
1292 "
1293 input DAE.Exp inExp1;
1294 input DAE.Exp inExp2;
1295 input DAE.Exp inExp3;
1296 input Option<DAE.Exp> optCond "condition from an if expression";
1297 input Integer uniqueEqIndex "offset for tmp vars";
1298 input list<BackendDAE.Equation> ieqnForNewVars;
1299 input list<DAE.ComponentRef> inewVarsCrefs;
1300 input Integer idepth "depth of tmp var";
1301 output DAE.Exp x;
1302 output DAE.Exp y;
1303 output Boolean new_x;
1304 output list<BackendDAE.Equation> eqnForNewVars "eqn for tmp vars";
1305 output list<DAE.ComponentRef> newVarsCrefs;
1306 output Integer odepth;
1307 algorithm
1308 (x, y, new_x, eqnForNewVars, newVarsCrefs, odepth) := matchcontinue inExp1
1309 local
1310 DAE.Exp arg, e1, e_1, e2, exP, lhs, e3, e5, e6, rhs, a1,x1, a2,x2, ee1, ee2;
1311 list<DAE.Exp> z1, z2, z3, z4;
1312 DAE.Type tp;
1313 list<BackendDAE.Equation> eqnForNewVars_;
1314 list<DAE.ComponentRef> newVarsCrefs_;
1315 DAE.Operator op1;
1316 String name;
1317
1318 // try to invert a function call
1319 // f(x) = y -> x = f^(-1)(y)
1320 case DAE.CALL(path = Absyn.IDENT(name = name),expLst = {arg})
1321 guard expHasCref(arg, inExp3) and not expHasCref(inExp2, inExp3)
1322 algorithm
1323 103 (y, new_x, eqnForNewVars_, newVarsCrefs_, odepth) := preprocessingSolveFunctionCall(name, arg, inExp2, inExp3, optCond, uniqueEqIndex, idepth);
1324
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if listEmpty(eqnForNewVars_) then
1326 ✗ eqnForNewVars_ := ieqnForNewVars;
1327 else
1328 eqnForNewVars_ := match optCond
1329 local
1330 DAE.Exp cond;
1331 case SOME(cond)
1332 8 then BackendDAE.IF_EQUATION({cond}, {eqnForNewVars_}, {}, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN) :: ieqnForNewVars;
1333 95 else listAppend(eqnForNewVars_, ieqnForNewVars);
1334 end match;
1335 end if;
1336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 then (if new_x then arg else inExp1, y, new_x, eqnForNewVars_, listAppend(newVarsCrefs_, inewVarsCrefs), odepth);
1337
1338 // x^n = y -> x = y^(1/n)
1339 case DAE.BINARY(e1, DAE.POW(tp), e2)
1340 guard expHasCref(e1, inExp3) and not expHasCref(e2, inExp3)
1341 algorithm
1342 100 tp := Expression.typeof(e1);
1343 100 exP := makeInitialGuess(tp, inExp3, e1);
1344 // exP := makeInitialGuess(tp, inExp3, inExp2);
1345 100 (exP, eqnForNewVars_, newVarsCrefs_) := makeTmpEqnAndCrefFromExp(exP, tp, "X$ABS", uniqueEqIndex, idepth, ieqnForNewVars, inewVarsCrefs, false);
1346 100 e_1 := Expression.makePureBuiltinCall("$_signNoNull", {exP}, tp); // sign
1347
1348 100 lhs := Expression.expPow(inExp2, Expression.inverseFactors(e2)); // y^(1/n)
1349 100 lhs := Expression.makePureBuiltinCall("abs", {lhs}, tp); // abs(y^(1/n))
1350 //lhs := Expression.makePureBuiltinCall("abs", {inExp2}, tp); // abs(y)
1351 //lhs := Expression.expPow(lhs, Expression.inverseFactors(e2)); // abs(y)^(1/n)
1352 100 lhs := Expression.expMul(e_1, lhs); // sign*abs(y^(1/n))
1353 100 then(e1, lhs, true, eqnForNewVars_, newVarsCrefs_, idepth + 1);
1354
1355 //QE
1356 // a*x^n + b*x^m = c
1357 // a*x^n - b*x^m = c
1358 case DAE.BINARY(ee1, op1, ee2)
1359 guard(Expression.isAddOrSub(op1))
1360 algorithm
1361 704 (z1, z2) := List.split1OnTrue(Expression.factors(ee1), expHasCref, inExp3);
1362 704 (z3, z4) := List.split1OnTrue(Expression.factors(ee2), expHasCref, inExp3);
1363
1364 704 x1 := makeProductLstSort(z1);
1365 704 a1 := makeProductLstSort(z2);
1366
1367 704 x2 := makeProductLstSort(z3);
1368
2/2
✓ Branch 1 taken 224 times.
✓ Branch 2 taken 480 times.
704 a2 := if Expression.isAdd(op1) then makeProductLstSort(z4) else Expression.negate(makeProductLstSort(z4));
1369 704 (e2, e3) := simplifyBinaryMulCoeff(x1);
1370 704 (e5, e6) := simplifyBinaryMulCoeff(x2);
1371 704 (lhs, rhs, eqnForNewVars_, newVarsCrefs_) := solveQE(a1,e2,e3,a2,e5,e6,inExp2,inExp3,ieqnForNewVars,inewVarsCrefs,uniqueEqIndex,idepth);
1372 56 then(lhs, rhs, true, eqnForNewVars_, newVarsCrefs_, idepth + 1);
1373
1374 else (inExp1, inExp2, false, ieqnForNewVars, inewVarsCrefs, idepth);
1375 end matchcontinue;
1376 end preprocessingSolveTmpVars;
1377
1378 protected function preprocessingSolveFunctionCall
1379 input String name "of the function";
1380 input DAE.Exp arg "ument of the function";
1381 input DAE.Exp rhs;
1382 input DAE.Exp inExp3 "solve for this";
1383 input Option<DAE.Exp> optCond "condition from an if expression";
1384 input Integer uniqueEqIndex "offset for tmp vars";
1385 input Integer idepth "depth of tmp var";
1386 output DAE.Exp result;
1387 output Boolean new_x;
1388 output list<BackendDAE.Equation> newEqns "eqns for tmp vars";
1389 output list<DAE.ComponentRef> newVars "tmp vars";
1390 output Integer odepth;
1391 algorithm
1392 (result, new_x, newEqns, newVars, odepth) := match name
1393 local
1394 DAE.Exp y, exP, sgn, inv, e1, e2, k1, k2, x1, x2;
1395 DAE.Type tp;
1396 list<BackendDAE.Equation> eqns;
1397 list<DAE.ComponentRef> vars;
1398 BackendDAE.Equation ass "assertion for finding domain violations";
1399
1400 // tanh(x) -> 0.5 * ln((1 + y)/(1 - y))
1401 // exists for y in (-1, 1)
1402 // unique
1403 case "tanh" algorithm
1404 ✗ tp := Expression.typeof(rhs);
1405 ✗ (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$TANH", uniqueEqIndex, idepth, {}, {}, false);
1406 ✗ e1 := Expression.expAdd(DAE.RCONST(1.0), y); // 1 + y
1407 ✗ e2 := Expression.expSub(DAE.RCONST(1.0), y); // 1 - y
1408 ✗ e1 := Expression.makeDiv(e1, e2); // (1 + y)/(1 - y)
1409 ✗ e1 := Expression.makePureBuiltinCall("log", {e1}, tp); // ln((1 + y)/(1 - y))
1410 ✗ inv := Expression.expMul(DAE.RCONST(0.5), e1); // 0.5 * ln((1 + y)/(1 - y))
1411 ✗ ass := makeDomainAssert(name, rhs, SOME((-1.0, false)), SOME((1.0, false))); // y in (-1, 1)
1412 ✗ then (inv, true, ass :: eqns, vars, idepth + 1);
1413
1414 // sinh(x) -> ln(y + sqrt(y^2 + 1))
1415 // exixts always
1416 // unique
1417 case "sinh" algorithm
1418 ✗ tp := Expression.typeof(rhs);
1419 ✗ (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$SINH", uniqueEqIndex, idepth, {}, {}, false);
1420 ✗ e1 := Expression.expPow(y, DAE.RCONST(2.0)); // y^2
1421 ✗ e1 := Expression.expAdd(e1, DAE.RCONST(1.0)); // y^2 + 1
1422 ✗ e1 := Expression.makePureBuiltinCall("sqrt", {e1}, tp); // sqrt(y^2 + 1)
1423 ✗ e1 := Expression.expAdd(y, e1); // y + sqrt(y^2 + 1)
1424 ✗ e1 := Expression.makePureBuiltinCall("log", {e1}, tp); // ln(y + sqrt(y^2 + 1))
1425 ✗ then (e1, true, eqns, vars, idepth + 1);
1426
1427 // cosh(x) -> ln(y + sign*sqrt(y^2 - 1))
1428 // exists for y in [1, inf)
1429 // two values, sign is -1 or 1
1430 case "cosh" algorithm
1431 4 tp := Expression.typeof(rhs);
1432 4 (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$COSH", uniqueEqIndex, idepth, {}, {}, false);
1433
1434 4 exP := makeInitialGuess(tp, inExp3, arg);
1435 4 (exP, eqns, vars) := makeTmpEqnAndCrefFromExp(exP, tp, "SIGN$COSH", uniqueEqIndex, idepth, eqns, vars, false);
1436 4 sgn := Expression.makePureBuiltinCall("$_signNoNull", {exP}, tp); // sign
1437
1438 4 e1 := Expression.expPow(y, DAE.RCONST(2.0)); // y^2
1439 4 e1 := Expression.expSub(e1, DAE.RCONST(1.0)); // y^2 - 1
1440 4 e1 := Expression.makePureBuiltinCall("sqrt", {e1}, tp); // sqrt(y^2 - 1)
1441 4 e1 := Expression.expMul(sgn, e1); // sign*sqrt(y^2 - 1)
1442 4 e1 := Expression.expAdd(y, e1); // y + sign*sqrt(y^2 - 1)
1443 4 e1 := Expression.makePureBuiltinCall("log", {e1}, tp); // ln(y + sign*sqrt(y^2 - 1))
1444
1445 4 ass := makeDomainAssert(name, rhs, SOME((1.0, true)), NONE()); // y in [1, inf)
1446 4 then (e1, true, ass :: eqns, vars, idepth + 1);
1447
1448 // cos(x) -> sign*acos(y) + 2*pi*k
1449 // exists for y in [-1, 1]
1450 // infinitely many values, k is integer, sign is -1 or 1
1451 case "cos" algorithm
1452 33 tp := Expression.typeof(rhs);
1453 33 (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$COS", uniqueEqIndex, idepth, {}, {}, false);
1454
1455 33 inv := Expression.makePureBuiltinCall("acos", {y}, tp);
1456 33 (inv, eqns, vars) := makeTmpEqnAndCrefFromExp(inv, tp, "INV$COS", uniqueEqIndex, idepth, eqns, vars, false);
1457
1458 33 exP := makeInitialGuess(tp, inExp3, arg);
1459 33 (exP, eqns, vars) := makeTmpEqnAndCrefFromExp(exP, tp, "PREX$COS", uniqueEqIndex, idepth, eqns, vars, false);
1460
1461 33 k1 := helpInvCos(inv, exP, tp, true);
1462 33 k2 := helpInvCos(inv, exP, tp, false);
1463 33 (k1, eqns, vars) := makeTmpEqnAndCrefFromExp(k1, tp, "k1$COS", uniqueEqIndex, idepth, eqns, vars, false);
1464 33 (k2, eqns, vars) := makeTmpEqnAndCrefFromExp(k2, tp, "k2$COS", uniqueEqIndex, idepth, eqns, vars, false);
1465
1466 33 x1 := helpInvCos2(k1, inv, tp, true);
1467 33 x2 := helpInvCos2(k2, inv, tp, false);
1468 33 (x1, eqns, vars) := makeTmpEqnAndCrefFromExp(x1, tp, "x1$COS", uniqueEqIndex, idepth, eqns, vars, false);
1469 33 (x2, eqns, vars) := makeTmpEqnAndCrefFromExp(x2, tp, "x2$COS", uniqueEqIndex, idepth, eqns, vars, false);
1470 33 e1 := helpInvCos3(x1, x2, exP, tp);
1471
1472 33 ass := makeDomainAssert(name, rhs, SOME((-1.0, true)), SOME((1.0, true))); // y in [-1, 1]
1473 33 then (e1, true, ass :: eqns, vars, idepth + 1);
1474
1475 // sin(x) -> (-1)^k * asin(y) + k*pi
1476 // exists for y in [-1, 1]
1477 // infinitely many values, k is integer
1478 case "sin" algorithm
1479 27 tp := Expression.typeof(rhs);
1480 27 (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$SIN", uniqueEqIndex, idepth, {}, {}, false);
1481
1482 27 inv := Expression.makePureBuiltinCall("asin", {y}, tp);
1483 27 (inv, eqns, vars) := makeTmpEqnAndCrefFromExp(inv, tp, "INV$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1484
1485 27 exP := makeInitialGuess(tp,inExp3,arg);
1486 27 (exP, eqns, vars) := makeTmpEqnAndCrefFromExp(exP, tp, "PREX$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1487
1488 27 k1 := helpInvSin(inv, arg, tp, true);
1489 27 k2 := helpInvSin(inv, arg, tp, false);
1490 27 (k1, eqns, vars) := makeTmpEqnAndCrefFromExp(k1, tp, "k1$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1491 27 (k2, eqns, vars) := makeTmpEqnAndCrefFromExp(k2, tp, "k2$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1492
1493 27 x1 := helpInvSin2(k1, inv, tp, true);
1494 27 x2 := helpInvSin2(k2, inv, tp, false);
1495 27 (x1, eqns, vars) := makeTmpEqnAndCrefFromExp(x1, tp, "x1$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1496 27 (x2, eqns, vars) := makeTmpEqnAndCrefFromExp(x2, tp, "x2$SIN", uniqueEqIndex, idepth, eqns, vars, false);
1497
1498 27 e1 := helpInvCos3(x1, x2, exP, tp);
1499
1500 27 ass := makeDomainAssert(name, rhs, SOME((-1.0, true)), SOME((1.0, true))); // y in [-1, 1]
1501 27 then (e1, true, ass :: eqns, vars, idepth + 1);
1502
1503 // tan(x) -> atan(y) + k*pi
1504 // exists always
1505 // infinitely many values, k is integer
1506 case "tan" algorithm
1507 5 tp := Expression.typeof(rhs);
1508 5 (y, eqns, vars) := makeTmpEqnAndCrefFromExp(rhs, tp, "Y$TAN", uniqueEqIndex, idepth, {}, {}, false);
1509
1510 5 inv := Expression.makePureBuiltinCall("atan", {y}, tp);
1511 5 (inv, eqns, vars) := makeTmpEqnAndCrefFromExp(inv, tp, "INV$TAN", uniqueEqIndex, idepth, eqns, vars, false);
1512
1513 5 exP := makeInitialGuess(tp, inExp3, arg);
1514 5 (exP, eqns, vars) := makeTmpEqnAndCrefFromExp(exP, tp, "PREX$TAN", uniqueEqIndex, idepth, eqns, vars, false);
1515
1516 5 k1 := Expression.expSub(exP, inv); // pre(x) - atan(y)
1517 5 k1 := Expression.makeDiv(k1, DAE.PI); // (pre(x) - atan(y))/pi
1518 5 k1 := Expression.makePureBuiltinCall("$_round", {k1}, tp); // k = round((pre(x) - atan(y))/pi)
1519 5 e1 := Expression.expMul(k1, DAE.PI); // k*pi
1520 5 e1 := Expression.expAdd(inv, e1); // atan(y) + pi*k
1521 5 then (e1, true, eqns, vars, idepth + 1);
1522
1523 // abs(x) -> sign*y
1524 // exists for y in [0, inf)
1525 // two values, sign is -1 or 1
1526 case "abs" algorithm
1527 34 tp := Expression.typeof(arg);
1528 34 exP := makeInitialGuess(tp, inExp3, arg);
1529 34 (exP, eqns, vars) := makeTmpEqnAndCrefFromExp(exP, tp, "SIGN$ABS", uniqueEqIndex, idepth, {}, {}, false);
1530 34 sgn := Expression.makePureBuiltinCall("$_signNoNull", {exP}, tp); // sign
1531 34 e1 := Expression.expMul(sgn, rhs); // sign*y
1532 34 ass := makeDomainAssert(name, rhs, SOME((0.0, true)), NONE()); // y in [0, inf)
1533 34 then (e1, true, ass ::eqns, vars, idepth + 1);
1534
1535 // sqrt(x) -> y^2
1536 // exists for y in [0, inf)
1537 // unique
1538 case "sqrt" algorithm
1539 ✗ inv := Expression.expPow(rhs, DAE.RCONST(2.0)); // y^2
1540 ✗ ass := makeDomainAssert(name, rhs, SOME((0.0, true)), NONE()); // y in [0, inf)
1541 ✗ then (inv, true, {ass}, {}, idepth + 1);
1542
1543 // asin(x) -> sin(y)
1544 // exists for y in [-pi/2, pi/2]
1545 // unique
1546 case "asin" algorithm
1547 ✗ tp := Expression.typeof(rhs);
1548 ✗ inv := Expression.makePureBuiltinCall("sin", {rhs}, tp); // sin(y)
1549 ✗ ass := makeDomainAssert(name, rhs, SOME((-0.5*Expression.toReal(DAE.PI), true)), SOME((0.5*Expression.toReal(DAE.PI), true))); // y in [-pi/2, pi/2]
1550 ✗ then (inv, true, {ass}, {}, idepth + 1);
1551
1552 // acos(x) -> cos(y)
1553 // exists for y in [0, pi]
1554 // unique
1555 case "acos" algorithm
1556 ✗ tp := Expression.typeof(rhs);
1557 ✗ inv := Expression.makePureBuiltinCall("cos", {rhs}, tp); // cos(y)
1558 ✗ ass := makeDomainAssert(name, rhs, SOME((0.0, true)), SOME((Expression.toReal(DAE.PI), true))); // y in [0, pi]
1559 ✗ then (inv, true, {ass}, {}, idepth + 1);
1560
1561 // atan(x) -> tan(y)
1562 // exists for y in [-pi/2, pi/2]
1563 // unique
1564 case "atan" algorithm
1565 ✗ tp := Expression.typeof(rhs);
1566 ✗ inv := Expression.makePureBuiltinCall("tan", {rhs}, tp); // tan(y)
1567 ✗ ass := makeDomainAssert(name, rhs, SOME((-0.5*Expression.toReal(DAE.PI), true)), SOME((0.5*Expression.toReal(DAE.PI), true))); // y in [-pi/2, pi/2]
1568 ✗ then (inv, true, {ass}, {}, idepth + 1);
1569
1570 // exp(x) -> log(y)
1571 // exists for y in (0, inf)
1572 // unique
1573 case "exp" algorithm
1574 ✗ tp := Expression.typeof(rhs);
1575 ✗ inv := Expression.makePureBuiltinCall("log", {rhs}, tp); // log(y)
1576 ✗ ass := makeDomainAssert(name, rhs, SOME((0.0, false)), NONE()); // y in (0, inf)
1577 ✗ then (inv, true, {ass}, {}, idepth + 1);
1578
1579 // log(x) -> exp(y)
1580 // exists always
1581 // unique
1582 case "log" algorithm
1583 ✗ tp := Expression.typeof(rhs);
1584 ✗ inv := Expression.makePureBuiltinCall("exp", {rhs}, tp); // exp(y)
1585 ✗ then (inv, true, {}, {}, idepth + 1);
1586
1587 // log10(x) -> 10^y
1588 // exists always
1589 // unique
1590 case "log10" algorithm
1591 ✗ inv := Expression.expPow(DAE.RCONST(10.0), rhs); // 10^y
1592 ✗ then (inv, true, {}, {}, idepth + 1);
1593
1594 // sign(x) is not invertible
1595 case "sign" then (rhs, false, {}, {}, idepth);
1596
1597 // $_DF$DER(x) = y -> (x - pre(x))/dt = y -> x = y*dt + pre(x)
1598 case "$_DF$DER" algorithm
1599 ✗ e1 := Expression.crefExp(ComponentReferenceBasics.makeCrefIdent(BackendDAE.symSolverDT, DAE.T_REAL_DEFAULT, {})); // dt
1600 ✗ exP := Expression.makePureBuiltinCall("pre", {arg}, Expression.typeof(arg)); // pre(x)
1601 ✗ e1 := Expression.expAdd(Expression.expMul(rhs, e1), exP); // y*dt + pre(x)
1602 ✗ then(e1, true, {}, {}, idepth + 1);
1603
1604 // don't know inverse of this function
1605 else (rhs, false, {}, {}, idepth);
1606 end match;
1607 end preprocessingSolveFunctionCall;
1608
1609 protected function simplifyBinaryMulCoeff
1610 "generalization of ExpressionSimplify.simplifyBinaryMulCoeff2"
1611 input DAE.Exp inExp;
1612 output DAE.Exp exp1;
1613 output DAE.Exp exp2;
1614 algorithm
1615 (exp1, exp2) := match inExp
1616 local
1617 DAE.Exp e,e1,e2;
1618 DAE.Exp coeff;
1619
1620 case e as DAE.CREF()
1621 then ((e, DAE.RCONST(1.0)));
1622
1623 case DAE.BINARY(exp1 = e1,operator = DAE.POW(),exp2 = DAE.UNARY(operator = DAE.UMINUS(), exp = coeff))
1624 ✗ then
1625 ((e1, Expression.negate(coeff)));
1626
1627 case DAE.BINARY(exp1 = e1,operator = DAE.POW(),exp2 = coeff)
1628 then ((e1,coeff));
1629
1630 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2)
1631 guard(ExpressionBasics.expEqual(e1, e2))
1632 then
1633 ((e1, DAE.RCONST(2.0)));
1634
1635 case DAE.BINARY(e1, DAE.DIV(), e2)
1636 guard(Expression.isOne(e1))
1637 then(e2, DAE.RCONST(-1.0));
1638
1639 case DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e})
1640 then ((e,DAE.RCONST(0.5)));
1641
1642 else ((inExp,DAE.RCONST(1.0)));
1643
1644 end match;
1645 end simplifyBinaryMulCoeff;
1646
1647 protected function solveQE
1648 "
1649 solve Quadratic equation with respect to inExp3
1650 IN: a,x,n,b,y,m
1651 where solve a*x^n + b*y^m = inExp2 with 2*m = n or 2*n = m and y = x
1652
1653 author: Vitalij Ruge
1654 "
1655 input DAE.Exp e1,e2,e3,e4,e5,e6;
1656 input DAE.Exp inExp2;
1657 input DAE.Exp inExp3;
1658
1659 input list<BackendDAE.Equation> ieqnForNewVars "eqn for tmp vars";
1660 input list<DAE.ComponentRef> inewVarsCrefs "cref for tmp vars";
1661 input Integer uniqueEqIndex, idepth "need for tmp vars";
1662
1663 output DAE.Exp rhs;
1664 output DAE.Exp lhs;
1665 output list<BackendDAE.Equation> eqnForNewVars;
1666 output list<DAE.ComponentRef> newVarsCrefs;
1667
1668 protected
1669 DAE.Exp e7, con, invExp, x1, x2, x, exP;
1670 DAE.Exp a,b,c, n, sgnb, b2, ac, sExp1, sExp2;
1671 DAE.Type tp;
1672 Boolean b1, b3;
1673 algorithm
1674
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 704 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
704 false := Expression.isZero(e1) and Expression.isZero(e2);
1675
2/2
✓ Branch 1 taken 644 times.
✓ Branch 2 taken 60 times.
704 true := ExpressionBasics.expEqual(e2,e5);
1676 60 b1 := ExpressionBasics.expEqual(e3, Expression.expMul(DAE.RCONST(2.0),e6));
1677 60 b3 := ExpressionBasics.expEqual(e6, Expression.expMul(DAE.RCONST(2.0),e3));
1678
1679
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 56 times.
60 true := b1 or b3;
1680
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 false := expHasCref(e1, inExp3);
1681
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 true := expHasCref(e2, inExp3);
1682
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 false := expHasCref(e3, inExp3);
1683
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 false := expHasCref(e4, inExp3);
1684
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 true := expHasCref(e5, inExp3);
1685
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 false := expHasCref(e6, inExp3);
1686
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 false := expHasCref(inExp2, inExp3);
1687
1688
1689
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 6 times.
56 a := if b1 then e1 else e4;
1690
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 6 times.
56 b := if b1 then e4 else e1;
1691 56 c := Expression.negate(inExp2);
1692
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 6 times.
56 n := if b1 then e6 else e3;
1693
1694 56 tp := Expression.typeof(a);
1695 56 (a, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(a, tp, "a$QE", uniqueEqIndex, idepth, ieqnForNewVars, inewVarsCrefs, false);
1696 56 con := DAE.RELATION(a,DAE.EQUAL(tp),DAE.RCONST(0.0),-1,NONE());
1697
1698 56 tp := Expression.typeof(b);
1699 56 (b, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(b, tp, "b$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1700 56 sgnb := Expression.makePureBuiltinCall("$_signNoNull",{b},tp);
1701 56 b2 := Expression.expPow(b, DAE.RCONST(2.0));
1702 56 (b2, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(b2, tp, "bPow2$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1703
1704 56 tp := Expression.typeof(c);
1705 56 (c, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(c, tp, "c$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1706 56 ac := Expression.expMul(a,c);
1707 56 ac := Expression.expMul(DAE.RCONST(4.0),ac);
1708
1709 56 sExp1 := Expression.expSub(b2,ac);
1710 56 sExp2 := Expression.makePureBuiltinCall("sqrt",{sExp1},tp);
1711 56 sExp2 := Expression.expMul(sgnb, sExp2);
1712
1713
1714 56 a := DAE.IFEXP(con, Expression.makeConstOne(tp), a);
1715 56 (a, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(a, tp, "a1$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1716
1717 56 x1 := Expression.expAdd(b, sExp2);
1718 56 x1 := Expression.makeDiv(x1, a);
1719 56 x1 := Expression.expMul(DAE.RCONST(-0.5), x1);
1720 56 tp := Expression.typeof(x1);
1721 56 x1 := DAE.IFEXP(con, Expression.makeConstOne(tp), x1);
1722 56 (x1, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(x1, tp, "x1$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1723
1724 //Vieta
1725 56 x2 := Expression.expMul(a,x1);
1726 56 x2 := Expression.makeDiv(c,x2);
1727 56 x2 := DAE.IFEXP(con, Expression.makeConstOne(tp), x2);
1728 56 x2 := DAE.IFEXP(DAE.RELATION(x1,DAE.EQUAL(tp),DAE.RCONST(0.0),-1,NONE()), DAE.RCONST(0.0), x2);
1729 56 (x2, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(x2, tp, "x2$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1730
1731 56 tp := Expression.typeof(e2);
1732 56 exP := makeInitialGuess(tp,inExp3,e2);
1733 56 (exP, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(exP, tp, "prex$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1734
1735 56 x := helpInvCos3(x1,x2,exP,tp);
1736 56 (x, eqnForNewVars, newVarsCrefs) := makeTmpEqnAndCrefFromExp(x, tp, "x$QE", uniqueEqIndex, idepth, eqnForNewVars, newVarsCrefs, false);
1737
1738 // a = 0
1739 56 e7 := Expression.makeDiv(inExp2,b);
1740 56 invExp := Expression.inverseFactors(n);
1741 56 (invExp, _) := ExpressionSimplify.simplify1(invExp);
1742 56 e7 := Expression.expPow(e7, invExp);
1743
1744 // if a==0
1745 56 rhs := DAE.IFEXP(con, e7 , x);
1746 // lhs
1747
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 50 times.
56 lhs := if b1 then Expression.expPow(e2, e6) else Expression.expPow(e2, e3);
1748
1749 end solveQE;
1750
1751 protected function solveIfExp
1752 "
1753 solve:
1754 if(f(y), f(x), g(x) ) = h(y) w.r.t. x
1755 "
1756 input DAE.Exp inExp1;
1757 input DAE.Exp inExp2;
1758 input DAE.Exp inExp3;
1759 input Option<DAE.Exp> inCond;
1760 input Option<AvlTreePathFunction.Tree> functions;
1761 input Option<Integer> uniqueEqIndex "offset for tmp vars";
1762 input Integer idepth;
1763 input Boolean doInline;
1764 input Boolean isContinuousIntegration;
1765 output DAE.Exp outExp;
1766 output list<DAE.Statement> outAsserts;
1767 output list<BackendDAE.Equation> eqnForNewVars "eqn for tmp vars";
1768 output list<DAE.ComponentRef> newVarsCrefs;
1769 output Integer odepth;
1770 algorithm
1771 (outExp, outAsserts, eqnForNewVars, newVarsCrefs, odepth) := match inExp1
1772 local
1773 DAE.Exp eCond, eThen, eElse, res, lhs, rhs, cond1, cond2;
1774 list<DAE.Statement> asserts, asserts1;
1775 list<BackendDAE.Equation> eqns, eqns1;
1776 list<DAE.ComponentRef> var, var1;
1777 Integer depth;
1778
1779 // f(a) if(g(b)) then f1(a) else f2(a) =>
1780 // a1 = solve f(a),f1(a) for a
1781 // a2 = solve f(a),f2(a) for a
1782 // => a = if g(b) then a1 else a2
1783 case DAE.IFEXP(eCond, eThen, eElse)
1784 guard
1785 isContinuousIntegration or not expHasCref(eCond, inExp3)
1786 algorithm
1787
1788 // nested if expressions need to combine their conditions
1789 (cond1, cond2) := match inCond
1790 local DAE.Exp theCond;
1791 case SOME(theCond)
1792 90 then (DAE.LBINARY(theCond, DAE.AND(Expression.typeof(eCond)), eCond), DAE.LBINARY(theCond, DAE.AND(Expression.typeof(eCond)), Expression.negate(eCond)));
1793 255 else (eCond, Expression.negate(eCond));
1794 end match;
1795
1796 345 (lhs, asserts1, eqns, var, depth) := solveWork(eThen, inExp2, inExp3, SOME(cond1), functions, uniqueEqIndex, idepth, doInline, isContinuousIntegration);
1797 299 (rhs, _, eqns1, var1, depth) := solveWork(eElse, inExp2, inExp3, SOME(cond2), functions, uniqueEqIndex, depth, doInline, isContinuousIntegration);
1798
1799 247 res := DAE.IFEXP(eCond, lhs, rhs);
1800 247 asserts := listAppend(asserts1, asserts1);
1801
1/2
✓ Branch 2 taken 247 times.
✗ Branch 3 not taken.
247 then
1802 (res, asserts, listAppend(eqns1, eqns), listAppend(var1, var), depth);
1803 else fail();
1804 end match;
1805 end solveIfExp;
1806
1807 protected function solveLinearSystem
1808 "
1809 solve linear system with newton step
1810
1811 ToDo:
1812 fixed is for ./simulation/modelica/equations/deriveToLog.mos
1813 "
1814 input DAE.Exp inExp1;
1815 input DAE.Exp inExp2;
1816 input DAE.Exp inExp3;
1817 input Option<AvlTreePathFunction.Tree> functions;
1818 input Integer idepth;
1819 output DAE.Exp outExp;
1820 output list<DAE.Statement> outAsserts;
1821 output list<BackendDAE.Equation> eqnForNewVars = {} "eqn for tmp vars";
1822 output list<DAE.ComponentRef> newVarsCrefs = {};
1823 output Integer odepth = idepth;
1824
1825
1826 algorithm
1827 (outExp,outAsserts) := match inExp3
1828 local
1829 DAE.Exp dere,e,z;
1830 DAE.ComponentRef cr;
1831 DAE.Exp rhs;
1832 DAE.Type tp;
1833 Integer i;
1834
1835 // cr = (e1-e2)/(der(e1-e2,cr))
1836 case DAE.CREF(componentRef = cr)
1837 algorithm
1838
2/2
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 4561 times.
4604 false := hasOnlyFactors(inExp1,inExp2);
1839 4561 e := Expression.expSub(inExp1,inExp2);
1840 4097 (e,_) := ExpressionSimplify.simplify1(e);
1841 //print("\ne: ");print(ExpressionBasics.printExpStr(e));
1842 4097 dere := Differentiate.differentiateExpSolve(e, cr, functions);
1843 //print("\nder(e): ");print(ExpressionBasics.printExpStr(dere));
1844 2240 (dere,_) := ExpressionSimplify.simplify(dere);
1845
2/2
✓ Branch 1 taken 1445 times.
✓ Branch 2 taken 795 times.
2240 false := Expression.isZero(dere);
1846
2/2
✓ Branch 1 taken 689 times.
✓ Branch 2 taken 106 times.
795 false := Expression.expHasCrefNoPreOrStart(dere, cr);
1847 106 tp := Expression.typeof(inExp3);
1848 106 (z,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1849 106 (e,i) := Expression.replaceExp(e, inExp3, z);
1850 // replace at least once, otherwise it's wrong
1851
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 101 times.
106 if i < 1 then
1852 5 fail();
1853 end if;
1854 101 (e,_) := ExpressionSimplify.simplify(e);
1855 101 rhs := Expression.negate(Expression.makeDiv(e,dere));
1856 then
1857 (rhs,{});
1858
1859 else fail();
1860 end match;
1861
1862 end solveLinearSystem;
1863
1864 protected function hasOnlyFactors "help function to solve2, returns true if equation e1 == e2, has either e1 == 0 or e2 == 0 and the expression only contains
1865 factors, e.g. a*b*c = 0. In this case we can not solve the equation"
1866 input DAE.Exp e1;
1867 input DAE.Exp e2;
1868 output Boolean res;
1869 algorithm
1870 res := matchcontinue e2
1871
1872 // try normal
1873 case _
1874 algorithm
1875
2/2
✓ Branch 1 taken 3112 times.
✓ Branch 2 taken 1492 times.
4604 true := Expression.isZero(e1);
1876 // More than two factors
1877
4/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1490 times.
✓ Branch 3 taken 1451 times.
✓ Branch 4 taken 39 times.
1492 _::_::_ := Expression.factors(e2);
1878 //.. and more than two crefs
1879
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 36 times.
39 _::_::_ := Expression.extractCrefsFromExp(e2);
1880 then
1881 true;
1882
1883 // swapped args
1884 case _
1885 algorithm
1886
2/2
✓ Branch 1 taken 2786 times.
✓ Branch 2 taken 1782 times.
4568 true := Expression.isZero(e2);
1887
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1782 times.
✓ Branch 3 taken 1757 times.
✓ Branch 4 taken 25 times.
1782 _::_::_ := Expression.factors(e1);
1888
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 7 times.
25 _::_::_ := Expression.extractCrefsFromExp(e1);
1889 then
1890 true;
1891
1892 else false;
1893
1894 end matchcontinue;
1895 end hasOnlyFactors;
1896
1897
1898 protected function expHasCref
1899 "
1900 helper function for solve.
1901 case distinction for
1902 DAE.CREF or 'der(DAE.CREF())'
1903 Expression.expHasCrefNoPreOrStart
1904 or
1905 Expression.expHasDerCref
1906 "
1907 input DAE.Exp inExp1;
1908 input DAE.Exp inExp3 "DAE.CREF or 'der(DAE.CREF())'";
1909 output Boolean res;
1910
1911 algorithm
1912 res := match inExp3
1913 local DAE.ComponentRef cr;
1914
1915 1234604 case DAE.CREF(componentRef = cr) then Expression.expHasCrefNoPreOrStart(inExp1, cr);
1916 38546 case DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {DAE.CREF(componentRef = cr)}) then Expression.expHasDerCref(inExp1, cr);
1917 else
1918 algorithm
1919 ✗ if Flags.isSet(Flags.FAILTRACE) then
1920 ✗ print("\n-ExpressionSolve.solve failed:");
1921 ✗ print(" with respect to: ");print(ExpressionBasics.printExpStr(inExp3));
1922 ✗ print(" not support!");
1923 ✗ print("\n");
1924 end if;
1925 ✗ then fail();
1926 end match;
1927
1928 end expHasCref;
1929
1930 protected function makeProductLstSort
1931 "Takes a list of expressions an makes a product
1932 expression multiplying all elements in the list.
1933
1934 - a*if(b,c,d) -> if(b,a*c,a*d)
1935
1936 "
1937 input list<DAE.Exp> inExpLst;
1938 output DAE.Exp outExp;
1939 protected
1940 DAE.Type tp;
1941 list<DAE.Exp> expLstDiv, expLst, expLst2;
1942 DAE.Exp e, e1, e2;
1943 DAE.Operator op;
1944 algorithm
1945
2/2
✓ Branch 0 taken 692988 times.
✓ Branch 1 taken 808580 times.
1501568 if listEmpty(inExpLst) then
1946 outExp := DAE.RCONST(1.0);
1947 692988 return;
1948 end if;
1949
1950 808580 tp := Expression.typeof(listHead(inExpLst));
1951
1952 808580 (expLstDiv, expLst) := List.splitOnTrue(inExpLst, Expression.isDivBinary);
1953 808580 outExp := makeProductLstSort2(expLst, tp);
1954
2/2
✓ Branch 0 taken 800774 times.
✓ Branch 1 taken 7806 times.
808580 if not listEmpty(expLstDiv) then
1955 expLst2 := {};
1956 7806 expLst := {};
1957
1958
2/2
✓ Branch 0 taken 9443 times.
✓ Branch 1 taken 7806 times.
17249 for elem in expLstDiv loop
1959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9443 times.
9443 DAE.BINARY(e1,op,e2) := elem;
1960 9443 expLst := e1::expLst;
1961 expLst2 := e2::expLst2;
1962 end for;
1963
1964
1/2
✓ Branch 0 taken 7806 times.
✗ Branch 1 not taken.
7806 if not listEmpty(expLst2) then
1965 7806 e := makeProductLstSort(expLst2);
1966
1/2
✓ Branch 1 taken 7806 times.
✗ Branch 2 not taken.
7806 if not Expression.isOne(e) then
1967 7806 outExp := Expression.makeDiv(outExp,e);
1968 end if;
1969 end if;
1970
1971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7806 times.
7806 if not listEmpty(expLst) then
1972 7806 e := makeProductLstSort(expLst);
1973 7806 outExp := Expression.expMul(outExp,e);
1974 end if;
1975
1976 end if;
1977
1978 end makeProductLstSort;
1979
1980
1981 protected function makeProductLstSort2
1982 input list<DAE.Exp> inExpLst;
1983 input DAE.Type tp;
1984 output DAE.Exp outExp = Expression.makeConstOne(tp);
1985 protected
1986 list<DAE.Exp> rest;
1987 algorithm
1988 808580 rest := ExpressionSimplify.simplifyList(inExpLst);
1989
2/2
✓ Branch 0 taken 837421 times.
✓ Branch 1 taken 808580 times.
1646001 for elem in rest loop
1990
2/2
✓ Branch 1 taken 827962 times.
✓ Branch 2 taken 9459 times.
837421 if not Expression.isOne(elem) then
1991 outExp := match elem
1992 local DAE.Exp e1,e2,e3;
1993 case DAE.IFEXP(e1,e2,e3)
1994 1026 then DAE.IFEXP(e1, Expression.expMul(outExp,e2), Expression.expMul(outExp,e3));
1995 826936 else Expression.expMul(outExp, elem);
1996 end match;
1997 end if;
1998 end for;
1999
2000 end makeProductLstSort2;
2001
2002 protected function makeTmpEqnAndCrefFromExp
2003 input DAE.Exp iExp;
2004 input DAE.Type tp;
2005 input String name;
2006 input Integer index1, index2;
2007 input list<BackendDAE.Equation> ieqnForNewVars;
2008 input list<DAE.ComponentRef> inewVarsCrefs;
2009 input Boolean need;
2010 output DAE.Exp oExp;
2011 output list<BackendDAE.Equation> oeqnForNewVars;
2012 output list<DAE.ComponentRef> onewVarsCrefs;
2013 protected
2014 DAE.ComponentRef cr;
2015 BackendDAE.Equation eqn;
2016 algorithm
2017 1081 (oExp,_) := ExpressionSimplify.simplify1(iExp);
2018
5/6
✓ Branch 0 taken 1081 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 971 times.
✓ Branch 4 taken 110 times.
✓ Branch 6 taken 849 times.
✓ Branch 7 taken 122 times.
1081 if need or not (Expression.isCref(oExp) or Expression.isConst(oExp)) then
2019 849 cr := ComponentReferenceBasics.makeCrefIdent("$TMP$VAR$" + intString(index1) + "$" + intString(index2) + name, tp , {});
2020 849 eqn := BackendDAE.SOLVED_EQUATION(cr, oExp, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
2021 849 oExp := Expression.crefExp(cr);
2022 oeqnForNewVars := eqn :: ieqnForNewVars;
2023 849 onewVarsCrefs := cr :: inewVarsCrefs;
2024 else
2025 oeqnForNewVars := ieqnForNewVars;
2026 onewVarsCrefs := inewVarsCrefs;
2027 end if;
2028 end makeTmpEqnAndCrefFromExp;
2029
2030 protected function makeDomainAssert
2031 input String name "of the function";
2032 input DAE.Exp rhs "solution of the function";
2033 input Option<tuple<Real, Boolean>> lowerBound "(value, including?)";
2034 input Option<tuple<Real, Boolean>> upperBound "(value, including?)";
2035 output BackendDAE.Equation assEq;
2036 protected
2037 String msg;
2038 DAE.Exp cond;
2039 DAE.Algorithm algo;
2040 DAE.Type tp = Expression.typeof(rhs);
2041 algorithm
2042 (msg, cond) := match (lowerBound, upperBound)
2043 local
2044 Real lower, upper;
2045 String str;
2046 DAE.Exp l, u;
2047
2048 // range [l, u]
2049 case (SOME((lower, true)), SOME((upper, true))) algorithm
2050 60 str := "Model error: Result of " + name + " outside the range "
2051 + realString(lower) + " <= " + ExpressionBasics.printExpStr(rhs)
2052 + " <= " + realString(upper) + ". Unable to invert.";
2053 60 l := DAE.RELATION(DAE.RCONST(lower), DAE.LESSEQ(tp), rhs, -1, NONE());
2054 60 u:= DAE.RELATION(rhs, DAE.LESSEQ(tp), DAE.RCONST(upper), -1, NONE());
2055 60 then (str, DAE.LBINARY(l, DAE.AND(tp), u));
2056
2057 // range [l, u)
2058 case (SOME((lower, true)), SOME((upper, false))) algorithm
2059 ✗ str := "Model error: Result of " + name + " outside the range "
2060 + realString(lower) + " <= " + ExpressionBasics.printExpStr(rhs)
2061 + " < " + realString(upper) + ". Unable to invert.";
2062 ✗ l:= DAE.RELATION(DAE.RCONST(lower), DAE.LESSEQ(tp), rhs, -1, NONE());
2063 ✗ u:= DAE.RELATION(rhs, DAE.LESS(tp), DAE.RCONST(upper), -1, NONE());
2064 ✗ then (str, DAE.LBINARY(l, DAE.AND(tp), u));
2065
2066 // range (l, u]
2067 case (SOME((lower, false)), SOME((upper, true))) algorithm
2068 ✗ str := "Model error: Result of " + name + " outside the range "
2069 + realString(lower) + " < " + ExpressionBasics.printExpStr(rhs)
2070 + " <= " + realString(upper) + ". Unable to invert.";
2071 ✗ l:= DAE.RELATION(DAE.RCONST(lower), DAE.LESS(tp), rhs, -1, NONE());
2072 ✗ u:= DAE.RELATION(rhs, DAE.LESSEQ(tp), DAE.RCONST(upper), -1, NONE());
2073 ✗ then (str, DAE.LBINARY(l, DAE.AND(tp), u));
2074
2075 // range (l, u)
2076 case (SOME((lower, false)), SOME((upper, false))) algorithm
2077 ✗ str := "Model error: Result of " + name + " outside the range "
2078 + realString(lower) + " < " + ExpressionBasics.printExpStr(rhs)
2079 + " < " + realString(upper) + ". Unable to invert.";
2080 ✗ l:= DAE.RELATION(DAE.RCONST(lower), DAE.LESS(tp), rhs, -1, NONE());
2081 ✗ u:= DAE.RELATION(rhs, DAE.LESS(tp), DAE.RCONST(upper), -1, NONE());
2082 ✗ then (str, DAE.LBINARY(l, DAE.AND(tp), u));
2083
2084 // range [l, inf)
2085 case (SOME((lower, true)), NONE()) algorithm
2086 38 str := "Model error: Result of " + name + " should be "
2087 + ExpressionBasics.printExpStr(rhs) + " >= " + realString(lower)
2088 + ". Unable to invert.";
2089 38 l:= DAE.RELATION(DAE.RCONST(lower), DAE.LESSEQ(tp), rhs, -1, NONE());
2090 then (str, l);
2091
2092 // range (l, inf)
2093 case (SOME((lower, true)), NONE()) algorithm
2094 ✗ str := "Model error: Result of " + name + " should be "
2095 + ExpressionBasics.printExpStr(rhs) + " > " + realString(lower)
2096 + ". Unable to invert.";
2097 ✗ l:= DAE.RELATION(DAE.RCONST(lower), DAE.LESS(tp), rhs, -1, NONE());
2098 then (str, l);
2099
2100 // range (-inf, u]
2101 case (NONE(), SOME((upper, true))) algorithm
2102 ✗ str := "Model error: Result of " + name + " should be "
2103 + ExpressionBasics.printExpStr(rhs) + " <= " + realString(upper)
2104 + ". Unable to invert.";
2105 ✗ u:= DAE.RELATION(rhs, DAE.LESSEQ(tp), DAE.RCONST(upper), -1, NONE());
2106 then (str, u);
2107
2108 // range (-inf, u)
2109 case (NONE(), SOME((upper, false))) algorithm
2110 ✗ str := "Model error: Result of " + name + " should be "
2111 + ExpressionBasics.printExpStr(rhs) + " < " + realString(upper)
2112 + ". Unable to invert.";
2113 ✗ u:= DAE.RELATION(rhs, DAE.LESS(tp), DAE.RCONST(upper), -1, NONE());
2114 then (str, u);
2115 end match;
2116
2117 196 algo := DAE.ALGORITHM_STMTS({DAE.STMT_ASSERT(cond, DAE.SCONST(msg), DAE.ASSERTIONLEVEL_ERROR, DAE.emptyElementSource)});
2118 98 assEq := BackendDAE.ALGORITHM(0, algo, DAE.emptyElementSource, DAE.EXPAND(), BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
2119 end makeDomainAssert;
2120
2121 protected function makeInitialGuess
2122 input DAE.Type tp;
2123 input DAE.Exp iExp1;
2124 input DAE.Exp iExp2;
2125 output DAE.Exp oExp;
2126 protected
2127 DAE.Exp con, e;
2128 algorithm
2129 259 con := Expression.makePureBuiltinCall("initial", {}, tp);
2130 259 e := Expression.traverseExpBottomUp(iExp2, makeInitialGuess2, (iExp1, "pre", tp, true));
2131 259 oExp := Expression.traverseExpBottomUp(iExp2, makeInitialGuess2, (iExp1, "pre", tp, false));
2132 259 oExp := DAE.IFEXP(con, e, oExp);
2133 end makeInitialGuess;
2134
2135 protected function makeInitialGuess2
2136 input DAE.Exp iExp;
2137 input tuple<DAE.Exp, String, DAE.Type, Boolean> itpl;
2138 output DAE.Exp oExp;
2139 output tuple<DAE.Exp, String, DAE.Type, Boolean> otpl = itpl;
2140 algorithm
2141 oExp := match(iExp, itpl)
2142 local
2143 DAE.ComponentRef cr1,cr2;
2144 DAE.Type tp;
2145 String fun;
2146 DAE.Exp e;
2147
2148 case (DAE.CREF(componentRef=cr1), (DAE.CREF(componentRef=cr2), fun, tp, _))
2149 guard(ComponentReferenceBasics.crefEqual(cr1, cr2)) algorithm
2150 518 e := Expression.makePureBuiltinCall(fun, {iExp}, tp);
2151 then e;
2152
2153 case (_, (_, _, tp, true)) algorithm
2154 try
2155
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 48 times.
132 SOME(e) := makeInitialGuess3(iExp, tp);
2156 else
2157 e := iExp;
2158 end try;
2159 then e;
2160
2161 else iExp;
2162 end match;
2163 end makeInitialGuess2;
2164
2165 protected function makeInitialGuess3
2166 input DAE.Exp iExp;
2167 input DAE.Type tp;
2168 output Option<DAE.Exp> oExp;
2169 algorithm
2170 oExp := match iExp
2171 local DAE.Exp e, con, o;
2172
2173 case DAE.CALL(path = Absyn.IDENT(name = "log"), expLst={e})
2174 algorithm
2175 12 con := DAE.RELATION(e, DAE.LESSEQ(tp), DAE.RCONST(0.0), -1, NONE());
2176 12 o := DAE.IFEXP(con, DAE.RCONST(-1/0.000000001), iExp);
2177 then SOME(o);
2178
2179 case DAE.CALL(path = Absyn.IDENT(name = "log10"), expLst={e})
2180 algorithm
2181 ✗ con := DAE.RELATION(e, DAE.LESSEQ(tp), DAE.RCONST(0.0), -1, NONE());
2182 ✗ o := DAE.IFEXP(con, DAE.RCONST(-1/0.000000001), iExp);
2183 then SOME(o);
2184
2185 case DAE.CALL(path = Absyn.IDENT(name = "sqrt"), expLst={e})
2186 algorithm
2187 ✗ con := DAE.RELATION(e, DAE.LESSEQ(tp), DAE.RCONST(0.0), -1, NONE());
2188 ✗ o := DAE.IFEXP(con, DAE.RCONST(0.0), iExp);
2189 then SOME(o);
2190
2191 case DAE.BINARY(exp2=e)
2192 algorithm
2193 36 con := DAE.RELATION(e, DAE.EQUAL(tp), DAE.RCONST(0.0), -1, NONE());
2194 36 o := DAE.IFEXP(con, DAE.RCONST(1.0), iExp);
2195 then SOME(o);
2196
2197 else NONE();
2198
2199 end match;
2200
2201 end makeInitialGuess3;
2202
2203 protected function helpInvCos
2204 input DAE.Exp acosy;
2205 input DAE.Exp x;
2206 input DAE.Type tp;
2207 input Boolean neg;
2208 output DAE.Exp k;
2209 algorithm
2210
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 33 times.
66 k := if neg then
2211 Expression.expAdd(x,acosy)
2212 else
2213 Expression.expSub(x,acosy);
2214 66 k := Expression.makeDiv(k, Expression.expMul(DAE.RCONST(2.0), DAE.PI));
2215 66 k := Expression.makePureBuiltinCall("$_round",{k},tp);
2216
2217 end helpInvCos;
2218
2219 protected function helpInvSin
2220 input DAE.Exp asiny;
2221 input DAE.Exp x;
2222 input DAE.Type tp;
2223 input Boolean neg;
2224 output DAE.Exp k;
2225 algorithm
2226
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 k := if neg then
2227 Expression.expAdd(x,asiny)
2228 else
2229 Expression.expSub(x,asiny);
2230 54 k := Expression.makeDiv(k, Expression.expMul(DAE.RCONST(2.0), DAE.PI));
2231
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 if neg then
2232 27 k := Expression.expSub(k, DAE.RCONST(0.5));
2233 end if;
2234 54 k := Expression.makePureBuiltinCall("$_round",{k},tp);
2235 end helpInvSin;
2236
2237 protected function helpInvCos2
2238 input DAE.Exp k;
2239 input DAE.Exp acosy;
2240 input DAE.Type tp;
2241 input Boolean neg;
2242 output DAE.Exp x;
2243 algorithm
2244
2245
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 33 times.
66 x := if neg then Expression.negate(acosy) else acosy;
2246 66 x := Expression.expAdd(x, Expression.expMul(k, Expression.expMul(DAE.RCONST(2.0), DAE.PI)));
2247
2248 end helpInvCos2;
2249
2250 protected function helpInvSin2
2251 input DAE.Exp k;
2252 input DAE.Exp asiny;
2253 input DAE.Type tp;
2254 input Boolean neg;
2255 output DAE.Exp x;
2256 protected
2257 DAE.Exp e;
2258 algorithm
2259
2260
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 x := if neg then Expression.negate(asiny) else asiny;
2261 54 e := Expression.expMul(k, Expression.expMul(DAE.RCONST(2.0), DAE.PI));
2262
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 e := if neg then Expression.expAdd(e, DAE.PI) else e;
2263 54 x := Expression.expAdd(x, e);
2264
2265 end helpInvSin2;
2266
2267 protected function helpInvCos3
2268 input DAE.Exp x1;
2269 input DAE.Exp x2;
2270 input DAE.Exp x;
2271 input DAE.Type tp;
2272 output DAE.Exp y;
2273 protected
2274 DAE.Exp diffx1 = absDiff(x1,x,tp);
2275 DAE.Exp diffx2 = absDiff(x2,x,tp);
2276 DAE.Exp con = DAE.RELATION(diffx1, DAE.LESS(tp), diffx2, -1, NONE());
2277 algorithm
2278 116 con := Expression.makeNoEvent(con);
2279 116 y := DAE.IFEXP(con, x1, x2);
2280 end helpInvCos3;
2281
2282 protected function absDiff
2283 input DAE.Exp x;
2284 input DAE.Exp y;
2285 input DAE.Type tp;
2286 output DAE.Exp z;
2287 algorithm
2288 232 z := Expression.expSub(x,y);
2289 232 z := Expression.makePureBuiltinCall("abs",{z},tp);
2290 end absDiff;
2291
2292 annotation(__OpenModelica_Interface="backend");
2293 end ExpressionSolve;
2294