Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 68.7% 698 / 0 / 1016
Functions: -% 0 / 1 / 1
Branches: 54.1% 262 / 0 / 484

OMCompiler/Compiler/BackEnd/Differentiate.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 Differentiate
37 " file: Differentiate.mo
38 package: Differentiate
39 description: Differentiation of equations from BackendDAE.BackendDAE
40
41
42 This module is responsible for symbolic differentiation of equations and
43 expressions.
44
45 The symbolic differentiation is used in the Newton-Raphson method and in
46 index reduction."
47
48 // public imports
49 public import Absyn;
50 public import BackendDAE;
51 public import DAE;
52 public import DAEUtil;
53 public import AvlTreePathFunction;
54
55 // protected imports
56 protected import AbsynUtil;
57 protected import Algorithm;
58 protected import Array;
59 protected import BackendDump;
60 protected import BackendDAECreate;
61 protected import BackendDAEUtil;
62 protected import BackendEquation;
63 protected import BackendUtil;
64 protected import BackendVariable;
65 protected import ClassInf;
66 protected import ComponentReference;
67 protected import ComponentReferenceBasics;
68 protected import DAEDump;
69 protected import DAEDumpTpl;
70 protected import Debug;
71 protected import ElementSource;
72 protected import Error;
73 protected import Ceval;
74 protected import Expression;
75 protected import ExpressionBasics;
76 protected import ExpressionSimplify;
77 protected import Flags;
78 protected import Inline;
79 protected import List;
80 protected import SCode;
81 protected import StringUtil;
82 protected import TypesDump;
83 protected import Types;
84 protected import Util;
85 protected import SymbolicJacobian.DAE_CJ;
86
87 constant Integer defaultMaxIter = 20;
88
89 // =============================================================================
90 // differentiation interfaces:
91 // - createDifferentiatedCrefName
92 // - createSeedCrefName
93 // - differentiateEquation
94 // - differentiateEquationTime
95 // - differentiateExpCrefFullJacobian
96 // - differentiateExpSolve
97 // - differentiateExpTime
98 // =============================================================================
99
100 public function differentiateEquationTime
101 "Differentiates an equation with respect to time.
102 Returns NONE() if it was not possible to calculate a derivative."
103 input BackendDAE.Equation inEquation;
104 input BackendDAE.Variables inVariables;
105 input BackendDAE.Shared inShared;
106 output Option<BackendDAE.Equation> outEquation;
107 output BackendDAE.Shared outShared = inShared;
108 protected
109 BackendDAE.DifferentiateInputData diffData;
110 BackendDAE.Equation eqn;
111 BackendDAE.Variables knvars;
112 DAE.ElementSource source;
113 AvlTreePathFunction.Tree funcs;
114 algorithm
115 try
116
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7514 times.
7514 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
117 ✗ BackendDump.debugStrEqnStr("### differentiateEquationTime\n", inEquation, " w.r.t. time\n");
118 end if;
119 7514 funcs := BackendDAEUtil.getFunctions(inShared);
120 7514 knvars := BackendDAEUtil.getGlobalKnownVarsFromShared(inShared);
121 diffData := BackendDAE.emptyInputData;
122 7514 diffData.dependenentVars := SOME(inVariables);
123 7514 diffData.knownVars := SOME(knvars);
124 7514 diffData.allVars := SOME(inVariables);
125 7514 (eqn, funcs) := differentiateEquation(inEquation, DAE.crefTime, diffData, BackendDAE.DIFFERENTIATION_TIME(), funcs);
126 outEquation := SOME(eqn);
127 7514 outShared := BackendDAEUtil.setSharedFunctionTree(inShared, funcs);
128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7514 times.
7514 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
129 ✗ BackendDump.debugStrEqnStr("### Result of differentiateEquationTime\n --> ", eqn, "\n");
130 end if;
131 else
132 ✗ source := BackendEquation.equationSource(inEquation);
133 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {"\nDifferentiate.differentiateEquationTime failed for " + BackendDump.equationString(inEquation) + "\n\n"}, ElementSource.getElementSourceFileInfo(source));
134 outEquation := NONE();
135 end try;
136 end differentiateEquationTime;
137
138 public function differentiateExpTime
139 "Differentiates an expression with respect to time."
140 input DAE.Exp inExp;
141 input BackendDAE.Variables inVariables;
142 input BackendDAE.Shared inShared;
143 output DAE.Exp outExp;
144 output BackendDAE.Shared outShared;
145 protected
146 DAE.Exp dexp;
147 AvlTreePathFunction.Tree funcs;
148 BackendDAE.DifferentiateInputData diffData;
149 BackendDAE.Variables knvars;
150 algorithm
151 try
152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 127 times.
127 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
153 ✗ BackendDump.debugStrExpStr("### differentiateExpTime\n ", inExp, " w.r.t. time\n");
154 end if;
155 127 funcs := BackendDAEUtil.getFunctions(inShared);
156 127 knvars := BackendDAEUtil.getGlobalKnownVarsFromShared(inShared);
157 diffData := BackendDAE.emptyInputData;
158 127 diffData.dependenentVars := SOME(inVariables);
159 127 diffData.knownVars := SOME(knvars);
160 127 (dexp, funcs) := differentiateExp(inExp, DAE.crefTime, diffData, BackendDAE.DIFFERENTIATION_TIME(), funcs, defaultMaxIter);
161 127 (outExp, _) := ExpressionSimplify.simplify(dexp);
162 127 outShared := BackendDAEUtil.setSharedFunctionTree(inShared, funcs);
163
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 127 times.
127 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
164 ✗ BackendDump.debugStrExpStr("### Result of differentiateExpTime\n --> ", outExp, "n");
165 end if;
166 else
167 // expandDerOperator expects sometime that differentiate fails,
168 // so the calling function need to take care of the error messages.
169 // TODO: change that in expandDerOperator
170 //Error.addSourceMessage(Error.INTERNAL_ERROR, {msg}, ElementSource.getElementSourceFileInfo(DAE.emptyElementSource));
171
172 ✗ if Flags.isSet(Flags.FAILTRACE) then
173 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {ExpressionBasics.printExpStr(inExp), "time"}, sourceInfo());
174 end if;
175 ✗ fail();
176 end try;
177 end differentiateExpTime;
178
179 public function differentiateExpSolve
180 "Differentiates an expression with respect to inCref."
181 input DAE.Exp inExp;
182 input DAE.ComponentRef inCref;
183 input Option<AvlTreePathFunction.Tree> functions;
184 output DAE.Exp outExp;
185 protected
186 list<DAE.Exp> fac = Expression.factors(inExp);
187 DAE.Exp dexp;
188 AvlTreePathFunction.Tree fun;
189 algorithm
190
2/2
✓ Branch 1 taken 785 times.
✓ Branch 2 taken 273431 times.
274216 ({}, _) := List.split1OnTrue(fac, Expression.expHasCrefInIf, inCref); // check if differentiateExpSolve is allowed
191
192 try
193 fun := match functions
194 local
195 AvlTreePathFunction.Tree fun_;
196 case SOME(fun_) then fun_;
197 else AvlTreePathFunction.Tree.EMPTY();
198 end match;
199
200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 273431 times.
273431 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
201 ✗ BackendDump.debugStrExpStrCrefStr("### differentiateExpSolve\n ", inExp, " w.r.t. ", inCref, "\n");
202 end if;
203 273431 (dexp, _) := differentiateExp(inExp, inCref, BackendDAE.emptyInputData, BackendDAE.SIMPLE_DIFFERENTIATION(), fun, defaultMaxIter);
204 263917 (outExp, _) := ExpressionSimplify.simplify(dexp);
205
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 263917 times.
263917 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
206 ✗ BackendDump.debugStrExpStr("### Result of differentiateExpSolve\n --> ", outExp, "\n");
207 end if;
208 else
209
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 9513 times.
9514 if Flags.isSet(Flags.FAILTRACE) then
210 3 Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {ExpressionBasics.printExpStr(inExp), ComponentReference.crefStr(inCref)}, sourceInfo());
211 end if;
212 9514 fail();
213 end try;
214 end differentiateExpSolve;
215
216
217 public function differentiateExpCrefFullJacobian
218 "Differentiates an expression inExp with respect to inCref."
219 input DAE.Exp inExp;
220 input DAE.ComponentRef inCref;
221 input BackendDAE.Variables inVariables;
222 input BackendDAE.Shared inShared;
223 output DAE.Exp outExp;
224 output BackendDAE.Shared outShared;
225 protected
226 DAE.Exp dexp;
227 AvlTreePathFunction.Tree funcs;
228 BackendDAE.DifferentiateInputData diffData;
229 BackendDAE.Variables knvars;
230 algorithm
231 try
232 151719 funcs := BackendDAEUtil.getFunctions(inShared);
233 151719 knvars := BackendDAEUtil.getGlobalKnownVarsFromShared(inShared);
234 diffData := BackendDAE.emptyInputData;
235 151719 diffData.dependenentVars := SOME(inVariables);
236 151719 diffData.knownVars := SOME(knvars);
237 151719 (dexp, funcs) := differentiateExp(inExp, inCref, diffData, BackendDAE.DIFF_FULL_JACOBIAN(), funcs, defaultMaxIter);
238 150295 (outExp,_) := ExpressionSimplify.simplify(dexp);
239 150295 outShared := BackendDAEUtil.setSharedFunctionTree(inShared, funcs);
240 else
241 // expandDerOperator expects sometimes that differentiate fails,
242 // so the calling function need to take care of the error messages.
243 // TODO: change that in expandDerOperator
244 //Error.addSourceMessage(Error.INTERNAL_ERROR, {msg}, ElementSource.getElementSourceFileInfo(DAE.emptyElementSource));
245
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1424 times.
1424 if Flags.isSet(Flags.FAILTRACE) then
247 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {ExpressionBasics.printExpStr(inExp), ComponentReference.crefStr(inCref)}, sourceInfo());
248 end if;
249 1424 fail();
250 end try;
251 end differentiateExpCrefFullJacobian;
252
253
254 // =============================================================================
255 // further interface functions to differentiation
256 // - differentiateEquation
257 // - differentiateBackendDAE
258 //
259 // =============================================================================
260
261
262 public function differentiateEquation
263 "Differentiates an equation with respect to a cref."
264 input BackendDAE.Equation inEquation;
265 input DAE.ComponentRef inDiffwrtCref;
266 input BackendDAE.DifferentiateInputData inInputData;
267 input BackendDAE.DifferentiationType inDiffType;
268 input AvlTreePathFunction.Tree inFunctionTree;
269 output BackendDAE.Equation outEquation;
270 output AvlTreePathFunction.Tree outFunctionTree;
271 algorithm
272 try
273 25649 (outEquation, outFunctionTree) := differentiateEquationFragile(inEquation, inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
274 else
275 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {BackendDump.equationString(inEquation), ComponentReference.crefStr(inDiffwrtCref)}, sourceInfo());
276 ✗ fail();
277 end try;
278 end differentiateEquation;
279
280 public function differentiateEquationFragile
281 "author: kabdelhak 2019-09
282 Differentiates an equation with respect to a cref, fails if it can't be differentiated."
283 input BackendDAE.Equation inEquation;
284 input DAE.ComponentRef inDiffwrtCref;
285 input BackendDAE.DifferentiateInputData inInputData;
286 input BackendDAE.DifferentiationType inDiffType;
287 input AvlTreePathFunction.Tree inFunctionTree;
288 output BackendDAE.Equation outEquation;
289 output AvlTreePathFunction.Tree outFunctionTree;
290 algorithm
291 // Debug dump
292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25649 times.
25649 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
293 ✗ BackendDump.debugStrEqnStr("### differentiateEquation\n ", inEquation, " w.r.t. " + ComponentReference.crefStr(inDiffwrtCref) + "\n");
294 end if;
295 (outEquation, outFunctionTree) := match inEquation
296 local
297 DAE.Exp e1_1, e2_1, e1, e2;
298 DAE.ComponentRef cref;
299 DAE.ElementSource source;
300 Integer size;
301 Option<Integer> recordSize;
302 list<DAE.Exp> expExpLst;
303 list<Integer> dimSize;
304 DAE.SymbolicOperation op1, op2;
305 AvlTreePathFunction.Tree funcs;
306 DAE.Algorithm alg;
307 list<BackendDAE.Equation> eqns;
308 list<list<BackendDAE.Equation>> eqnslst;
309 list<DAE.Statement> statementLst;
310 DAE.Expand expand;
311 BackendDAE.WhenEquation whenEqn;
312 BackendDAE.EquationAttributes eqAttr;
313
314 // equations
315 case BackendDAE.EQUATION(exp=e1, scalar=e2, source=source, attr=eqAttr)
316 algorithm
317 20378 (e1_1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, defaultMaxIter);
318 20378 (e1_1, _) := ExpressionSimplify.simplify(e1_1);
319
320 20378 (e2_1, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
321 20378 (e2_1, _) := ExpressionSimplify.simplify(e2_1);
322
323 20378 op1 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e1_1);
324 20378 op2 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e2, e2_1);
325 20378 source := List.foldr({op1, op2}, ElementSource.addSymbolicTransformation, source);
326
327 20378 then
328 (BackendDAE.EQUATION(e1_1, e2_1, source, eqAttr), funcs);
329
330 // solved equations
331 case BackendDAE.SOLVED_EQUATION(componentRef=cref, exp=e2, source=source, attr=eqAttr)
332 algorithm
333 5212 e1 := Expression.crefExp(cref);
334
335 5212 (e1_1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, defaultMaxIter);
336 5212 (e1_1, _) := ExpressionSimplify.simplify(e1_1);
337
338 5212 (e2_1, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
339 5212 (e2_1, _) := ExpressionSimplify.simplify(e2_1);
340
341 5212 op1 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e1_1);
342 5212 op2 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e2, e2_1);
343 5212 source := List.foldr({op1, op2}, ElementSource.addSymbolicTransformation, source);
344
345 5212 then
346 (BackendDAE.EQUATION(e1_1, e2_1, source, eqAttr), funcs);
347
348 // RESIDUAL_EQUATION
349 case BackendDAE.RESIDUAL_EQUATION(exp=e1, source=source, attr=eqAttr)
350 algorithm
351
352 ✗ (e1_1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, defaultMaxIter);
353 ✗ (e1_1, _) := ExpressionSimplify.simplify(e1_1);
354
355 ✗ op1 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e1_1);
356 ✗ source := List.foldr({op1}, ElementSource.addSymbolicTransformation, source);
357
358 ✗ then
359 (BackendDAE.RESIDUAL_EQUATION(e1_1, source, eqAttr), funcs);
360
361 // complex equations
362 case BackendDAE.COMPLEX_EQUATION(size=size, left=e1, right=e2, source=source, attr=eqAttr)
363 algorithm
364 39 (e1_1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, defaultMaxIter);
365 39 (e1_1, _) := ExpressionSimplify.simplify(e1_1);
366
367 39 (e2_1, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
368 39 (e2_1, _) := ExpressionSimplify.simplify(e2_1);
369
370
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
39 if valueEq(inDiffType, BackendDAE.DIFFERENTIATION_TIME()) then
371 ✗ (e1_1, e2_1) := keepDiscreteTupleElements(e1, e2, e1_1, e2_1);
372 end if;
373
374 39 op1 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e1_1);
375 39 op2 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e2, e2_1);
376 39 source := List.foldr({op1, op2}, ElementSource.addSymbolicTransformation, source);
377
378 39 then
379 (BackendDAE.COMPLEX_EQUATION(size, e1_1, e2_1, source, eqAttr), funcs);
380
381 // Array Equations
382 case BackendDAE.ARRAY_EQUATION(dimSize=dimSize, left=e1, right=e2, source=source, attr=eqAttr, recordSize=recordSize)
383 algorithm
384 ✗ (e1_1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, defaultMaxIter);
385 ✗ (e1_1, _) := ExpressionSimplify.simplify(e1_1);
386
387 ✗ (e2_1, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
388 ✗ (e2_1, _) := ExpressionSimplify.simplify(e2_1);
389
390 ✗ op1 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e1_1);
391 ✗ op2 := DAE.OP_DIFFERENTIATE(inDiffwrtCref, e2, e2_1);
392 ✗ source := List.foldr({op1, op2}, ElementSource.addSymbolicTransformation, source);
393
394 ✗ then
395 (BackendDAE.ARRAY_EQUATION(dimSize, e1_1, e2_1, source, eqAttr, recordSize), funcs);
396
397 // differentiate algorithm
398 case BackendDAE.ALGORITHM(size=size, alg=DAE.ALGORITHM_STMTS(statementLst=statementLst), source=source, expand=expand, attr=eqAttr)
399 algorithm
400 // get Allgorithm
401 6 (statementLst, funcs) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, defaultMaxIter);
402 6 alg := DAE.ALGORITHM_STMTS(statementLst);
403
404 //op1 = DAE.OP_DIFFERENTIATE(cr, before, after)
405 //op1 = DAE.OP_DIFFERENTIATE(inDiffwrtCref, e1, e2);
406 //source = ElementSource.addSymbolicTransformation(source, op1);
407
408 6 then
409 (BackendDAE.ALGORITHM(size, alg, source, expand, eqAttr), funcs);
410
411 // if-equations
412 case BackendDAE.IF_EQUATION(conditions=expExpLst, eqnstrue=eqnslst, eqnsfalse=eqns, source=source, attr=eqAttr)
413 algorithm
414 ✗ (eqnslst, funcs) := differentiateEquationsLst(eqnslst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree);
415 ✗ (eqns, funcs) := differentiateEquations(eqns, inDiffwrtCref, inInputData, inDiffType, {}, funcs);
416
417 ✗ then
418 (BackendDAE.IF_EQUATION(expExpLst, eqnslst, eqns, source, eqAttr), funcs);
419
420 case BackendDAE.WHEN_EQUATION(size=size, whenEquation=whenEqn, source=source, attr=eqAttr)
421 algorithm
422 14 (whenEqn, funcs) := differentiateWhenEquations(whenEqn, inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
423
424 14 then
425 (BackendDAE.WHEN_EQUATION(size, whenEqn, source, eqAttr), funcs);
426 else algorithm
427 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {BackendDump.equationString(inEquation), ComponentReference.crefStr(inDiffwrtCref)}, sourceInfo());
428 ✗ then fail();
429 end match;
430 // Debug dump
431
1/2
✓ Branch 1 taken 25649 times.
✗ Branch 2 not taken.
25649 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
432 ✗ BackendDump.debugStrEqnStr("### Result of differentiateEquation\n --> ", outEquation,"\n");
433 end if;
434 end differentiateEquationFragile;
435
436
437 protected function keepDiscreteTupleElements
438 "Discrete elements of a tuple equation keep their undifferentiated equation,
439 so the derivative still solves for them and keeps the size of the original."
440 input DAE.Exp lhs;
441 input DAE.Exp rhs;
442 input DAE.Exp dlhs;
443 input DAE.Exp drhs;
444 output DAE.Exp outLhs = dlhs;
445 output DAE.Exp outRhs = drhs;
446 protected
447 list<DAE.Exp> lhsLst, dlhsLst, rhsLst, drhsLst;
448 list<Boolean> isDiscrete;
449 algorithm
450 (lhsLst, dlhsLst) := match (lhs, dlhs)
451 case (DAE.TUPLE(PR = lhsLst), DAE.TUPLE(PR = dlhsLst)) then (lhsLst, dlhsLst);
452 else ({}, {});
453 end match;
454 ✗ isDiscrete := list(BackendEquation.isDiscreteTupleElement(e) for e in lhsLst);
455 ✗ if not listMember(true, isDiscrete) then
456 ✗ return;
457 end if;
458
459 ✗ rhsLst := BackendEquation.tupleElements(rhs, lhsLst);
460 ✗ drhsLst := BackendEquation.tupleElements(drhs, dlhsLst);
461 ✗ outLhs := DAE.TUPLE(list(if d then l else dl threaded for d in isDiscrete, l in lhsLst, dl in dlhsLst));
462 ✗ outRhs := DAE.TUPLE(list(if d then r else dr threaded for d in isDiscrete, r in rhsLst, dr in drhsLst));
463 end keepDiscreteTupleElements;
464
465 protected function differentiateEquations
466 "Differentiates an equation with respect to a cref."
467 input list<BackendDAE.Equation> inEquations;
468 input DAE.ComponentRef inDiffwrtCref;
469 input BackendDAE.DifferentiateInputData inInputData;
470 input BackendDAE.DifferentiationType inDiffType;
471 input list<BackendDAE.Equation> inEquationsAccum;
472 input AvlTreePathFunction.Tree inFunctionTree;
473 output list<BackendDAE.Equation> outEquations;
474 output AvlTreePathFunction.Tree outFunctionTree;
475 algorithm
476 (outEquations,outFunctionTree) := matchcontinue inEquations
477 local
478 AvlTreePathFunction.Tree funcs;
479 list<BackendDAE.Equation> rest, eqns;
480 BackendDAE.Equation eqn;
481
482 ✗ case {} then (listReverse(inEquationsAccum), inFunctionTree);
483
484 // equations
485 case eqn::rest
486 algorithm
487 ✗ (eqn, funcs) := differentiateEquation(eqn, inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
488 eqns := eqn::inEquationsAccum;
489 ✗ (eqns, funcs) := differentiateEquations(rest, inDiffwrtCref, inInputData, inDiffType, eqns, funcs);
490 then (eqns, funcs);
491
492 case eqn::_
493 algorithm
494 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {BackendDump.equationString(eqn), ComponentReference.crefStr(inDiffwrtCref)}, sourceInfo());
495 ✗ then
496 fail();
497 end matchcontinue;
498 end differentiateEquations;
499
500 protected function differentiateEquationsLst
501 "Differentiates a list of an equation list with respect to a cref.
502 Helper function to differentiate a IF-EQUATION."
503 input list<list<BackendDAE.Equation>> inEquationsLst;
504 input DAE.ComponentRef inDiffwrtCref;
505 input BackendDAE.DifferentiateInputData inInputData;
506 input BackendDAE.DifferentiationType inDiffType;
507 input list<list<BackendDAE.Equation>> inEquationsLstAccum;
508 input AvlTreePathFunction.Tree inFunctionTree;
509 output list<list<BackendDAE.Equation>> outEquationsLst;
510 output AvlTreePathFunction.Tree outFunctionTree;
511 algorithm
512 (outEquationsLst, outFunctionTree) := matchcontinue inEquationsLst
513 local
514 AvlTreePathFunction.Tree funcs;
515 list<list<BackendDAE.Equation>> rest, eqnsLst;
516 list<BackendDAE.Equation> eqns;
517
518 ✗ case {} then (listReverse(inEquationsLstAccum), inFunctionTree);
519
520 // equations
521 case eqns::rest
522 algorithm
523 ✗ (eqns, funcs) := differentiateEquations(eqns, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree);
524 eqnsLst := eqns::inEquationsLstAccum;
525 ✗ (eqnsLst, funcs) := differentiateEquationsLst(rest, inDiffwrtCref, inInputData, inDiffType, eqnsLst, funcs);
526 then (eqnsLst, funcs);
527
528 case eqns::_
529 algorithm
530 ✗ Error.addSourceMessage(Error.NON_EXISTING_DERIVATIVE, {BackendDump.equationListString(eqns, "equation list"), ComponentReference.crefStr(inDiffwrtCref)}, sourceInfo());
531 ✗ then
532 fail();
533 end matchcontinue;
534 end differentiateEquationsLst;
535
536 protected function differentiateWhenEquations
537 "Differentiates a when equation with respect to a cref."
538 input BackendDAE.WhenEquation inWhenEquations;
539 input DAE.ComponentRef inDiffwrtCref;
540 input BackendDAE.DifferentiateInputData inInputData;
541 input BackendDAE.DifferentiationType inDiffType;
542 input AvlTreePathFunction.Tree inFunctionTree;
543 output BackendDAE.WhenEquation outWhenEquations;
544 output AvlTreePathFunction.Tree outFunctionTree;
545 protected
546 BackendDAE.WhenEquation elsewhenPart, delsewhenPart;
547 Option<BackendDAE.WhenEquation> oelsepart;
548 list<BackendDAE.WhenOperator> whenStmtLst, stmtLst;
549 AvlTreePathFunction.Tree funcs;
550 DAE.Exp condition;
551 algorithm
552 17 BackendDAE.WHEN_STMTS(condition = condition, whenStmtLst = whenStmtLst, elsewhenPart = oelsepart) := inWhenEquations;
553 17 funcs := inFunctionTree;
554 stmtLst := {};
555
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 for rs in whenStmtLst loop
556 rs := match rs
557 local
558 DAE.ElementSource src;
559 DAE.Exp right, dright, eleft, dleft;
560
561 case BackendDAE.ASSIGN(eleft, right, src) algorithm
562 17 (dleft, funcs) := differentiateExp(eleft, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
563 17 (dright, funcs) := differentiateExp(right, inDiffwrtCref, inInputData, inDiffType, funcs, defaultMaxIter);
564 17 then BackendDAE.ASSIGN(dleft, dright, src);
565
566 else rs;
567 end match;
568
569 stmtLst := rs::stmtLst;
570 end for;
571
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 14 times.
17 if isSome(oelsepart) then
572 3 SOME(elsewhenPart) := oelsepart;
573 3 (delsewhenPart, funcs) := differentiateWhenEquations(elsewhenPart, inDiffwrtCref, inInputData, inDiffType, funcs);
574 oelsepart := SOME(delsewhenPart);
575 else
576 oelsepart := NONE();
577 end if;
578
579 17 outWhenEquations := BackendDAE.WHEN_STMTS(condition, stmtLst, oelsepart);
580
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 outFunctionTree := funcs;
581 end differentiateWhenEquations;
582
583 // =============================================================================
584 // main differentiation functions
585 // - differentiateExp
586 // - differentiateStatements
587 //
588 // =============================================================================
589
590 protected function differentiateExp
591 input DAE.Exp inExp;
592 input DAE.ComponentRef inDiffwrtCref;
593 input BackendDAE.DifferentiateInputData inInputData;
594 input BackendDAE.DifferentiationType inDiffType;
595 input AvlTreePathFunction.Tree inFunctionTree;
596 input Integer maxIter;
597 output DAE.Exp outDiffedExp;
598 output AvlTreePathFunction.Tree outFunctionTree;
599 protected
600 constant Boolean debug = false;
601 algorithm
602 if debug then print("\nDifferentiate Exp: "+ExpressionBasics.printExpStr(inExp)+
603 " w.r.t. "+ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref)+"\n"); end if;
604
605 /*
606 // This check does not seem to be necessary since looking through the stack of expression seems to stop iteration in most cases, and you get a spam of messages from this check.
607 if maxIter < 1 then
608 Error.addInternalError("Differentiation reached maximum number of iterations ("+String(defaultMaxIter)+"). Current expression is: " + ExpressionBasics.printExpStr(inExp) + " w.r.t. " + ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref), sourceInfo());
609 fail();
610 end if;
611 */
612 (outDiffedExp, outFunctionTree) := match inExp
613 local
614 Absyn.Path p, p1, p2;
615 Boolean b;
616 DAE.CallAttributes attr;
617 DAE.Exp e1, e2, e3, actual, simplified, lambda;
618 DAE.Exp res, res1, res2;
619 AvlTreePathFunction.Tree functionTree;
620 DAE.Operator op;
621 DAE.Type tp;
622 Integer i;
623 String s1, s2, stp;
624 list<String> strLst;
625 list<DAE.Var> varLst;
626 //String se1;
627 list<DAE.Exp> sub, expl;
628 list<list<DAE.Exp>> matrix, dmatrix;
629 DAE.ComponentRef cref;
630 list<DAE.Subscript> subs;
631
632 // types that are not differentiated
633 case DAE.SCONST() then (inExp, inFunctionTree);
634 case DAE.BCONST() then (inExp, inFunctionTree);
635 case DAE.CLKCONST() then (inExp, inFunctionTree);
636 case DAE.ENUM_LITERAL() then (inExp, inFunctionTree);
637
638 // constants => results in zero
639 case DAE.ICONST() then (DAE.ICONST(0), inFunctionTree);
640 case DAE.RCONST() then (DAE.RCONST(0.0), inFunctionTree);
641
642 case DAE.CREF(componentRef=cref, ty=tp) algorithm
643
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2631042 times.
2631048 if ComponentReference.isStartCref(cref) then
644 // differentiate start value
645 6 res := Expression.makeConstZero(tp);
646 6 functionTree := inFunctionTree;
647 else
648 2631042 (res, functionTree) := differentiateCrefs(inExp, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
649 end if;
650 2631040 then (res, functionTree);
651
652 case DAE.BINARY() algorithm
653 2631882 (res, functionTree) := differentiateBinary(inExp, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
654 2616574 res := ExpressionSimplify.simplifyBinaryExp(res);
655 2616574 then (res, functionTree);
656
657 case DAE.UNARY(operator=op, exp=e1) algorithm
658 181715 (res, functionTree) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
659 181320 res := DAE.UNARY(op, res);
660 181320 res := ExpressionSimplify.simplifyUnaryExp(res);
661 181320 then (res, functionTree);
662
663 // boolean expression, e.g. relation, are left as they are
664 case DAE.LBINARY() then (inExp, inFunctionTree);
665 case DAE.LUNARY() then (inExp, inFunctionTree);
666 case DAE.RELATION() then (inExp, inFunctionTree);
667
668 case DAE.IFEXP(expCond=e1, expThen=e2, expElse=e3) algorithm
669 21636 (res1, functionTree) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
670 20809 (res2, functionTree) := differentiateExp(e3, inDiffwrtCref, inInputData, inDiffType, functionTree, maxIter-1);
671 20687 res := DAE.IFEXP(e1, res1, res2);
672 20687 (res, _) := ExpressionSimplify.simplify1(res);
673 20687 then (res, functionTree);
674
675 // differentiate homotopy
676 case DAE.CALL(path=Absyn.IDENT(name="homotopy"), expLst={actual, simplified}) algorithm
677 2040 lambda := Expression.crefExp(ComponentReferenceBasics.makeCrefIdent(BackendDAE.homotopyLambda, DAE.T_REAL_DEFAULT, {}));
678 2040 (e1, functionTree) := differentiateExp(actual, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
679 1222 (e2, functionTree) := differentiateExp(simplified, inDiffwrtCref, inInputData, inDiffType, functionTree, maxIter);
680 1219 e3 := DAE.BINARY(
681 DAE.BINARY(lambda, DAE.MUL(DAE.T_REAL_DEFAULT), e1), /* lambda*e1 */
682 DAE.ADD(DAE.T_REAL_DEFAULT), /* + */
683 DAE.BINARY(DAE.BINARY(DAE.RCONST(1.0),DAE.SUB(DAE.T_REAL_DEFAULT),lambda), DAE.MUL(DAE.T_REAL_DEFAULT), e2) /* (lambda-1)*e2*/
684 );
685 1219 then (e3, functionTree);
686
687 /*
688 do not differentiate semiLinear, if the second or third expression contains the diff cref
689 ticket: #5595
690 */
691 case DAE.CALL(path=Absyn.IDENT(name="semiLinear"), expLst={_, e2, e3})
692 guard(Expression.expHasCref(e2, inDiffwrtCref) or Expression.expHasCref(e3, inDiffwrtCref))
693 1324 then fail();
694
695 // differentiate call
696 case DAE.CALL() algorithm
697 72119 (res, functionTree) := differentiateCalls(inExp, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
698 61478 (res, _) := ExpressionSimplify.simplify1(res);
699 61478 then (res, functionTree);
700
701 case DAE.RECORD(path = p, exps = expl, comp = strLst, ty=tp) algorithm
702 sub := {};
703 186 functionTree := inFunctionTree;
704
2/2
✓ Branch 0 taken 1853 times.
✓ Branch 1 taken 186 times.
2039 for e in expl loop
705 1853 (e1, functionTree) := differentiateExp(e, inDiffwrtCref, inInputData, inDiffType, functionTree, maxIter);
706 sub := e1 :: sub;
707 end for;
708 186 then (DAE.RECORD(p, listReverse(sub), strLst, tp), functionTree);
709
710 case DAE.ARRAY(ty=tp, scalar=b, array=expl) algorithm
711 11266 (expl, functionTree) := List.map3Fold(expl, function differentiateExp(maxIter=maxIter-1), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11266 times.
11266 res := DAE.ARRAY(tp, b, expl);
713 11266 (res, _) := ExpressionSimplify.simplify1(res);
714 11266 then (res, functionTree);
715
716 case DAE.MATRIX(ty=tp, integer=i, matrix=matrix) algorithm
717 8 (dmatrix, functionTree) := List.mapFoldList(matrix, function differentiateExp(maxIter=maxIter-1, inDiffwrtCref = inDiffwrtCref, inInputData = inInputData, inDiffType = inDiffType), inFunctionTree);
718 8 res := DAE.MATRIX(tp, i, dmatrix);
719 8 (res, _) := ExpressionSimplify.simplify1(res);
720 8 then (res, functionTree);
721
722 case DAE.RANGE() then (inExp, inFunctionTree);
723
724 case DAE.TUPLE(PR=expl) algorithm
725 17 (expl, functionTree) := List.map3Fold(expl, function differentiateExp(maxIter=maxIter-1), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
726 17 res := DAE.TUPLE(expl);
727 17 (res, _) := ExpressionSimplify.simplify1(res);
728 17 then (res, functionTree);
729
730 case DAE.CAST(ty=tp, exp=e1) algorithm
731 7552 (res, functionTree) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
732 7552 (res, _) := ExpressionSimplify.simplify1(res);
733 7552 then (DAE.CAST(tp, res), functionTree);
734
735 case DAE.ASUB(exp=e1, sub=subs) algorithm
736 19317 (res1, functionTree) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
737
4/4
✓ Branch 0 taken 18655 times.
✓ Branch 1 taken 18655 times.
✓ Branch 2 taken 18655 times.
✓ Branch 3 taken 18655 times.
37310 res := Expression.makeASUB(res1, list(Expression.getSubscriptExp(s) for s in subs));
738 18655 (res, _) := ExpressionSimplify.simplify1(res);
739 18655 then (res, functionTree);
740
741 case DAE.TSUB(exp=e1, ix=i, ty=tp)
742 algorithm
743 83 (res1, functionTree) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
744
745
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if not referenceEq(e1, res1) then
746 11 res := DAE.TSUB(res1, i, tp);
747 11 (res,_) := ExpressionSimplify.simplify1(res);
748 else
749 res := inExp;
750 end if;
751 11 then (res, functionTree);
752
753 case e1 as DAE.RSUB()
754 algorithm
755 // Try simplifying first.
756 5494 (res, b) := ExpressionSimplify.simplify(e1);
757
2/2
✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 3270 times.
5494 if b then
758 2224 (res, functionTree) := differentiateExp(res, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
759 else
760 3270 (res1, functionTree) := differentiateExp(e1.exp, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
761 // This might not be needed anymore. If it is simplifiable
762 // Then it would have been simplified above.
763
1/2
✓ Branch 0 taken 1603 times.
✗ Branch 1 not taken.
1603 if not referenceEq(e1.exp, res1) then
764 try
765 (expl, strLst) := match res1
766 case DAE.RECORD(exps=expl,comp=strLst) then (expl, strLst);
767 case DAE.CALL(path=p1,expLst=expl,attr=DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path=p2), varLst=varLst)))
768 guard AbsynUtil.pathEqual(p1,p2)
769 ✗ then (expl, list(v.name for v in varLst));
770 end match;
771 ✗ res := listGet(expl, List.position1OnTrue(strLst, stringEq, e1.fieldName));
772 else
773 1603 e1.exp := res1;
774 1603 (res,_) := ExpressionSimplify.simplify1(e1);
775 end try;
776 end if;
777 end if;
778 3827 then (res, functionTree);
779
780 case DAE.SIZE() then (inExp, inFunctionTree);
781
782 case DAE.REDUCTION()
783 algorithm
784 ✗ (res1, functionTree) := differentiateExp(inExp.expr, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter-1);
785
786 ✗ if not referenceEq(inExp.expr, res1) then
787 ✗ res := DAE.REDUCTION(inExp.reductionInfo, res1, inExp.iterators);
788 ✗ res := ExpressionSimplify.simplify1(res);
789 else
790 res := inExp;
791 end if;
792 ✗ then
793 (res, functionTree);
794
795 else algorithm
796 ✗ true := Flags.isSet(Flags.FAILTRACE);
797 ✗ s1 := ExpressionBasics.printExpStr(inExp);
798 ✗ s2 := ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref);
799 ✗ stp := TypesDump.printTypeStr(Expression.typeof(inExp));
800 ✗ Debug.trace("- differentiateExp " + s1 + " type: " + stp + " w.r.t " + s2 + " failed\n");
801 ✗ then fail();
802 end match;
803 if debug then print("Differentiate-Exp-result: " + ExpressionBasics.printExpStr(outDiffedExp) + "\n"); end if;
804 end differentiateExp;
805
806 protected function differentiateStatements
807 input list<DAE.Statement> inStmts;
808 input DAE.ComponentRef inDiffwrtCref;
809 input BackendDAE.DifferentiateInputData inInputData;
810 input BackendDAE.DifferentiationType inDiffType;
811 input list<DAE.Statement> inStmtsAccum;
812 input AvlTreePathFunction.Tree inFunctionTree;
813 input Integer maxIter;
814 output list<DAE.Statement> outDiffedStmts;
815 output AvlTreePathFunction.Tree outFunctionTree;
816 algorithm
817 (outDiffedStmts, outFunctionTree) := matchcontinue inStmts
818 local
819 DAE.ComponentRef cref;
820 DAE.ElementSource source;
821 DAE.Exp lhs, rhs, derivedLHS, derivedRHS;
822 AvlTreePathFunction.Tree functions;
823 DAE.Statement currStatement, stmt, dstmt;
824 DAE.Type type_;
825 BackendDAE.DifferentiateInputData inputData;
826 BackendDAE.Var controlVar;
827 Boolean iterIsArray,initialCall;
828 DAE.Ident ident;
829 DAE.Exp exp;
830 DAE.Exp elseif_exp;
831 DAE.Else elseif_else_;
832 list<DAE.Exp> expLst, dexpLst, expLstRHS;
833 list<tuple<DAE.Exp, DAE.Exp>> exptl;
834 list<DAE.Statement> statementLst, restStatements, derivedStatements1, derivedStatements2, else_statementLst, elseif_statementLst;
835 String s1,s2;
836 list<Option<DAE.Statement>> optDerivedStatements1;
837 list<tuple<DAE.ComponentRef, array<DAE.Exp>>> sub_iters;
838
839 307 case {} then (listReverse(inStmtsAccum), inFunctionTree);
840
841 case (currStatement as DAE.STMT_ASSIGN(type_=type_, exp1=lhs, exp=rhs, source=source))::restStatements
842 algorithm
843 1161 (derivedLHS, functions) := differentiateExp(lhs, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
844 1161 (derivedRHS, functions) := differentiateExp(rhs, inDiffwrtCref, inInputData, inDiffType, functions, maxIter);
845 1161 (derivedRHS,_) := ExpressionSimplify.simplify(derivedRHS);
846 /* if assigment is empty remove derived assignment */
847
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1161 times.
1161 if (Expression.isZero(derivedLHS)) then
848 derivedStatements1 := {currStatement};
849 else
850 1161 derivedStatements1 := {DAE.STMT_ASSIGN(type_, derivedLHS, derivedRHS, source), currStatement};
851 end if;
852 1161 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
853 1161 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
854 then (derivedStatements2, functions);
855
856 case (currStatement as DAE.STMT_TUPLE_ASSIGN(expExpLst= expLst, exp=rhs, source=source))::restStatements
857 algorithm
858 6 (dexpLst,functions) := List.map3Fold(expLst, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
859
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 5 times.
6 (derivedRHS as DAE.TUPLE(expLstRHS), functions) := differentiateExp(rhs, inDiffwrtCref, inInputData, inDiffType, functions, maxIter);
860
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 (DAE.TUPLE(expLstRHS),_) := ExpressionSimplify.simplify(derivedRHS);
861 5 exptl := List.zip(dexpLst, expLstRHS);
862 5 optDerivedStatements1 := List.map2(exptl, makeAssignmentfromTuple, source, inFunctionTree);
863
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 5 times.
20 derivedStatements1 := list(Util.getOption(s) for s guard isSome(s) in optDerivedStatements1);
864 5 derivedStatements2 := listAppend(derivedStatements1, {currStatement});
865 5 derivedStatements1 := listAppend(derivedStatements2, inStmtsAccum);
866 5 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, functions, maxIter);
867 then (derivedStatements2, functions);
868
869 case (currStatement as DAE.STMT_TUPLE_ASSIGN(expExpLst=expLst, exp=rhs as DAE.CALL(), type_= type_, source=source))::restStatements
870 algorithm
871 1 (dexpLst,functions) := List.map3Fold(expLst, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
872
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (derivedRHS as DAE.CALL(attr=DAE.CALL_ATTR(ty=type_)), functions) := differentiateExp(rhs, inDiffwrtCref, inInputData, inDiffType, functions, maxIter);
873 1 optDerivedStatements1 := {SOME(DAE.STMT_TUPLE_ASSIGN(type_, dexpLst, derivedRHS, source))};
874
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
2 derivedStatements1 := list(Util.getOption(s) for s guard isSome(s) in optDerivedStatements1);
875 1 derivedStatements2 := listAppend(derivedStatements1, {currStatement});
876 1 derivedStatements1 := listAppend(derivedStatements2, inStmtsAccum);
877 1 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, functions, maxIter);
878 then (derivedStatements2, functions);
879
880 case (currStatement as DAE.STMT_ASSIGN_ARR(lhs=lhs, exp=rhs, type_=type_, source=source))::restStatements
881 algorithm
882 5 (derivedLHS, functions) := differentiateExp(lhs, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
883 5 (derivedRHS, functions) := differentiateExp(rhs, inDiffwrtCref, inInputData, inDiffType, functions, maxIter);
884 5 (derivedRHS,_) := ExpressionSimplify.simplify(derivedRHS);
885 5 derivedStatements1 := {DAE.STMT_ASSIGN_ARR(type_, derivedLHS, derivedRHS, source), currStatement};
886 5 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
887 5 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
888 then (derivedStatements2, functions);
889
890 case DAE.STMT_FOR(type_=type_, iterIsArray=iterIsArray, iter=ident, range=exp, statementLst=statementLst, source=source, sub_iters=sub_iters)::restStatements
891 algorithm
892 6 cref := ComponentReferenceBasics.makeCrefIdent(ident, DAE.T_INTEGER_DEFAULT, {});
893 6 controlVar := BackendDAE.VAR(cref, BackendDAE.DISCRETE(), DAE.BIDIR(), DAE.NON_PARALLEL(), DAE.T_REAL_DEFAULT, NONE(), NONE(), {}, DAE.emptyElementSource, NONE(), NONE(), NONE(), NONE(), DAE.NON_CONNECTOR(), DAE.NOT_INNER_OUTER(), false, false, false);
894 6 inputData := addGlobalVars({controlVar}, inInputData);
895 6 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inputData, inDiffType, {}, inFunctionTree, maxIter);
896
897
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 derivedStatements1 := {DAE.STMT_FOR(type_, iterIsArray, ident, exp, derivedStatements1, source, sub_iters)};
898
899 6 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
900 6 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
901 then (derivedStatements2, functions);
902
903 case DAE.STMT_IF(exp=exp, statementLst=statementLst, else_=DAE.NOELSE(), source=source)::restStatements
904 algorithm
905 30 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
906 30 derivedStatements1 := {DAE.STMT_IF(exp, derivedStatements1, DAE.NOELSE(), source)};
907 30 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
908 30 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
909 then (derivedStatements2, functions);
910
911 case DAE.STMT_IF(exp=exp, statementLst=statementLst, else_=DAE.ELSEIF(exp=elseif_exp, statementLst=elseif_statementLst, else_=elseif_else_), source=source)::restStatements
912 algorithm
913 29 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
914 58 (derivedStatements2, functions) := differentiateStatements({DAE.STMT_IF(elseif_exp, elseif_statementLst, elseif_else_, source)}, inDiffwrtCref, inInputData, inDiffType, {}, functions, maxIter);
915 29 derivedStatements1 := {DAE.STMT_IF(exp, derivedStatements1, DAE.ELSE(derivedStatements2), source)};
916 29 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
917 29 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
918 then (derivedStatements2, functions);
919
920 case DAE.STMT_IF(exp=exp, statementLst=statementLst, else_=DAE.ELSE(statementLst=else_statementLst), source=source)::restStatements
921 algorithm
922 59 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
923 59 (derivedStatements2, functions) := differentiateStatements(else_statementLst, inDiffwrtCref, inInputData, inDiffType, {}, functions, maxIter);
924 59 derivedStatements1 := {DAE.STMT_IF(exp, derivedStatements1, DAE.ELSE(derivedStatements2), source)};
925 59 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
926 59 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
927 then (derivedStatements2, functions);
928
929 case DAE.STMT_WHILE(exp=exp, statementLst=statementLst, source=source)::restStatements
930 algorithm
931 10 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
932 10 derivedStatements1 := {DAE.STMT_WHILE(exp, derivedStatements1, source)};
933 10 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
934 10 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
935 then (derivedStatements2, functions);
936
937 case DAE.STMT_WHEN(exp=exp, initialCall=initialCall, statementLst=statementLst, elseWhen= NONE(), source=source)::restStatements
938 algorithm
939 4 (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
940
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
6 derivedStatements1 := {DAE.STMT_WHEN(exp, {}, initialCall, derivedStatements1, NONE(), source)};
941 4 derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
942 4 (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
943 then (derivedStatements2, functions);
944
945 case DAE.STMT_WHEN(exp=exp, initialCall=initialCall, statementLst=statementLst, elseWhen= SOME(stmt), source=source)::restStatements
946 algorithm
947 ✗ (derivedStatements1, functions) := differentiateStatements(statementLst, inDiffwrtCref, inInputData, inDiffType, {}, inFunctionTree, maxIter);
948 ✗ ({dstmt}, functions) := differentiateStatements({stmt}, inDiffwrtCref, inInputData, inDiffType, {}, functions, maxIter);
949 ✗ derivedStatements1 := {DAE.STMT_WHEN(exp, {}, initialCall, derivedStatements1, SOME(dstmt), source)};
950 ✗ derivedStatements2 := listAppend(derivedStatements1, inStmtsAccum);
951 ✗ (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements2, functions, maxIter);
952 then (derivedStatements2, functions);
953
954 case (DAE.STMT_ASSERT())::restStatements
955 algorithm
956 36 (derivedStatements1, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, inStmtsAccum, inFunctionTree, maxIter);
957 then (derivedStatements1, functions);
958
959 case (currStatement as DAE.STMT_TERMINATE())::restStatements
960 algorithm
961 derivedStatements1 := currStatement::inStmtsAccum;
962 ✗ (derivedStatements2, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, inFunctionTree, maxIter);
963 then (derivedStatements2, functions);
964
965 case (currStatement as DAE.STMT_REINIT())::restStatements
966 algorithm
967 derivedStatements1 := currStatement::inStmtsAccum;
968 ✗ (derivedStatements1, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, inFunctionTree, maxIter);
969 then (derivedStatements1, functions);
970
971 case (currStatement as DAE.STMT_NORETCALL())::restStatements
972 algorithm
973 derivedStatements1 := currStatement::inStmtsAccum;
974 ✗ (derivedStatements1, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, inFunctionTree, maxIter);
975 then (derivedStatements1, functions);
976
977 case (currStatement as DAE.STMT_RETURN())::restStatements
978 algorithm
979 derivedStatements1 := currStatement::inStmtsAccum;
980 ✗ (derivedStatements1, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, inFunctionTree, maxIter);
981 then (derivedStatements1, functions);
982
983 case (currStatement as DAE.STMT_BREAK())::restStatements
984 algorithm
985 derivedStatements1 := currStatement::inStmtsAccum;
986 ✗ (derivedStatements1, functions) := differentiateStatements(restStatements, inDiffwrtCref, inInputData, inDiffType, derivedStatements1, inFunctionTree, maxIter);
987 then (derivedStatements1, functions);
988
989 else
990 algorithm
991 ✗ if Flags.isSet(Flags.FAILTRACE) then
992 ✗ currStatement::_ := inStmts;
993 ✗ s1 := DAEDump.ppStatementStr(currStatement);
994 ✗ s2 := ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref);
995 ✗ Debug.trace("- differentiateStatements " + s1 + " w.r.t: " + s2 + " failed\n");
996 end if;
997 ✗ then fail();
998 end matchcontinue;
999 end differentiateStatements;
1000
1001 protected function isDiscreteAssignStatment
1002 input DAE.Statement inStmt;
1003 output Boolean out;
1004 algorithm
1005 out := match inStmt
1006 local
1007 DAE.Type tp;
1008 case DAE.STMT_ASSIGN(type_= tp)
1009 ✗ then Types.isDiscreteType(tp);
1010 case DAE.STMT_ASSIGN_ARR(type_= tp)
1011 ✗ then Types.isDiscreteType(tp);
1012 case DAE.STMT_TUPLE_ASSIGN(type_= tp)
1013 ✗ then Types.isDiscreteType(tp);
1014 else false;
1015 end match;
1016 end isDiscreteAssignStatment;
1017
1018
1019 protected function makeAssignmentfromTuple
1020 "Help function for differentiateStatements"
1021 input tuple<DAE.Exp, DAE.Exp> inTpl;
1022 input DAE.ElementSource source;
1023 input AvlTreePathFunction.Tree inFunctionTree;
1024 output Option<DAE.Statement> outStmt;
1025 algorithm
1026 outStmt := match inTpl
1027 local
1028 DAE.Exp e1, e2;
1029 DAE.Type tp;
1030
1031 case (e1 as DAE.CREF(ty=tp), e2)
1032 15 then SOME(DAE.STMT_ASSIGN(tp, e1, e2, source));
1033
1034 case (e1 as DAE.CALL(), e2) guard( Expression.isRecordCall(e1, inFunctionTree))
1035 algorithm
1036 ✗ tp := Expression.typeof(e1);
1037 ✗ then SOME(DAE.STMT_ASSIGN(tp, e1, e2, source));
1038
1039 case (e1, e2) guard Expression.isZero(e1)
1040 then NONE();
1041
1042 end match;
1043 end makeAssignmentfromTuple;
1044
1045 // =============================================================================
1046 // help functions for differentiation
1047 // - differentiateCrefs
1048 // - differentiateCalls
1049 // - differentiateBinary (e.g.: ADD, SUB, MUL, DIV, POW, ...
1050 //
1051 // =============================================================================
1052
1053 protected function differentiateCrefs
1054 input DAE.Exp inExp; // in as DAE.CREF(_)
1055 input DAE.ComponentRef inDiffwrtCref;
1056 input BackendDAE.DifferentiateInputData inInputData;
1057 input BackendDAE.DifferentiationType inDiffType;
1058 input AvlTreePathFunction.Tree inFunctionTree;
1059 input Integer maxIter;
1060 output DAE.Exp outDiffedExp;
1061 output AvlTreePathFunction.Tree outFunctionTree;
1062 protected
1063 constant Boolean debug = false;
1064 algorithm
1065 if debug then print("\nDifferentiate Exp-Cref: "+ExpressionBasics.printExpStr(inExp)+
1066 " w.r.t. "+ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref)+"\n"); end if;
1067 (outDiffedExp, outFunctionTree) :=
1068 matchcontinue(inExp, inDiffwrtCref, inInputData, inDiffType)
1069 local
1070
1071 BackendDAE.DifferentiationType diffType;
1072 Absyn.Path path;
1073
1074 BackendDAE.Variables timevars;
1075 BackendDAE.Variables knvars;
1076 BackendDAE.Var var;
1077 BackendDAE.VarKind kind;
1078
1079 list<BackendDAE.Var> scalarLst;
1080 DAE.Type tp, arrayType, compType;
1081 DAE.Exp e, e1, zero, one;
1082 DAE.Exp res, res1;
1083 DAE.ComponentRef cr, cr1;
1084 list<DAE.Exp> expl, expl_1, diffed_exps = {};
1085
1086 list<DAE.Var> varLst;
1087 list<DAE.ComponentRef> scalarCrefs;
1088
1089 String s1, s2, serr, se1, matrixName;
1090
1091 //
1092 // This part contains general rules for differentation crefs
1093 //
1094
1095 // case for records without expanding the record
1096 case ((DAE.CREF(componentRef = cr,ty = tp as DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_)))), _, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName)), BackendDAE.DIFFERENTIATION_FUNCTION())
1097 algorithm
1098 43 cr := ComponentReference.prependStringCref(BackendDAE.functionDerivativeNamePrefix, cr);
1099 43 cr := ComponentReference.prependStringCref(matrixName, cr);
1100
1101 43 res := Expression.makeCrefExp(cr, tp);
1102 43 then
1103 (res, inFunctionTree);
1104
1105 // case for Records
1106 case ((DAE.CREF(componentRef = cr,ty = tp as DAE.T_COMPLEX(varLst=varLst,complexClassType=ClassInf.RECORD(path)))), _, _, _)
1107 algorithm
1108 44 expl := List.map1(varLst,Expression.generateCrefsExpFromExpVar,cr);
1109 expl_1 := {};
1110 44 outFunctionTree := inFunctionTree;
1111
2/2
✓ Branch 0 taken 443 times.
✓ Branch 1 taken 44 times.
487 for comp in expl loop
1112 443 (e1, outFunctionTree) := differentiateExp(comp, inDiffwrtCref, inInputData, inDiffType, outFunctionTree, maxIter);
1113 443 compType := Expression.typeof(comp);
1114
6/8
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 382 times.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 2 times.
✓ Branch 7 taken 59 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 59 times.
443 if Expression.isZero(e1) and (Types.isString(compType) or Types.isBoolean(compType) or Types.isEnumeration(compType)) then
1115 // a String, Boolean or enumeration component has no derivative and
1116 // is differentiated to a real zero, which is not type correct in
1117 // its slot. Use a zero of its own type instead.
1118 // Only the constant is replaced, a differentiation that yields a
1119 // seed variable, as the Jacobian does, has to be kept as it is.
1120 2 e1 := zeroOfType(compType);
1121 end if;
1122 expl_1 := e1 :: expl_1;
1123 end for;
1124 44 res := DAE.CALL(path,listReverse(expl_1),DAE.CALL_ATTR(tp,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
1125 44 then
1126 (res, outFunctionTree);
1127
1128
1129 // case for array without expanding the array
1130 case (DAE.CREF(componentRef = cr,ty=tp as DAE.T_ARRAY()), _, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName)), BackendDAE.DIFFERENTIATION_FUNCTION())
1131 algorithm
1132 87 cr := ComponentReference.prependStringCref(BackendDAE.functionDerivativeNamePrefix, cr);
1133 87 cr := ComponentReference.prependStringCref(matrixName, cr);
1134
1135 87 res := Expression.makeCrefExp(cr, tp);
1136 87 then
1137 (res, inFunctionTree);
1138
1139 // case for arrays
1140 case ((e as DAE.CREF(ty = DAE.T_ARRAY())), _, _, diffType) guard ( match diffType case BackendDAE.GENERIC_GRADIENT() then false; else true; end match )
1141 algorithm
1142
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1065 times.
1071 true := Flags.isSet(Flags.NF_SCALARIZE); // only expand if scalarize
1143
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1065 times.
1065 (e1,true) := Expression.extendArrExp(e,false);
1144 1065 (res, outFunctionTree) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1145 then
1146 (res, outFunctionTree);
1147
1148 // let WILD() => WILD()
1149 case ((e as DAE.CREF(componentRef = DAE.WILD())), _, _, _)
1150 2 then
1151 (e, inFunctionTree);
1152
1153 // D(x)/dx => 1
1154 case (DAE.CREF(componentRef = cr, ty = tp), _, _, _)
1155 algorithm
1156
2/2
✓ Branch 1 taken 2332320 times.
✓ Branch 2 taken 297910 times.
2630230 true := ComponentReferenceBasics.crefEqual(cr, inDiffwrtCref);
1157 297910 (one,_) := Expression.makeOneExpression(Expression.arrayDimension(tp));
1158 297910 then
1159 (one, inFunctionTree);
1160
1161 // D(y)/dx => 0
1162 case (DAE.CREF(ty = tp), _, _, BackendDAE.SIMPLE_DIFFERENTIATION())
1163 algorithm
1164 1180291 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1165
1166 1180291 then
1167 (zero, inFunctionTree);
1168
1169 // D(y)/dx => 0
1170 case (DAE.CREF(ty = tp), _, _, BackendDAE.DIFF_FULL_JACOBIAN())
1171 algorithm
1172 1002380 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1173 1002380 then
1174 (zero, inFunctionTree);
1175
1176 // Constants, known variables, parameters and discrete variables have a 0-derivative, not the inputs
1177 case ((DAE.CREF(componentRef = cr, ty = tp)), _, BackendDAE.DIFFINPUTDATA(knownVars=SOME(knvars)), _)
1178 algorithm
1179 //print("\nExp-Cref\n known vars: " + ExpressionBasics.printExpStr(e));
1180 131396 (var,_) := BackendVariable.getVarSingle(cr, knvars);
1181
2/2
✓ Branch 1 taken 514 times.
✓ Branch 2 taken 17966 times.
18480 false := BackendVariable.isVarOnTopLevelAndInput(var);
1182 17966 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1183 17966 then
1184 (zero, inFunctionTree);
1185
1186 // d(discrete)/d(x) = 0
1187 case ((DAE.CREF(componentRef = cr,ty = tp)), _, BackendDAE.DIFFINPUTDATA(allVars=SOME(timevars)), BackendDAE.DIFFERENTIATION_TIME())
1188 algorithm
1189 23120 (BackendDAE.VAR(varKind = kind),_) := BackendVariable.getVarSingle(cr, timevars);
1190 //print("\nExp-Cref\n known vars: " + ComponentReferenceBasics.printComponentRefStr(cr));
1191
3/4
✓ Branch 1 taken 23006 times.
✓ Branch 2 taken 16 times.
✓ Branch 4 taken 23006 times.
✗ Branch 5 not taken.
23022 true := listMember(kind,{BackendDAE.DISCRETE()}) or not Types.isReal(tp);
1192 16 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1193 16 then
1194 (zero, inFunctionTree);
1195 //
1196 // This part contains special rules for DIFFERENTIATION_TIME()
1197 //
1198
1199 // special rule for DUMMY_STATES, they become DUMMY_DER
1200 case ((DAE.CREF(componentRef = cr,ty = tp)), _, BackendDAE.DIFFINPUTDATA(dependenentVars=SOME(timevars)), BackendDAE.DIFFERENTIATION_TIME())
1201 algorithm
1202 23511 (var,_) := BackendVariable.getVarSingle(cr, timevars);
1203
1/2
✓ Branch 1 taken 23410 times.
✗ Branch 2 not taken.
23410 true := BackendVariable.isDummyStateVar(var);
1204 ✗ cr := ComponentReference.crefPrefixDer(cr);
1205 ✗ res := Expression.makeCrefExp(cr, tp);
1206 ✗ then
1207 (res, inFunctionTree);
1208
1209 // Continuous-time variables (and for shared eq-systems, also unknown variables: keep them as-they-are)
1210 case ((e as DAE.CREF(componentRef = cr,ty = tp)), _, BackendDAE.DIFFINPUTDATA(dependenentVars=SOME(timevars)), BackendDAE.DIFFERENTIATION_TIME())
1211 algorithm
1212 //({BackendDAE.VAR(varKind = BackendDAE.STATE(index=_))},_) = BackendVariable.getVar(cr, timevars);
1213 23511 BackendVariable.getVarSingle(cr, timevars);
1214 23410 res := DAE.CALL(Absyn.IDENT("der"),{e},DAE.CALL_ATTR(tp,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
1215 23410 then
1216 (res, inFunctionTree);
1217
1218 //
1219 // This part contains special rules for DIFFERENTIATION_FUNCTION()
1220 //
1221 // dependenent variable cref without subscript
1222 case ((DAE.CREF(componentRef = cr,ty=tp)), _, BackendDAE.DIFFINPUTDATA(dependenentVars=SOME(timevars)), BackendDAE.DIFFERENTIATION_FUNCTION())
1223 algorithm
1224 6793 cr1 := ComponentReferenceBasics.crefStripLastSubs(cr);
1225 6793 BackendVariable.getVar(cr1, timevars);
1226 4 (zero, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1227 4 then
1228 (zero, inFunctionTree);
1229
1230 // dependenent variable cref
1231 case ((DAE.CREF(componentRef = cr,ty=tp)), _, BackendDAE.DIFFINPUTDATA(dependenentVars=SOME(timevars)), BackendDAE.DIFFERENTIATION_FUNCTION())
1232 algorithm
1233 6789 BackendVariable.getVar(cr, timevars);
1234 ✗ (zero, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1235 ✗ then
1236 (zero, inFunctionTree);
1237
1238 // all other variable crefs are needed to differentiate
1239 case ((DAE.CREF(componentRef = cr,ty=tp)), _, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName)), BackendDAE.DIFFERENTIATION_FUNCTION())
1240 algorithm
1241 6975 cr := ComponentReference.prependStringCref(BackendDAE.functionDerivativeNamePrefix, cr);
1242 6975 cr := ComponentReference.prependStringCref(matrixName, cr);
1243 6975 res := Expression.makeCrefExp(cr, tp);
1244 6975 then
1245 (res, inFunctionTree);
1246
1247 //
1248 // This part contains special rules for GENERIC_GRADIENT()
1249 //
1250 case (DAE.CREF(ty=tp), DAE.CREF_IDENT(ident="$"), _, BackendDAE.GENERIC_GRADIENT())
1251 algorithm
1252 11533 (res,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1253 11525 then
1254 (res, inFunctionTree);
1255
1256 // d(x)/d(x) => generate seed variables
1257 case ((DAE.CREF(componentRef = cr,ty = tp)), _, BackendDAE.DIFFINPUTDATA(independenentVars=SOME(timevars),matrixName=SOME(matrixName)), BackendDAE.GENERIC_GRADIENT())
1258 algorithm
1259 //true = List.isMemberOnTrue(cr, diffCref, ComponentReferenceBasics.crefEqual);
1260 89644 (scalarLst, _) := BackendVariable.getVar(cr, timevars);
1261 // fix for ticket #7550
1262 // if not all elements (but some of them) are iteration variables
1263 // we scalarize the cref and treat them individually. afterwards
1264 // thread them to an DAE.ARRAY()
1265 18790 arrayType := ComponentReference.crefTypeFull(cr);
1266
2/4
✓ Branch 0 taken 18790 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18790 times.
18790 if not listEmpty(scalarLst) and listLength(scalarLst) <> Types.getDimensionProduct(arrayType) then
1267 ✗ scalarCrefs := ComponentReference.expandCref(cr, true);
1268 ✗ outFunctionTree := inFunctionTree;
1269 ✗ for cref in scalarCrefs loop
1270 ✗ (res1, outFunctionTree) := differentiateCrefs(Expression.crefExp(cref), inDiffwrtCref, inInputData, inDiffType, outFunctionTree, maxIter);
1271 diffed_exps := res1 :: diffed_exps;
1272 end for;
1273 ✗ res := Expression.listToArray(listReverse(diffed_exps), TypesDump.getDimensions(arrayType));
1274 else
1275 18790 cr := createSeedCrefName(cr, matrixName);
1276 18790 res := DAE.CREF(cr, tp);
1277 end if;
1278
1279 18790 then
1280 (res, inFunctionTree);
1281
1282
1283 // d(x)/d(z) = CREF(d(x)/d(dummy))
1284 case (DAE.CREF(componentRef=cr, ty=tp), _, BackendDAE.DIFFINPUTDATA(allVars=SOME(timevars),matrixName=SOME(matrixName)), BackendDAE.GENERIC_GRADIENT())
1285 algorithm
1286
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37553 times.
70854 (var::_, _) := BackendVariable.getVar(cr, timevars);
1287 //Take care! state means => der(state)
1288
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 37533 times.
37553 false := BackendVariable.isStateVar(var);
1289
1290 37533 cr := ComponentReference.createDifferentiatedCrefName(cr, inDiffwrtCref, matrixName);
1291 37533 res := DAE.CREF(cr, tp);
1292 37533 then
1293 (res, inFunctionTree);
1294
1295 // d(x)/d(z) = CREF(d(x)/d(dummy))
1296 case (DAE.CREF(componentRef=cr, ty=tp), _, BackendDAE.DIFFINPUTDATA(dependenentVars=SOME(timevars),matrixName=SOME(matrixName)), BackendDAE.GENERIC_GRADIENT())
1297 algorithm
1298
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
33321 (var::_, _) := BackendVariable.getVar(cr, timevars);
1299 //Take care! state means => der(state)
1300
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 false := BackendVariable.isStateVar(var);
1301
1302 ✗ cr := ComponentReference.createDifferentiatedCrefName(cr, inDiffwrtCref, matrixName);
1303 ✗ res := DAE.CREF(cr, tp);
1304 ✗ then
1305 (res, inFunctionTree);
1306
1307 // d(state)/d(x) = 0
1308 // d(input)/d(x) = 0
1309 // d(all other)/d(x) = 0
1310 case (DAE.CREF(ty=tp), _, _, BackendDAE.GENERIC_GRADIENT())
1311 algorithm
1312 33329 (zero, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1313 33321 then
1314 (zero, inFunctionTree);
1315
1316 // fallback case -> not known cref results in zero
1317 // D(y)/dx => 0
1318 case (DAE.CREF(ty = tp), _, _, BackendDAE.DIFFERENTIATION_TIME())
1319 algorithm
1320 101 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1321 101 then
1322 (zero, inFunctionTree);
1323
1324 else
1325 algorithm
1326
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 true := Flags.isSet(Flags.FAILTRACE);
1327 ✗ s1 := ExpressionBasics.printExpStr(inExp);
1328 ✗ se1 := TypesDump.printTypeStr(Expression.typeof(inExp));
1329 ✗ s2 := ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref);
1330 ✗ serr := stringAppendList({"\n- differentiateCrefs ",s1," type:", se1 ," w.r.t: ",s2," failed\n"});
1331 ✗ Debug.trace(serr);
1332 ✗ then
1333 fail();
1334 end matchcontinue;
1335 if debug then print("Differentiate-ExpCref-result: " + ExpressionBasics.printExpStr(outDiffedExp) + "\n"); end if;
1336 end differentiateCrefs;
1337
1338 public function createDiffedCrefName
1339 input DAE.ComponentRef inCref;
1340 input String inMatrixName;
1341 output DAE.ComponentRef outCref;
1342 protected
1343 list<DAE.Subscript> subs;
1344 algorithm
1345 63 subs := ComponentReference.crefLastSubs(inCref);
1346
1347 63 outCref := ComponentReferenceBasics.crefStripLastSubs(inCref);
1348
1349 63 outCref := ComponentReference.prependStringCref(BackendDAE.functionDerivativeNamePrefix, outCref);
1350 63 outCref := ComponentReference.prependStringCref(inMatrixName, outCref);
1351 63 outCref := ComponentReference.crefSetLastSubs(outCref, subs);
1352 63 outCref := ComponentReference.crefSetLastType(outCref, ComponentReference.crefLastType(inCref));
1353 end createDiffedCrefName;
1354
1355 public function createSeedCrefName
1356 input DAE.ComponentRef inCref;
1357 input String inMatrixName;
1358 output DAE.ComponentRef outCref;
1359 protected
1360 list<DAE.Subscript> subs;
1361 constant Boolean debug = false;
1362 algorithm
1363 if debug then print("inCref: " + ComponentReferenceBasics.printComponentRefStr(inCref) +"\n"); end if;
1364 if debug then print("after full type " + TypesDump.printTypeStr(ComponentReference.crefTypeConsiderSubs(inCref)) + "\n"); end if;
1365 38302 subs := ComponentReference.crefLastSubs(inCref);
1366 38302 outCref := ComponentReferenceBasics.crefStripLastSubs(inCref);
1367 38302 outCref := ComponentReference.crefSetLastType(outCref, DAE.T_UNKNOWN_DEFAULT);
1368 38302 outCref := ComponentReference.joinCrefs(outCref, ComponentReferenceBasics.makeCrefIdent("Seed" + inMatrixName, DAE.T_UNKNOWN_DEFAULT, {}));
1369 if debug then print("after join: " + ComponentReferenceBasics.printComponentRefListStr(ComponentReference.expandCref(outCref, true)) + "\n"); end if;
1370 38302 outCref := ComponentReference.crefSetLastSubs(outCref, subs);
1371 38302 outCref := ComponentReference.crefSetLastType(outCref, ComponentReference.crefLastType(inCref));
1372 if debug then print("outCref: " + ComponentReferenceBasics.printComponentRefStr(outCref) +"\n"); end if;
1373 end createSeedCrefName;
1374
1375 public function isSeedCref
1376 "Returns true if the last cref part is prefixed with 'Seed', i.e. x.y.z.SeedLSJac0"
1377 input DAE.ComponentRef cr;
1378 output Boolean b;
1379 algorithm
1380 b := match cr
1381 ✗ case DAE.CREF_IDENT() then StringUtil.startsWith(cr.ident, "Seed");
1382 ✗ case DAE.CREF_QUAL() then isSeedCref(cr.componentRef);
1383 else false;
1384 end match;
1385 end isSeedCref;
1386
1387 protected function differentiateCalls
1388 "
1389 function: differentiateCalls
1390 "
1391 input DAE.Exp inExp; // in as DAE.CALL(_)
1392 input DAE.ComponentRef inDiffwrtCref;
1393 input BackendDAE.DifferentiateInputData inInputData;
1394 input BackendDAE.DifferentiationType inDiffType;
1395 input AvlTreePathFunction.Tree inFunctionTree;
1396 input Integer maxIter;
1397 output DAE.Exp outDiffedExp;
1398 output AvlTreePathFunction.Tree outFunctionTree;
1399 protected
1400 constant Boolean debug = false;
1401 algorithm
1402 if debug then print("\nDifferentiate Exp-Call: "+ExpressionBasics.printExpStr(inExp)+
1403 " w.r.t. "+ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref)+"\n"); end if;
1404
1405 (outDiffedExp, outFunctionTree) :=
1406 match(inExp, inDiffwrtCref, inInputData, inDiffType)
1407 local
1408
1409 Absyn.Path path;
1410
1411 BackendDAE.Variables timevars;
1412
1413 DAE.CallAttributes attr;
1414 DAE.ComponentRef cr, cj;
1415 DAE.Exp e, e1, zero;
1416 DAE.Exp res, actual, simplified;
1417 DAE.Type tp;
1418 AvlTreePathFunction.Tree funcs;
1419
1420 Integer i;
1421
1422 list<DAE.Exp> expl;
1423
1424
1425 String s1, s2, serr, matrixName, name;
1426
1427 // differentiate homotopy
1428 case (DAE.CALL(path=Absyn.IDENT(name="homotopy"), expLst={actual, simplified}), _, _, _) algorithm
1429 ✗ (e1, funcs) := differentiateExp(actual, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1430 ✗ (_, funcs) := differentiateExp(simplified, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1431 ✗ then (e1, funcs);
1432
1433 /* with previous are the actaully states marked in synchronous */
1434 case (DAE.CALL(path=Absyn.IDENT(name = "previous"), expLst = {DAE.CREF(componentRef=cr, ty=tp)}), _, BackendDAE.DIFFINPUTDATA(independenentVars=SOME(timevars),matrixName=SOME(matrixName)), BackendDAE.GENERIC_GRADIENT()) algorithm
1435
1436 ✗ cr := ComponentReferenceBasics.makeCrefQual(DAE.previousNamePrefix, tp, {}, cr);
1437 ✗ (_::_, _) := BackendVariable.getVar(cr, timevars);
1438 ✗ cr := createSeedCrefName(cr, matrixName);
1439
1440 ✗ res := DAE.CREF(cr, tp);
1441 ✗ then (res, inFunctionTree);
1442
1443 case (DAE.CALL(path = path as Absyn.IDENT(name = "der"),expLst = {e},attr=attr), _, _, BackendDAE.DIFFERENTIATION_TIME())
1444 2113 then
1445 (DAE.CALL(path,{e,DAE.ICONST(2)},attr), inFunctionTree);
1446
1447 case (DAE.CALL(path = (path as Absyn.IDENT(name = "der")),expLst = {e,DAE.ICONST(i)},attr=attr), _, _, BackendDAE.DIFFERENTIATION_TIME())
1448 algorithm
1449 ✗ i := i + 1;
1450 ✗ then
1451 (DAE.CALL(path,{e,DAE.ICONST(i)},attr), inFunctionTree);
1452
1453 // special case for daeMode:
1454 // der(x) gets differentiated to $cj * x.Seed
1455 // (cj aka alpha, provided by the dae mode integrator)
1456 case (DAE.CALL(path = Absyn.IDENT(name = "der"),expLst = {e}), _, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName)), BackendDAE.GENERIC_GRADIENT(true))
1457 algorithm
1458 cj := DAE.CREF_IDENT(SymbolicJacobian.DAE_CJ, DAE.T_REAL_DEFAULT, {});
1459 ✗ cr := Expression.expCref(e);
1460 ✗ tp := Expression.typeof(e);
1461 ✗ cr := createSeedCrefName(cr, matrixName);
1462 ✗ res := Expression.makeCrefExp(cr, tp);
1463 ✗ res := DAE.BINARY(Expression.makeCrefExp(cj, DAE.T_REAL_DEFAULT), DAE.MUL(DAE.T_REAL_DEFAULT), res);
1464 ✗ then
1465 (res, inFunctionTree);
1466
1467 case (DAE.CALL(path=Absyn.IDENT(name = "der"),expLst = {e}), _, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName)), _)
1468 algorithm
1469 519 cr := Expression.expCref(e);
1470 519 tp := Expression.typeof(e);
1471 519 cr := ComponentReference.crefPrefixDer(cr);
1472 519 cr := ComponentReference.createDifferentiatedCrefName(cr, inDiffwrtCref, matrixName);
1473 519 res := Expression.makeCrefExp(cr, tp);
1474
1475
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 519 times.
519 if ComponentReferenceBasics.crefEqual(DAE.CREF_IDENT("$",DAE.T_REAL_DEFAULT,{}), inDiffwrtCref) then
1476 ✗ (res,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1477 end if;
1478 519 then
1479 (res, inFunctionTree);
1480
1481 /* Differentiate with respect to DAE.CREF_IDENT(ident="$") demands zero expressions */
1482 case (DAE.CALL(path=Absyn.IDENT(name = "der"),expLst = {e}), DAE.CREF_IDENT(ident="$"), _, _)
1483 algorithm
1484 ✗ (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(Expression.typeof(e)));
1485 ✗ then
1486 (zero, inFunctionTree);
1487
1488 /* Exclude records here, they are handled component-wise in differentiateFunctionCall
1489 and builtin function are handled in differentiateCall* */
1490 case (e as DAE.CALL(attr=DAE.CALL_ATTR(ty=tp,builtin=false)), DAE.CREF_IDENT(ident="$"), _, _)
1491 guard ( not Expression.isRecordCall(e, inFunctionTree) )
1492 algorithm
1493 4 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1494 4 then
1495 (zero, inFunctionTree);
1496
1497 case (e as DAE.CALL(attr=DAE.CALL_ATTR(ty=tp,builtin=false)), _, _, BackendDAE.DIFF_FULL_JACOBIAN())
1498 guard not (Expression.isRecordCall(e, inFunctionTree) or expHasRelatedCref(e, inDiffwrtCref))
1499 algorithm
1500 1420 (zero,_) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1501 1420 then
1502 (zero, inFunctionTree);
1503
1504 // differentiate builtin calls with 1 argument
1505 case (DAE.CALL(path=Absyn.IDENT(name),attr=DAE.CALL_ATTR(builtin=true),expLst={e}), _, _, _)
1506 algorithm
1507 18301 (res, funcs) := differentiateCallExp1Arg(name, e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1508 then (res, funcs);
1509
1510 // differentiate builtin calls with N arguments with match
1511 // der(arctan2(y,0)) = der(sign(y)*pi/2) = 0
1512 case (DAE.CALL(path=Absyn.IDENT("atan2"),attr=DAE.CALL_ATTR(builtin=true),expLst={_,e1 as DAE.RCONST(real=0.0)}), _, _, _)
1513 ✗ then
1514 (e1, inFunctionTree);
1515
1516 // differentiate builtin calls with N arguments as match
1517 case (DAE.CALL(path=Absyn.IDENT(name),attr=(attr as DAE.CALL_ATTR(builtin=true)),expLst= (expl as (_::_::_))), _, _, _)
1518 algorithm
1519 7438 (res, funcs) := differentiateCallExpNArg(name, expl, attr, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1520 then (res, funcs);
1521
1522 case (e as DAE.CALL(), _, _, _)
1523 algorithm
1524 42324 (e1, funcs) := differentiateFunctionCall(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1525 33587 (e1,_,_,_) := Inline.inlineExp(e1,(SOME(funcs),{DAE.NORM_INLINE()}),DAE.emptyElementSource/*TODO:Can we propagate source?*/);
1526 33587 then
1527 (e1, funcs);
1528 /*
1529 case (e as DAE.CALL(expLst = _), _, _, _, _)
1530 algorithm
1531 Error.addMessage(Error.NON_EXISTING_DERIVATIVE, {ExpressionBasics.printExpStr(e), ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref)});
1532 then
1533 fail();
1534 */
1535 else
1536 algorithm
1537 ✗ true := Flags.isSet(Flags.FAILTRACE);
1538 ✗ s1 := ExpressionBasics.printExpStr(inExp);
1539 ✗ s2 := ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref);
1540 ✗ serr := stringAppendList({"\n- Function differentiateCalls failed. differentiateExp ",s1," w.r.t: ",s2," failed\n"});
1541 ✗ Debug.trace(serr);
1542 ✗ then
1543 fail();
1544 end match;
1545 if debug then print("Differentiate-ExpCall-result: " + ExpressionBasics.printExpStr(outDiffedExp) + "\n"); end if;
1546 end differentiateCalls;
1547
1548 protected function expHasRelatedCref
1549 "Returns true if the expression contains a cref that is cr, an array or
1550 record containing cr, or a part of cr, ignoring subscripts."
1551 input DAE.Exp exp;
1552 input DAE.ComponentRef cr;
1553 output Boolean hasCref;
1554 algorithm
1555 49453 (_, hasCref) := Expression.traverseExpTopDown(exp, function expHasRelatedCrefWork(cr = cr), false);
1556 end expHasRelatedCref;
1557
1558 protected function expHasRelatedCrefWork
1559 input output DAE.Exp exp;
1560 output Boolean cont;
1561 input output Boolean hasCref;
1562 input DAE.ComponentRef cr;
1563 algorithm
1564
2/2
✓ Branch 0 taken 742924 times.
✓ Branch 1 taken 78076 times.
821000 if not hasCref then
1565 hasCref := match exp
1566
9/10
✓ Branch 1 taken 200753 times.
✓ Branch 2 taken 28151 times.
✓ Branch 4 taken 200753 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 199938 times.
✓ Branch 8 taken 815 times.
✓ Branch 10 taken 7344 times.
✓ Branch 11 taken 192594 times.
✓ Branch 13 taken 166 times.
✓ Branch 14 taken 7993 times.
228904 case DAE.CREF() then ComponentReferenceBasics.crefEqualWithoutSubs(exp.componentRef, cr) or
1567 ComponentReferenceBasics.crefPrefixOfIgnoreSubscripts(cr, exp.componentRef) or
1568 (Types.isArray(exp.ty) or Types.isComplexType(exp.ty)) and
1569 ComponentReferenceBasics.crefPrefixOfIgnoreSubscripts(exp.componentRef, cr);
1570 else false;
1571 end match;
1572 end if;
1573
1/2
✓ Branch 0 taken 821000 times.
✗ Branch 1 not taken.
821000 cont := not hasCref;
1574 end expHasRelatedCrefWork;
1575
1576 protected function differentiateCallExp1Arg
1577 "This function differentiates built-in call expressions with 1 argument
1578 with respect to a given variable,given as third argument."
1579 input String name;
1580 input DAE.Exp exp;
1581 input DAE.ComponentRef inDiffwrtCref;
1582 input BackendDAE.DifferentiateInputData inInputData;
1583 input BackendDAE.DifferentiationType inDiffType;
1584 input AvlTreePathFunction.Tree inFuncs;
1585 input Integer maxIter;
1586 output DAE.Exp outDiffedExp;
1587 output AvlTreePathFunction.Tree outFunctionTree;
1588 algorithm
1589 (outDiffedExp,outFunctionTree) := match (name, exp)
1590 local
1591 DAE.Exp exp_1,exp_2;
1592 AvlTreePathFunction.Tree funcs;
1593 DAE.Type tp;
1594 list<DAE.Exp> expl;
1595
1596 case ("pre",_) algorithm
1597 25 tp := Expression.typeof(exp);
1598 25 exp_1 := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1599 25 then (exp_1, inFuncs);
1600
1601 case ("previous",_) algorithm
1602 9 tp := Expression.typeof(exp);
1603 9 exp_1 := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1604 9 then (exp_1, inFuncs);
1605
1606 case ("$getPart",_) algorithm
1607 2 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1608 then (exp_1, funcs);
1609
1610 ✗ case ("firstTick",_) then (exp, inFuncs);
1611 ✗ case ("interval",_) then (exp, inFuncs);
1612
1613 // diff(sin(x)) = cos(x)*der(x)
1614 case ("sin",_)
1615 algorithm
1616 3338 tp := Expression.typeof(exp);
1617 3338 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1618 3338 exp_2 := Expression.makePureBuiltinCall("cos", {exp}, tp);
1619 3338 then (DAE.BINARY(exp_2, DAE.MUL(tp), exp_1), funcs);
1620
1621 // diff(cos(x)) = -sin(x)*der(x)
1622 case ("cos",_)
1623 algorithm
1624 3556 tp := Expression.typeof(exp);
1625 3556 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1626 3553 exp_2 := Expression.makePureBuiltinCall("sin", {exp}, tp);
1627 3553 then (DAE.BINARY(DAE.UNARY(DAE.UMINUS(tp),exp_2), DAE.MUL(tp), exp_1), funcs);
1628
1629 // diff(tan(x)) = (2*der(x)/(cos(2*x)+1))
1630 case ("tan",_)
1631 algorithm
1632 11 tp := Expression.typeof(exp);
1633 11 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1634 22 exp_2 := Expression.makePureBuiltinCall("cos", {DAE.BINARY(DAE.RCONST(2.0),DAE.MUL(tp),exp)}, tp);
1635 11 then
1636 (DAE.BINARY(
1637 DAE.BINARY(DAE.RCONST(2.0), DAE.MUL(tp), exp_1), DAE.DIV(tp),
1638 DAE.BINARY(exp_2, DAE.ADD(tp), DAE.RCONST(1.0))), funcs);
1639
1640 // der(arcsin(x)) = der(x)/sqrt(1-x^2)
1641 case ("asin",_)
1642 algorithm
1643 ✗ tp := Expression.typeof(exp);
1644 ✗ (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1645 ✗ exp_2 := Expression.makePureBuiltinCall("sqrt", {DAE.BINARY(DAE.RCONST(1.0),DAE.SUB(tp),DAE.BINARY(exp,DAE.MUL(tp),exp))}, tp);
1646 ✗ then (DAE.BINARY(exp_1,DAE.DIV(tp),exp_2), funcs);
1647
1648 // der(arccos(x)) = -der(x)/sqrt(1-x^2)
1649 case ("acos",_)
1650 algorithm
1651 42 tp := Expression.typeof(exp);
1652 42 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1653 84 exp_2 := Expression.makePureBuiltinCall("sqrt", {DAE.BINARY(DAE.RCONST(1.0),DAE.SUB(tp),DAE.BINARY(exp,DAE.MUL(tp),exp))}, tp);
1654 42 then (DAE.UNARY(DAE.UMINUS(tp),DAE.BINARY(exp_1,DAE.DIV(tp),exp_2)), funcs);
1655
1656 // der(arctan(x)) = der(x)/(1+x^2)
1657 case ("atan",_)
1658 algorithm
1659 39 tp := Expression.typeof(exp);
1660 39 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1661 39 then (DAE.BINARY(exp_1,DAE.DIV(tp),DAE.BINARY(DAE.RCONST(1.0),DAE.ADD(tp),DAE.BINARY(exp,DAE.MUL(tp),exp))), funcs);
1662
1663 // der(sinh(x)) => der(x)sinh(x)
1664 case ("sinh",_)
1665 algorithm
1666 4 tp := Expression.typeof(exp);
1667 4 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1668 4 exp_2 := Expression.makePureBuiltinCall("cosh",{exp},tp);
1669 4 then (DAE.BINARY(exp_1,DAE.MUL(tp),exp_2), funcs);
1670
1671 // der(cosh(x)) => der(x)sinh(x)
1672 case ("cosh",_)
1673 algorithm
1674 36 tp := Expression.typeof(exp);
1675 36 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1676 36 exp_2 := Expression.makePureBuiltinCall("sinh",{exp},tp);
1677 36 then (DAE.BINARY(exp_1,DAE.MUL(tp),exp_2), funcs);
1678
1679 // der(tanh(x)) = der(x) / cosh(x)^2
1680 case ("tanh",_)
1681 algorithm
1682 14 tp := Expression.typeof(exp);
1683 14 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType, inFuncs, maxIter);
1684 14 exp_2 := Expression.makePureBuiltinCall("cosh", {exp}, tp);
1685 14 then (DAE.BINARY(exp_1, DAE.DIV(tp),
1686 DAE.BINARY(exp_2, DAE.POW(tp), DAE.RCONST(2.0))), funcs);
1687
1688 // diff(exp(x)) = der(x)*exp(x)
1689 case ("exp",_)
1690 algorithm
1691 967 tp := Expression.typeof(exp);
1692 967 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1693 966 exp_2 := Expression.makePureBuiltinCall("exp",{exp},tp);
1694 966 then (DAE.BINARY(exp_2, DAE.MUL(tp), exp_1), funcs);
1695
1696 // diff(log(x)) = der(x)/x
1697 case ("log",_)
1698 algorithm
1699 2278 tp := Expression.typeof(exp);
1700 2278 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1701 2275 then
1702 (DAE.BINARY(exp_1, DAE.DIV(tp), exp), funcs);
1703
1704 // diff(log10(x)) = der(x)/(x*log(10))
1705 case ("log10",_)
1706 algorithm
1707 97 tp := Expression.typeof(exp);
1708 97 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1709 97 exp_2 := Expression.makePureBuiltinCall("log",{DAE.RCONST(10.0)},tp);
1710 97 then
1711 (DAE.BINARY(exp_1, DAE.DIV(tp),
1712 DAE.BINARY(exp, DAE.MUL(tp), exp_2)), funcs);
1713
1714 // diff(sqrt(x)) = der(x)/(2*sqrt(x))
1715 case ("sqrt",_)
1716 algorithm
1717 1296 tp := Expression.typeof(exp);
1718 1296 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1719 1296 exp_2 := Expression.makePureBuiltinCall("sqrt",{exp},tp);
1720 1296 then
1721 (DAE.BINARY(exp_1, DAE.DIV(tp),
1722 DAE.BINARY(DAE.RCONST(2.0), DAE.MUL(tp), exp_2)), funcs);
1723
1724 // der(abs(x)) = sign(x)der(x)
1725 case ("abs",_)
1726 algorithm
1727 2841 tp := Expression.typeof(exp);
1728 2841 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1729 2829 exp_2 := Expression.makePureBuiltinCall("sign",{exp}, tp);
1730 2829 then (DAE.BINARY(exp_2, DAE.MUL(tp), exp_1), funcs);
1731
1732 case ("sign",_)
1733 algorithm
1734 287 tp := Expression.typeof(exp);
1735 287 (exp_1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1736 287 then (exp_1, inFuncs);
1737
1738 case ("transpose",_)
1739 algorithm
1740 5 tp := Expression.typeof(exp);
1741 5 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1742 3 exp_2 := Expression.makePureBuiltinCall("transpose",{exp_1},tp);
1743 3 then
1744 (exp_2, funcs);
1745
1746 case ("sum",_)
1747 algorithm
1748 1746 tp := Expression.typeof(exp);
1749 1746 (exp_1, funcs) := differentiateExp(exp, inDiffwrtCref, inInputData,inDiffType,inFuncs, maxIter);
1750 1731 exp_2 := Expression.makePureBuiltinCall("sum",{exp_1},tp);
1751 1731 then
1752 (exp_2, funcs);
1753
1754 case ("max",DAE.ARRAY(array=expl,ty=tp))
1755 algorithm
1756 ✗ tp := Types.arrayElementType(tp);
1757 ✗ exp_1 := createFromNCall2ArgsCall("max", expl, tp);
1758 ✗ (exp_2, funcs) := differentiateExp(exp_1, inDiffwrtCref, inInputData, inDiffType, inFuncs, maxIter);
1759 then
1760 (exp_2, funcs);
1761
1762 case ("min",DAE.ARRAY(array=expl,ty=tp))
1763 algorithm
1764 ✗ tp := Types.arrayElementType(tp);
1765 ✗ exp_1 := createFromNCall2ArgsCall("min", expl, tp);
1766 ✗ (exp_2, funcs) := differentiateExp(exp_1, inDiffwrtCref, inInputData, inDiffType, inFuncs, maxIter);
1767 then
1768 (exp_2, funcs);
1769
1770 case ("floor",_)
1771 algorithm
1772 2 tp := Expression.typeof(exp);
1773 2 (exp_1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1774 2 then
1775 (exp_1, inFuncs);
1776
1777 case ("ceil",_)
1778 algorithm
1779 1 tp := Expression.typeof(exp);
1780 1 (exp_1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1781 1 then
1782 (exp_1, inFuncs);
1783
1784 case ("integer",_)
1785 algorithm
1786 17 tp := Expression.typeof(exp);
1787 17 (exp_1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1788 17 then
1789 (exp_1, inFuncs);
1790
1791 end match;
1792 end differentiateCallExp1Arg;
1793
1794 protected function createFromNCall2ArgsCall
1795 input String funcName;
1796 input list<DAE.Exp> expl;
1797 input DAE.Type tp;
1798 output DAE.Exp result;
1799 protected
1800 DAE.Exp e1,e2;
1801 list<DAE.Exp> rest;
1802 algorithm
1803 ✗ e1::e2::rest := expl;
1804 ✗ result := Expression.makePureBuiltinCall(funcName,{e1,e2},tp);
1805 ✗ for elem in rest loop
1806 ✗ result := Expression.makePureBuiltinCall(funcName,{result,elem},tp);
1807 end for;
1808 end createFromNCall2ArgsCall;
1809
1810 protected function differentiateCallExpNArg "
1811 This function differentiates built-in call expressions with N argument
1812 with respect to a given variable,given as third argument."
1813 input String name;
1814 input list<DAE.Exp> inExpl;
1815 input DAE.CallAttributes inAttr;
1816 input DAE.ComponentRef inDiffwrtCref;
1817 input BackendDAE.DifferentiateInputData inInputData;
1818 input BackendDAE.DifferentiationType inDiffType;
1819 input AvlTreePathFunction.Tree inFunctionTree;
1820 input Integer maxIter;
1821 output DAE.Exp outDiffedExp;
1822 output AvlTreePathFunction.Tree outFunctionTree;
1823 algorithm
1824 (outDiffedExp,outFunctionTree) := match(name,inExpl,inAttr)
1825 local
1826 DAE.Exp e, e1, e2, e3, e4, etmp;
1827 DAE.Exp res, res1, res2;
1828 DAE.Type tp;
1829 AvlTreePathFunction.Tree funcs;
1830 Integer i;
1831
1832 case ("smooth",{DAE.ICONST(i),e2}, DAE.CALL_ATTR(ty=tp))
1833 algorithm
1834 914 (res1, funcs) := differentiateExp(e2,inDiffwrtCref,inInputData,inDiffType,inFunctionTree, maxIter);
1835 825 e1 := DAE.ICONST(i-1);
1836
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 608 times.
1042 res2 := if intGe(i,1) then Expression.makePureBuiltinCall("smooth", {e1, res1}, tp) else res1;
1837 825 then
1838 (res2, funcs);
1839
1840 case ("noEvent",{e1}, DAE.CALL_ATTR(ty=tp))
1841 algorithm
1842 ✗ (res1, funcs) := differentiateExp(e1,inDiffwrtCref,inInputData,inDiffType,inFunctionTree, maxIter);
1843 ✗ res1 := Expression.makePureBuiltinCall("noEvent", {res1}, tp);
1844 ✗ then
1845 (res1, funcs);
1846
1847 // der(arctan2(x,y)) = der(x/y)/(1+(x/y)^2)
1848 case ("atan2",{e,e1}, DAE.CALL_ATTR(ty=tp))
1849 algorithm
1850 396 e2 := Expression.makeDiv(e,e1);
1851 396 (res1, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1852 396 res2 := Expression.addNoEventToRelations(DAE.IFEXP(DAE.RELATION(e1,DAE.EQUAL(tp),DAE.RCONST(0.0),-1,NONE()),
1853 e1,
1854 DAE.BINARY(res1, DAE.DIV(tp), DAE.BINARY(DAE.RCONST(1.0), DAE.ADD(tp), DAE.BINARY(e2, DAE.MUL(tp),e2)))
1855 ));
1856 396 then
1857 (res2, funcs);
1858
1859 // der(semiLinear(x,a,b)) = if (x>=0) then a*x else b*x -> if (x>=0) then da*x+a*dx else db*x+b*dx
1860 case ("semiLinear", {e,e1,e2}, DAE.CALL_ATTR(ty=tp))
1861 algorithm
1862 212 (res, funcs) := differentiateExp(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1863 212 (res1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1864 212 (res2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1865 212 res1 := Expression.expAdd(Expression.expMul(res1, e),Expression.expMul(e1, res));
1866 212 res2 := Expression.expAdd(Expression.expMul(res2, e),Expression.expMul(e2, res));
1867 212 (res, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1868 212 res := DAE.RELATION(e, DAE.GREATEREQ(tp), res, -1, NONE());
1869 212 then
1870 (DAE.IFEXP(res, res1, res2), funcs);
1871
1872 case ("cross", {e1,e2}, DAE.CALL_ATTR(ty=tp))
1873 algorithm
1874 70 (res1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1875 70 (res2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1876 70 res2 := Expression.makePureBuiltinCall("cross",{e1,res2},tp);
1877 70 res1 := Expression.makePureBuiltinCall("cross",{res1,e2},tp);
1878 70 then
1879 (DAE.BINARY(res2, DAE.ADD_ARR(tp), res1), funcs);
1880
1881 case ("max", {e1,e2}, DAE.CALL_ATTR(ty=tp))
1882 algorithm
1883 3487 (res1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1884 3487 (res2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1885 6956 then
1886 (DAE.IFEXP(DAE.CALL(Absyn.IDENT("noEvent"),{DAE.RELATION(e1,DAE.GREATER(tp),e2,-1,NONE())},DAE.callAttrBuiltinBool), res1, res2), funcs);
1887
1888 case ("min", {e1,e2}, DAE.CALL_ATTR(ty=tp))
1889 algorithm
1890 2349 (res1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1891 2267 (res2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
1892 4534 then
1893 (DAE.IFEXP(DAE.CALL(Absyn.IDENT("noEvent"),{DAE.RELATION(e1,DAE.LESS(tp),e2,-1,NONE())},DAE.callAttrBuiltinBool), res1, res2), funcs);
1894
1895 // diff(div(e1,e2)) = diff(if noEvent(e1 > 0) then floor(e1/e2) else ceil(e1/e2)) = 0.0;
1896 case ("div", {_,_}, DAE.CALL_ATTR(ty=tp))
1897 algorithm
1898 3 (res1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1899 3 then
1900 (res1, inFunctionTree);
1901
1902 // diff(mod(e1,e2)) = diff(e1 - e2*floor(e1/e2))
1903 case ("mod", {e1,e2}, DAE.CALL_ATTR(ty=tp))
1904 algorithm
1905 2 etmp := Expression.makePureBuiltinCall("floor", {DAE.BINARY(e1, DAE.DIV(tp), e2)}, tp);
1906 1 e := DAE.BINARY(e1, DAE.SUB(tp), DAE.BINARY(e2, DAE.MUL(tp), etmp));
1907 1 (res1, funcs) := differentiateExp(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1908 then
1909 (res1, funcs);
1910
1911 // diff(rem(e1,e2)) = diff(e1 -div(e1,e2)*e2)
1912 case ("rem", {e1,e2}, DAE.CALL_ATTR(ty=tp))
1913 algorithm
1914 ✗ (res1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1915 then
1916 (res1, funcs);
1917
1918 case ("delay", {_, e2, e3, e4}, DAE.CALL_ATTR(ty=tp))
1919 algorithm
1920 res1 := match inDiffType
1921 case BackendDAE.DIFFERENTIATION_TIME() then DAE.RCONST(1.0);
1922 else DAE.RCONST(0.0);
1923 end match;
1924 ✗ (res2, funcs) := differentiateExp(e3, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
1925 ✗ res2 := DAE.BINARY(res1, DAE.SUB(tp), res2);
1926 ✗ (res2, _) := ExpressionSimplify.simplify(res2);
1927 ✗ if Expression.isZero(res2) then
1928 ✗ res := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1929 else
1930 // differentiate delayed expression w.r.t. time
1931 ✗ (e, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, BackendDAE.DIFFERENTIATION_TIME(), funcs, maxIter);
1932 ✗ e := DAE.CALL(Absyn.IDENT(name), {DAE.ICONST(-1), e, e3, e4}, inAttr);
1933 ✗ res := DAE.BINARY(res2, DAE.MUL(tp), e);
1934 ✗ (res, _) := ExpressionSimplify.simplify(res);
1935 end if;
1936 ✗ then
1937 (res, funcs);
1938
1939 case ("sample", _, DAE.CALL_ATTR(ty=tp))
1940 algorithm
1941 6 (res1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1942 6 then
1943 (res1, inFunctionTree);
1944
1945 /* floor ceil and interger are expanded by the zeroCrossing index, thus they
1946 have 2 arguments */
1947 case ("floor", _, DAE.CALL_ATTR(ty=tp))
1948 algorithm
1949 ✗ (res1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1950 ✗ then
1951 (res1, inFunctionTree);
1952
1953 case ("ceil", _, DAE.CALL_ATTR(ty=tp))
1954 algorithm
1955 ✗ (res1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1956 ✗ then
1957 (res1, inFunctionTree);
1958
1959 case ("integer", _, DAE.CALL_ATTR(ty=tp))
1960 algorithm
1961 ✗ (res1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
1962 ✗ then
1963 (res1, inFunctionTree);
1964
1965 end match;
1966 end differentiateCallExpNArg;
1967
1968 protected function differentiateBinary
1969 input DAE.Exp inExp; // in as DAE.BINARY(_)
1970 input DAE.ComponentRef inDiffwrtCref;
1971 input BackendDAE.DifferentiateInputData inInputData;
1972 input BackendDAE.DifferentiationType inDiffType;
1973 input AvlTreePathFunction.Tree inFunctionTree;
1974 input Integer maxIter;
1975 output DAE.Exp outDiffedExp;
1976 output AvlTreePathFunction.Tree outFunctionTree;
1977 algorithm
1978 (outDiffedExp, outFunctionTree) := match inExp
1979 local
1980
1981
1982
1983 DAE.ComponentRef cr;
1984 DAE.Exp e, e0, e1, e2, zero, etmp;
1985 DAE.Exp de1, de2;
1986 AvlTreePathFunction.Tree funcs;
1987 DAE.Type tp, tp1;
1988
1989 Integer i;
1990
1991
1992
1993 Real r;
1994
1995 String s1, s2, serr;
1996
1997 case DAE.BINARY(exp1 = e1,operator = DAE.ADD(ty = tp),exp2 = e2)
1998 algorithm
1999 855265 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2000 854098 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2001 853696 then
2002 (DAE.BINARY(de1,DAE.ADD(tp),de2), funcs);
2003
2004 case DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARR(ty = tp),exp2 = e2)
2005 algorithm
2006 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2007 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2008 ✗ then
2009 (DAE.BINARY(de1,DAE.ADD_ARR(tp),de2), funcs);
2010
2011 case DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARRAY_SCALAR(ty = tp),exp2 = e2)
2012 algorithm
2013 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2014 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2015 ✗ then
2016 (DAE.BINARY(de1,DAE.ADD_ARRAY_SCALAR(tp),de2), funcs);
2017
2018 case DAE.BINARY(exp1 = e1,operator = DAE.SUB(ty = tp),exp2 = e2)
2019 algorithm
2020 617006 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2021 614589 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2022 606636 then
2023 (DAE.BINARY(de1,DAE.SUB(tp),de2), funcs);
2024
2025 case DAE.BINARY(exp1 = e1,operator = DAE.SUB_ARR(ty = tp),exp2 = e2)
2026 algorithm
2027 58 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2028 57 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2029 27 then
2030 (DAE.BINARY(de1,DAE.SUB_ARR(tp),de2), funcs);
2031
2032 case DAE.BINARY(exp1 = e1,operator = DAE.SUB_SCALAR_ARRAY(ty = tp),exp2 = e2)
2033 algorithm
2034 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2035 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2036 ✗ then
2037 (DAE.BINARY(de1,DAE.SUB_SCALAR_ARRAY(tp),de2), funcs);
2038
2039 // fg\' + f\'g
2040 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(ty = tp),exp2 = e2)
2041 algorithm
2042 1049079 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2043 1047620 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2044 1046353 then
2045 (DAE.BINARY(DAE.BINARY(e1,DAE.MUL(tp),de2),DAE.ADD(tp),
2046 DAE.BINARY(de1,DAE.MUL(tp),e2)), funcs);
2047
2048 // fg\' + f\'g
2049 case DAE.BINARY(exp1 = e1,operator = DAE.MUL_ARR(ty = tp),exp2 = e2)
2050 algorithm
2051 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2052 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2053 ✗ then
2054 (DAE.BINARY(DAE.BINARY(e1,DAE.MUL_ARR(tp),de2),DAE.ADD(tp),
2055 DAE.BINARY(de1,DAE.MUL_ARR(tp),e2)), funcs);
2056
2057 // fg\' + f\'g
2058 case DAE.BINARY(exp1 = e1,operator = DAE.MUL_ARRAY_SCALAR(ty = tp),exp2 = e2)
2059 algorithm
2060 37 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2061 21 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2062 21 then
2063 (DAE.BINARY(DAE.BINARY(e1,DAE.MUL_ARRAY_SCALAR(tp),de2),DAE.ADD_ARR(tp),
2064 DAE.BINARY(de1,DAE.MUL_ARRAY_SCALAR(tp),e2)), funcs);
2065
2066 // fg\' + f\'g
2067 case DAE.BINARY(exp1 = e1,operator = DAE.MUL_SCALAR_PRODUCT(ty = tp),exp2 = e2)
2068 algorithm
2069 160 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2070 160 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2071 160 then
2072 (DAE.BINARY(DAE.BINARY(e1,DAE.MUL_SCALAR_PRODUCT(tp),de2),DAE.ADD(tp),
2073 DAE.BINARY(de1,DAE.MUL_SCALAR_PRODUCT(tp),e2)), funcs);
2074
2075 // fg\' + f\'g
2076 case DAE.BINARY(exp1 = e1,operator = DAE.MUL_MATRIX_PRODUCT(ty = tp),exp2 = e2)
2077 algorithm
2078 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2079 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2080 ✗ then
2081 (DAE.BINARY(DAE.BINARY(e1,DAE.MUL_MATRIX_PRODUCT(tp),de2),DAE.ADD_ARR(tp),
2082 DAE.BINARY(de1,DAE.MUL_MATRIX_PRODUCT(tp),e2)), funcs);
2083
2084 // (f\'g - fg\') / g^2
2085 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp),exp2 = e2)
2086 algorithm
2087 42065 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2088 41497 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2089 41497 then
2090 (DAE.BINARY(
2091 DAE.BINARY(DAE.BINARY(de1,DAE.MUL(tp),e2), DAE.SUB(tp),
2092 DAE.BINARY(e1,DAE.MUL(tp),de2)), DAE.DIV(tp), DAE.BINARY(e2,DAE.MUL(tp),e2)), funcs);
2093
2094 // (f\'g - fg\') / g^2
2095 case DAE.BINARY(exp1 = e1,operator = DAE.DIV_ARR(ty = tp),exp2 = e2)
2096 algorithm
2097 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2098 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2099 ✗ then
2100 (DAE.BINARY(
2101 DAE.BINARY(DAE.BINARY(de1,DAE.MUL_ARR(tp),e2),DAE.SUB_ARR(tp),
2102 DAE.BINARY(e1,DAE.MUL_ARR(tp),de2)), DAE.DIV_ARR(tp), DAE.BINARY(e2,DAE.MUL_ARR(tp),e2)), funcs);
2103
2104
2105 // (f\'g - fg\') / g^2
2106 case DAE.BINARY(exp1 = e1,operator = DAE.DIV_ARRAY_SCALAR(ty = tp),exp2 = e2)
2107 algorithm
2108 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2109 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2110 ✗ tp1 := Expression.typeof(e2);
2111 ✗ then
2112 (DAE.BINARY(
2113 DAE.BINARY(DAE.BINARY(de1,DAE.MUL_ARRAY_SCALAR(tp),e2),DAE.SUB_ARR(tp),
2114 DAE.BINARY(e1,DAE.MUL_ARRAY_SCALAR(tp),de2)),DAE.DIV_ARRAY_SCALAR(tp),DAE.BINARY(e2,DAE.MUL(tp1),e2)), funcs);
2115
2116 // (f\'g - fg\') / g^2
2117 case DAE.BINARY(exp1 = e1,operator = DAE.DIV_SCALAR_ARRAY(ty = tp),exp2 = e2)
2118 algorithm
2119 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2120 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, funcs, maxIter);
2121 ✗ then
2122 (DAE.BINARY(
2123 DAE.BINARY(DAE.BINARY(de1,DAE.MUL_ARRAY_SCALAR(tp),e2),DAE.SUB_ARR(tp),
2124 DAE.BINARY(e1,DAE.MUL_ARRAY_SCALAR(tp),de2)),DAE.DIV_ARR(tp),DAE.BINARY(e2,DAE.MUL_ARR(tp),e2)), funcs);
2125
2126 // x^r
2127 case DAE.BINARY(exp1 = e1,operator = DAE.POW(tp),exp2 = (e2 as DAE.RCONST(real=r)))
2128 algorithm
2129 67285 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2130 67257 r := r - 1.0;
2131 67257 e := DAE.BINARY(DAE.BINARY(e2,DAE.MUL(tp),
2132 DAE.BINARY(e1,DAE.POW(tp),DAE.RCONST(r))),
2133 DAE.MUL(tp),de1);
2134 67257 then
2135 (e, funcs);
2136 // x^i
2137 case DAE.BINARY(exp1 = e1,operator = DAE.POW(tp),exp2 = (e2 as DAE.ICONST(integer = i)))
2138 algorithm
2139 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2140 ✗ i := i - 1;
2141 ✗ e := DAE.BINARY(DAE.BINARY(e2,DAE.MUL(tp),
2142 DAE.BINARY(e1,DAE.POW(tp),DAE.ICONST(i))),
2143 DAE.MUL(tp),de1);
2144 ✗ then
2145 (e, funcs);
2146 // der(0^x) = 0
2147 case DAE.BINARY(exp1 = (DAE.RCONST(real=0.0)),operator = DAE.POW(tp))
2148 algorithm
2149 ✗ zero := Expression.makeZeroExpression(Expression.arrayDimension(tp));
2150 then
2151 (zero, inFunctionTree);
2152
2153 // der(r^x) = r^x*ln(r)*der(x)
2154 case e0 as DAE.BINARY(exp1 = DAE.RCONST(real=r),operator = DAE.POW(tp),exp2 = e1)
2155 algorithm
2156 ✗ (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2157 ✗ r := log(r);
2158 ✗ e := DAE.BINARY(DAE.BINARY(e0,DAE.MUL(tp),DAE.RCONST(r)),DAE.MUL(tp),de1);
2159 ✗ then
2160 (e, funcs);
2161
2162 // added for ticket #6068
2163 // (p is a parameter)
2164 // x^p
2165 case DAE.BINARY(exp1 = e1,operator = DAE.POW(tp),exp2 = (e2 as DAE.CREF(componentRef = cr)))
2166 guard(isParamOrConstant(cr, inInputData))
2167 algorithm
2168 etmp := match tp
2169 ✗ case DAE.T_INTEGER() then DAE.BINARY(e2, DAE.SUB(tp), DAE.ICONST(1));
2170 456 else DAE.BINARY(e2, DAE.SUB(tp), DAE.RCONST(1.0));
2171 end match;
2172 456 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2173 456 e := DAE.BINARY(DAE.BINARY(e2,DAE.MUL(tp),
2174 DAE.BINARY(e1,DAE.POW(tp),etmp)),
2175 DAE.MUL(tp),de1);
2176 456 then
2177 (e, funcs);
2178
2179 // added for ticket #6068
2180 // (p is a parameter)
2181 // der(p^x) = p^x*ln(p)*der(x)
2182 // if p == 0 then 0;
2183 case e0 as DAE.BINARY(exp1 = e1 as DAE.CREF(componentRef = cr), operator = DAE.POW(tp), exp2 = e2)
2184 guard(isParamOrConstant(cr, inInputData))
2185 algorithm
2186 ✗ (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2187 ✗ etmp := Expression.makePureBuiltinCall("log", {e1}, tp);
2188 // if p is equal to zero, then return zero (do not search for event)
2189 ✗ e := Expression.addNoEventToRelations(
2190 DAE.IFEXP(DAE.RELATION(e1, DAE.EQUAL(tp), DAE.RCONST(0.0), -1, NONE()), DAE.RCONST(0.0),
2191 DAE.BINARY(DAE.BINARY(e0,DAE.MUL(tp),etmp),DAE.MUL(tp),de2)));
2192 ✗ then
2193 (e, funcs);
2194
2195
2196 // der(x^y) = x^(y-1) * ( x*ln(x)*der(y)+(y*der(x)))
2197 // if x == 0 then 0;
2198 case DAE.BINARY(exp1 = e1,operator = DAE.POW(tp), exp2 = e2)
2199 algorithm
2200 471 (de1, funcs) := differentiateExp(e1, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2201 471 (de2, funcs) := differentiateExp(e2, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2202 471 etmp := Expression.makePureBuiltinCall("log", {e1}, tp);
2203 // if x is equal to zero, then return zero (do not search for event)
2204 471 e := Expression.addNoEventToRelations(DAE.IFEXP(DAE.RELATION(e1, DAE.EQUAL(tp), DAE.RCONST(0.0), -1, NONE()),
2205 DAE.RCONST(0.0), DAE.BINARY(DAE.BINARY(e1, DAE.POW(tp), DAE.BINARY(e2, DAE.SUB(tp), DAE.RCONST(1.0))),
2206 DAE.MUL(tp), DAE.BINARY(DAE.BINARY(DAE.BINARY(e1, DAE.MUL(tp), etmp), DAE.MUL(tp), de2),
2207 DAE.ADD(tp), DAE.BINARY(e2, DAE.MUL(tp), de1)))));
2208 471 then
2209 (e, funcs);
2210
2211 else
2212 algorithm
2213 ✗ true := Flags.isSet(Flags.FAILTRACE);
2214 ✗ s1 := ExpressionBasics.printExpStr(inExp);
2215 ✗ s2 := ComponentReferenceBasics.printComponentRefStr(inDiffwrtCref);
2216 ✗ serr := stringAppendList({"\n- Function differentiateBinary failed. differentiateExp ",s1," w.r.t: ",s2," failed\n"});
2217 ✗ Debug.trace(serr);
2218 ✗ then
2219 fail();
2220
2221 end match;
2222 end differentiateBinary;
2223
2224 // =============================================================================
2225 // functions to generate derivative of a function
2226 // =============================================================================
2227
2228 protected function differentiateFunctionCall"
2229 Author: Frenkel TUD, wbraun
2230
2231 "
2232 input DAE.Exp inExp; // in as DAE.CALL(_)
2233 input DAE.ComponentRef inDiffwrtCref;
2234 input BackendDAE.DifferentiateInputData inInputData;
2235 input BackendDAE.DifferentiationType inDiffType;
2236 input AvlTreePathFunction.Tree inFunctionTree;
2237 input Integer maxIter;
2238 output DAE.Exp outDiffedExp;
2239 output AvlTreePathFunction.Tree outFunctionTree;
2240 algorithm
2241 (outDiffedExp, outFunctionTree) :=
2242 matchcontinue(inExp, inDiffType)
2243 local
2244
2245
2246 DAE.Exp e, de, zero;
2247 list<DAE.Exp> expl,expl1,dexpl;
2248 Absyn.Path path,dpath;
2249 Boolean b,c,isImpure;
2250 DAE.InlineType dinl;
2251 DAE.Type ty;
2252 AvlTreePathFunction.Tree functions;
2253 DAE.FunctionDefinition mapper;
2254 DAE.Type tp, dtp;
2255 list<Boolean> blst;
2256 list<DAE.Type> tlst;
2257 String typstring, dastring;
2258 list<String> typlststring;
2259 DAE.TailCall tc;
2260 DAE.CallAttributes attr;
2261
2262
2263
2264 /* ticket5459
2265 if the function call does not contain the cref, the derivative is zero
2266 prevents failing of this function
2267 - Maybe not only for SIMPLE_DIFFERENTIATION ?
2268 */
2269 case (_, BackendDAE.SIMPLE_DIFFERENTIATION())
2270 guard(not expHasRelatedCref(inExp, inDiffwrtCref))
2271 algorithm
2272 19716 (e, _) := Expression.makeZeroExpression(Expression.arrayDimension(Expression.typeof(inExp)));
2273 19716 then (e, inFunctionTree);
2274
2275 case (DAE.CALL(path=path,expLst=expl,attr=DAE.CALL_ATTR(tuple_=b,builtin=c,isImpure=isImpure,ty=ty,tailCall=tc)), BackendDAE.DIFFERENTIATION_TIME())
2276 algorithm
2277 // get function mapper
2278 //print("Search for function mapper\n");
2279 2764 (mapper, tp) := getFunctionMapper(path, inFunctionTree);
2280 2655 (dpath, blst) := differentiateFunction1(path,mapper, tp, expl, (inDiffwrtCref, inInputData, inDiffType, inFunctionTree));
2281
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2655 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2655 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2655 times.
2655 SOME(DAE.FUNCTION(type_=dtp,inlineType=dinl)) := AvlTreePathFunction.get(inFunctionTree, dpath);
2282 // check if derivativ function has all expected inputs
2283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2655 times.
2655 (true,_) := checkDerivativeFunctionInputs(blst, tp, dtp);
2284 2655 (expl1,_) := List.splitOnBoolList(expl, blst);
2285 2655 (dexpl, outFunctionTree) := List.map3Fold(expl1, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
2286 2655 expl1 := listAppend(expl,dexpl);
2287
3/6
✓ Branch 0 taken 2655 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2655 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2655 times.
✗ Branch 5 not taken.
10620 then
2288 (DAE.CALL(dpath,expl1,DAE.CALL_ATTR(ty,b,c,isImpure,false,dinl,tc,DAE.NoReturn.RETURNS)),outFunctionTree);
2289
2290 case (DAE.CALL(path=path,expLst=expl), BackendDAE.DIFFERENTIATION_TIME())
2291 algorithm
2292 // get function mapper
2293 //print("Search for function mapper2\n");
2294 109 (mapper, tp) := getFunctionMapper(path, inFunctionTree);
2295 ✗ (dpath, blst) := differentiateFunction1(path, mapper, tp, expl, (inDiffwrtCref, inInputData, inDiffType, inFunctionTree));
2296 ✗ SOME(DAE.FUNCTION(type_ = dtp)) := AvlTreePathFunction.get(inFunctionTree, dpath);
2297 // check if derivativ function has all expected inputs
2298 ✗ (false, tlst) := checkDerivativeFunctionInputs(blst, tp, dtp);
2299 // add Warning
2300 ✗ typlststring := List.map(tlst, TypesDump.unparseType);
2301 ✗ typstring := "\n" + stringDelimitList(typlststring,";\n");
2302 ✗ dastring := AbsynUtil.pathString(dpath);
2303 ✗ print("Input warnings for function mapper2\n");
2304 ✗ Error.addMessage(Error.UNEXPECTED_FUNCTION_INPUTS_WARNING, {dastring,typstring});
2305 ✗ then
2306 fail();
2307
2308 // try to inline
2309 case (DAE.CALL(attr=DAE.CALL_ATTR(builtin=false)), _)
2310 algorithm
2311
3/4
✓ Branch 0 taken 19953 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18545 times.
✓ Branch 3 taken 1408 times.
19953 failure(BackendDAE.DIFF_FULL_JACOBIAN() := inDiffType);
2312
2/2
✓ Branch 2 taken 10628 times.
✓ Branch 3 taken 7917 times.
18545 (e,_,true) := Inline.forceInlineExp(inExp,(SOME(inFunctionTree),{DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}),DAE.emptyElementSource,Ceval.cevalSimpleWithFunctionTreeReturnExp);
2313 7917 (e, functions) := differentiateExp(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2314 then
2315 (e, functions);
2316
2317 // differentiate record call
2318 case (e as DAE.CALL(path=path, expLst=expl, attr=attr), _) guard( Expression.isRecordCall(e, inFunctionTree))
2319 algorithm
2320 ✗ (dexpl, functions) := List.map3Fold(expl, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
2321 ✗ then (DAE.CALL(path, dexpl, attr), functions);
2322
2323 //differentiate function partial
2324 case (e, _)
2325 algorithm
2326 // Debug dump
2327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12847 times.
12847 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
2328 ✗ BackendDump.debugStrExpStr("### Differentiate call\n ", e, " w.r.t. " + ComponentReference.crefStr(inDiffwrtCref) + "\n");
2329 end if;
2330 12847 (de, functions) := differentiateFunctionCallPartial(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2331 4110 (e,_,b) := Inline.forceInlineExp(de,(SOME(functions),{DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}),DAE.emptyElementSource,Ceval.cevalSimpleWithFunctionTreeReturnExp);
2332
2/2
✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 2269 times.
4110 if b then
2333 de := e;
2334 end if;
2335 // Debug dump
2336
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4110 times.
4110 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
2337 ✗ BackendDump.debugStrExpStr("### result output :\n", de, " w.r.t. " + ComponentReference.crefStr(inDiffwrtCref) + "\n");
2338 end if;
2339 4110 then
2340 (de, functions);
2341
2342 case (_, _)
2343 algorithm
2344 /* TODO: Check replace this rule by other, since it's not correct
2345 in case of
2346 - failure(BackendDAE.DIFFERENTIATION_FUNCTION() = inDiffType);
2347 - failure(BackendDAE.GENERIC_GRADIENT() = inDiffType);
2348 but anyway fornow it catches some testsuite cases.
2349 */
2350
1/2
✓ Branch 1 taken 8737 times.
✗ Branch 2 not taken.
8737 false := expHasRelatedCref(inExp, inDiffwrtCref)
2351 "If the expression does not contain the variable,
2352 the derivative is zero. For efficiency reasons this rule
2353 is last. Otherwise expressions is always traversed twice
2354 when differentiating.";
2355 ✗ tp := Expression.typeof(inExp);
2356 ✗ zero := Expression.createZeroExpression(tp);
2357 ✗ then (zero, inFunctionTree);
2358
2359 else
2360 algorithm
2361
1/2
✓ Branch 1 taken 8737 times.
✗ Branch 2 not taken.
8737 true := Flags.isSet(Flags.FAILTRACE);
2362 ✗ Debug.trace(getInstanceName() + " failed for " + ExpressionBasics.printExpStr(inExp) + "\n");
2363 ✗ then fail();
2364 end matchcontinue;
2365 end differentiateFunctionCall;
2366
2367 protected function differentiateFunctionCallPartial"
2368 Author: Frenkel TUD, wbraun
2369
2370 "
2371 input DAE.Exp inExp; // in as DAE.CALL(_)
2372 input DAE.ComponentRef inDiffwrtCref;
2373 input BackendDAE.DifferentiateInputData inInputData;
2374 input BackendDAE.DifferentiationType inDiffType;
2375 input AvlTreePathFunction.Tree inFunctionTree;
2376 input Integer maxIter;
2377 output DAE.Exp outDiffedExp;
2378 output AvlTreePathFunction.Tree outFunctionTree;
2379 algorithm
2380 (outDiffedExp, outFunctionTree) :=
2381 matchcontinue inExp
2382 local
2383
2384 BackendDAE.DifferentiateInputData diffFuncData;
2385
2386 DAE.Exp e, exp;
2387 list<DAE.Exp> expl,expl1,dexpl,dexplZero;
2388 Absyn.Path path,dpath;
2389 Boolean b,c,isImpure;
2390 DAE.InlineType dinl;
2391 DAE.Type ty, dtp;
2392 AvlTreePathFunction.Tree functions;
2393 DAE.FunctionDefinition mapper;
2394 DAE.Type tp, dtp;
2395 list<Boolean> blst;
2396 list<DAE.Type> tlst;
2397 list<tuple<DAE.Exp,Boolean>> expBoolLst;
2398 String typstring, dastring, funstring, str;
2399 list<String> typlststring;
2400 DAE.TailCall tc;
2401
2402 list<DAE.Element> inputVarsDer;
2403 list<DAE.Element> outputVarsDer;
2404
2405 DAE.Function func,dfunc;
2406 String funcname;
2407 Boolean success;
2408
2409 case DAE.CALL(path=path,expLst=expl,attr=DAE.CALL_ATTR(tuple_=b,builtin=c,isImpure=isImpure,ty=ty,tailCall=tc))
2410 algorithm
2411 // get function mapper
2412 //print("Search for function mapper\n");
2413 12847 (mapper, tp) := getFunctionMapper(path, inFunctionTree);
2414 4043 (dpath, blst) := differentiateFunction1(path,mapper, tp, expl, (inDiffwrtCref, inInputData, inDiffType, inFunctionTree));
2415
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 4035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4035 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4035 times.
4042 SOME(DAE.FUNCTION(type_=dtp,inlineType=dinl)) := AvlTreePathFunction.get(inFunctionTree, dpath);
2416 // check if derivative function has all expected inputs
2417
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4035 times.
4035 (true,_) := checkDerivativeFunctionInputs(blst, tp, dtp);
2418 4035 (expl1,_) := List.splitOnBoolList(expl, blst);
2419 4035 (dexpl, functions) := List.map3Fold(expl1, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, inFunctionTree);
2420 4035 funcname := BackendUtil.modelicaStringToCStr(AbsynUtil.pathString(path), false);
2421 diffFuncData := BackendDAE.emptyInputData;
2422 4035 diffFuncData.matrixName := SOME(funcname);
2423 4035 (dexplZero, functions) := List.map3Fold(expl1, function differentiateExp(maxIter=maxIter), DAE.CREF_IDENT("$",DAE.T_REAL_DEFAULT,{}), diffFuncData, BackendDAE.GENERIC_GRADIENT(false), functions);
2424
7/8
✓ Branch 0 taken 7655 times.
✓ Branch 1 taken 4033 times.
✓ Branch 2 taken 7655 times.
✓ Branch 3 taken 4033 times.
✓ Branch 4 taken 7655 times.
✓ Branch 5 taken 4033 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4033 times.
11688 dexplZero := list(typedZeroSeed(a, z) threaded for a in expl1, z in dexplZero);
2425 // debug dump
2426
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4033 times.
4033 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION) then
2427 ✗ print("### differentiated argument list:\n");
2428 ✗ print("Diffed ExpList: \n");
2429 ✗ print(stringDelimitList(List.map(dexpl, ExpressionBasics.printExpStr), ", ") + "\n");
2430 end if;
2431
4/6
✓ Branch 0 taken 4033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4033 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4028 times.
✓ Branch 5 taken 5 times.
16127 e := DAE.CALL(dpath,expl1,DAE.CALL_ATTR(ty,b,c,isImpure,false,dinl,tc,DAE.NoReturn.RETURNS));
2432 4033 e := createPartialArguments(ty, dexpl, dexplZero, expl, e, inDiffType);
2433 4033 then
2434 (e,functions);
2435
2436 case DAE.CALL(path=path,expLst=expl)
2437 algorithm
2438 // get function mapper
2439 //print("Search for function mapper2\n");
2440 8814 (mapper, tp) := getFunctionMapper(path, inFunctionTree);
2441 10 (dpath, blst) := differentiateFunction1(path, mapper, tp, expl, (inDiffwrtCref, inInputData, inDiffType, inFunctionTree));
2442
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
11 SOME(DAE.FUNCTION(type_=dtp)) := AvlTreePathFunction.get(inFunctionTree, dpath);
2443 // check if derivativ function has all expected inputs
2444
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 (false, tlst) := checkDerivativeFunctionInputs(blst, tp, dtp);
2445 // add Warning
2446 ✗ typlststring := List.map(tlst, TypesDump.unparseType);
2447 ✗ typstring := "\n" + stringDelimitList(typlststring,";\n");
2448 ✗ dastring := AbsynUtil.pathString(dpath);
2449 ✗ print("Input warnings for function mapper2\n");
2450 ✗ Error.addMessage(Error.UNEXPECTED_FUNCTION_INPUTS_WARNING, {dastring,typstring});
2451 ✗ then
2452 fail();
2453
2454 // differentiate function
2455 case e as DAE.CALL(path=path,expLst=expl,attr=DAE.CALL_ATTR(tuple_=b,builtin=false,isImpure=isImpure,ty=ty,tailCall=tc))
2456 algorithm
2457 // TODO: FIXIT! expressionSolve and analyticJacobian don't
2458 // return new functionTree, so we can't differentiate functions then.
2459
3/4
✓ Branch 0 taken 8814 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1454 times.
✓ Branch 3 taken 7360 times.
8814 failure(BackendDAE.SIMPLE_DIFFERENTIATION() := inDiffType);
2460
3/4
✓ Branch 0 taken 1454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 1377 times.
1454 failure(BackendDAE.DIFF_FULL_JACOBIAN() := inDiffType);
2461
2462 // get algorithm of the function
2463
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 77 times.
77 SOME(func) := AvlTreePathFunction.get(inFunctionTree,path);
2464
2465 //catch recursive functions call
2466
2/2
✓ Branch 1 taken 75 times.
✓ Branch 2 taken 2 times.
77 if not AvlSetPath.hasKey(inInputData.diffedFunctions, path) then
2467
2468 // add function to diffed functions set
2469 75 inInputData.diffedFunctions := AvlSetPath.add(inInputData.diffedFunctions, path);
2470 // differentiate function
2471 75 (dfunc, functions, blst) := differentiatePartialFunction(func, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
2472
2473 75 dpath := DAEUtil.functionName(dfunc);
2474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
75 DAE.T_FUNCTION(funcResultType = dtp) := DAEUtil.getFunctionType(dfunc);
2475
2476 // debug
2477
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
75 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2478 ✗ funstring := Tpl.tplString(DAEDumpTpl.dumpFunction, dfunc);
2479 ✗ print("### Differentiate function: \n" + funstring + "\n\n");
2480 end if;
2481
2482 75 functions := AvlTreePathFunction.addDaeFunction({dfunc}, functions);
2483 // add differentiated function as function mapper
2484 75 func := DAEUtil.addFunctionDefinition(func, DAE.FUNCTION_DER_MAPPER(path, dpath, 1, {}, NONE(), {}));
2485 75 functions := AvlTreePathFunction.add(functions, path, SOME(func));
2486 else
2487 2 (functions, inputVarsDer, _, outputVarsDer, _, blst) := getFunctionInOutVars(func, inFunctionTree, inDiffwrtCref, maxIter);
2488 2 (dpath, dtp) := getDiffedTypeandName(func, inputVarsDer, outputVarsDer, blst);
2489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 DAE.T_FUNCTION(funcResultType = dtp) := dtp;
2490 end if;
2491
2492 // debug
2493 // differentiate expl
2494
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2495 ✗ print("### Detailed arguments list: \n");
2496 ✗ print(stringDelimitList(List.map(expl, ExpressionBasics.printExpStr), ", ") + "\n");
2497 ✗ print("### and argument types: \n");
2498 ✗ print(stringDelimitList(List.mapMap(expl, Expression.typeof, TypesDump.printTypeStr), " | ") + "\n");
2499 ✗ print("### and output type: \n" + TypesDump.printTypeStr(dtp) + "\n");
2500 end if;
2501
2502 // create differentiated call arguments
2503 77 expBoolLst := List.zip(expl, blst);
2504 77 expBoolLst := List.filterOnTrue(expBoolLst, Util.tuple22);
2505 77 expl1 := List.map(expBoolLst, Util.tuple21);
2506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2507 ✗ print("### Selected Arguments: \n");
2508 ✗ print(stringDelimitList(List.map(expl1, ExpressionBasics.printExpStr), ", ") + "\n");
2509 end if;
2510
2511 77 (dexpl, functions) := List.map3Fold(expl1, function differentiateExp(maxIter=maxIter), inDiffwrtCref, inInputData, inDiffType, functions);
2512
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2513 ✗ print("### Diffed ExpList: \n");
2514 ✗ print(stringDelimitList(List.map(dexpl, ExpressionBasics.printExpStr), ", ") + "\n");
2515 end if;
2516
2517 // try to create zero expression to fill up the arguments, if it fails use the total differentiation
2518 77 (dexplZero, functions, success) := tryZeroDiff(expl1, functions, maxIter);
2519
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 6 times.
77 if success then
2520
3/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 6 times.
207 e := DAE.CALL(dpath,dexpl,DAE.CALL_ATTR(dtp,b,false,isImpure,false,DAE.NO_INLINE(),tc,DAE.NoReturn.RETURNS));
2521 71 exp := createPartialArguments(ty, dexpl, dexplZero, expl, e, inDiffType);
2522 else
2523
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
16 exp := DAE.CALL(dpath,listAppend(expl,dexpl),DAE.CALL_ATTR(dtp,b,false,isImpure,false,DAE.NO_INLINE(),tc,DAE.NoReturn.RETURNS));
2524 end if;
2525
2526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2527 ✗ print("### differentiated result CALL :\n");
2528 ✗ print(ExpressionBasics.printExpStr(exp) + "\n");
2529 end if;
2530 77 then
2531 (exp, functions);
2532
2533 else
2534 algorithm
2535
1/2
✓ Branch 1 taken 8737 times.
✗ Branch 2 not taken.
8737 true := Flags.isSet(Flags.FAILTRACE);
2536 ✗ str := "Differentiate.differentiateFunctionCallPartial failed for " + ExpressionBasics.printExpStr(inExp) + "\n";
2537 ✗ Debug.trace(str);
2538 ✗ then fail();
2539 end matchcontinue;
2540 end differentiateFunctionCallPartial;
2541
2542 function addFunctionConstantsAndParameters
2543 input output Option<BackendDAE.Variables> knownVars_opt;
2544 input DAE.Function func;
2545 algorithm
2546 knownVars_opt := match func
2547 local
2548 list<DAE.Element> body;
2549 Option<BackendDAE.Var> var_opt;
2550 list<BackendDAE.Var> body_knowns = {};
2551
2552 case DAE.FUNCTION(functions = DAE.FUNCTION_DEF(body = body)::_)
2553 algorithm
2554
2/2
✓ Branch 0 taken 611 times.
✓ Branch 1 taken 75 times.
686 for element in body loop
2555 611 var_opt := BackendDAECreate.lowerKnownVarSingle(element);
2556
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 586 times.
611 if isSome(var_opt) then
2557 25 body_knowns := Util.getOption(var_opt) :: body_knowns;
2558 end if;
2559 end for;
2560
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 70 times.
75 if listEmpty(body_knowns) then
2561 // basically do nothing, just for visualization
2562 knownVars_opt := knownVars_opt;
2563 elseif isSome(knownVars_opt) then
2564 // add to current variable vector
2565 ✗ knownVars_opt := SOME(BackendVariable.addVars(body_knowns, Util.getOption(knownVars_opt)));
2566 else
2567 // create new variable vector
2568 5 knownVars_opt := SOME(BackendVariable.listVar(body_knowns));
2569 end if;
2570 then knownVars_opt;
2571
2572 else knownVars_opt;
2573 end match;
2574 end addFunctionConstantsAndParameters;
2575
2576 function tryZeroDiff
2577 input output list<DAE.Exp> explist;
2578 input output AvlTreePathFunction.Tree functions;
2579 input Integer maxIter;
2580 output Boolean success;
2581 protected
2582 list<DAE.Exp> args = explist;
2583 algorithm
2584 try
2585 77 (explist, functions) := List.map3Fold(explist, function differentiateExp(maxIter=maxIter), DAE.CREF_IDENT("$",DAE.T_REAL_DEFAULT,{}), BackendDAE.emptyInputData, BackendDAE.GENERIC_GRADIENT(false), functions);
2586
7/8
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 158 times.
✓ Branch 5 taken 71 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 71 times.
229 explist := list(typedZeroSeed(a, z) threaded for a in args, z in explist);
2587 success := true;
2588 else
2589 explist := {};
2590 success := false;
2591 end try;
2592 end tryZeroDiff;
2593
2594 protected function createPartialArguments
2595 input DAE.Type outputType;
2596 input list<DAE.Exp> inArgs;
2597 input list<DAE.Exp> inDiffedArgs;
2598 input list<DAE.Exp> inOrginalExpl;
2599 input DAE.Exp inCall;
2600 input BackendDAE.DifferentiationType inDiffType;
2601 output DAE.Exp outExp;
2602 algorithm
2603 outExp := matchcontinue(outputType, inCall)
2604 local
2605 Absyn.Path path, rPath;
2606 DAE.CallAttributes attr;
2607 list<DAE.Exp> expLst;
2608 DAE.Exp ezero, e;
2609 DAE.Dimensions dims;
2610 list<DAE.Type> tys;
2611 list<DAE.Var> varLst;
2612 list<String> varNames;
2613
2614 case (DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path=rPath),varLst=varLst), DAE.CALL(path=path, attr=attr))
2615 algorithm
2616 // In a function body the result is a statement, so one call with the
2617 // actual seeds gives the whole record - the derivative function is linear
2618 // in them. Collecting the partials per component instead costs a call per
2619 // (component, argument) pair. Everywhere else the result becomes an
2620 // equation that BackendEquation.scalarComplexEquations has to be able to
2621 // split, and that needs the record.
2622
3/4
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 33 times.
75 if boolAnd(not List.all(inArgs, isZeroDerivative),
2623 valueEq(inDiffType, BackendDAE.DIFFERENTIATION_FUNCTION())) then
2624 42 e := DAE.CALL(path, listAppend(inOrginalExpl, inArgs), attr);
2625 else
2626
4/4
✓ Branch 0 taken 354 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 354 times.
✓ Branch 3 taken 33 times.
387 tys := list(DAEUtil.varType(v) for v in varLst);
2627
4/4
✓ Branch 0 taken 354 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 354 times.
✓ Branch 3 taken 33 times.
387 varNames := list(DAEUtil.typeVarIdent(v) for v in varLst);
2628 33 expLst := createPartialArgumentsRecord(tys, varNames, inArgs, inDiffedArgs, inOrginalExpl, inCall, inDiffType);
2629 27 e := DAE.RECORD(rPath, expLst, varNames, outputType);
2630 end if;
2631 then e;
2632
2633 case (DAE.T_COMPLEX(complexClassType=ClassInf.RECORD()), DAE.TSUB(exp=DAE.CALL(path=path, attr=attr)))
2634 4 then DAE.CALL(path, listAppend(inOrginalExpl,inArgs), attr);
2635
2636 case (DAE.T_TUPLE(types = tys), _) algorithm
2637 11 expLst := createPartialArgumentsTuple(tys, inArgs, inDiffedArgs, inOrginalExpl, inCall, inDiffType);
2638 9 then DAE.TUPLE(expLst);
2639
2640 case (_, _)
2641 algorithm
2642 4331 dims := Expression.arrayDimension(outputType);
2643 4331 (ezero,_) := Expression.makeZeroExpression(dims);
2644 4329 e := createPartialDifferentiatedExp(inArgs, inDiffedArgs, inOrginalExpl, inCall, 1, ezero);
2645 then e;
2646
2647 //else case as fallback create total differentiation call
2648 case (_, DAE.CALL(path=path, attr=attr))
2649 8 then DAE.CALL(path, listAppend(inOrginalExpl,inArgs), attr);
2650
2651 end matchcontinue;
2652 end createPartialArguments;
2653
2654 protected function createPartialArgumentsTuple
2655 input list<DAE.Type> inTypesLst;
2656 input list<DAE.Exp> inArgs;
2657 input list<DAE.Exp> inDiffedArgs;
2658 input list<DAE.Exp> inOrginalExpl;
2659 input DAE.Exp inCall;
2660 input BackendDAE.DifferentiationType inDiffType;
2661 output list<DAE.Exp> outExpLst;
2662 algorithm
2663
7/8
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
36 outExpLst := list( createPartialArguments(
2664 tp, inArgs, inDiffedArgs, inOrginalExpl, (DAE.TSUB(inCall, number, tp)), inDiffType
2665 )
2666 threaded for tp in inTypesLst, number in 1:listLength(inTypesLst));
2667 end createPartialArgumentsTuple;
2668
2669 protected function createPartialArgumentsRecord
2670 input list<DAE.Type> inTypesLst;
2671 input list<DAE.String> inVarNames;
2672 input list<DAE.Exp> inArgs;
2673 input list<DAE.Exp> inDiffedArgs;
2674 input list<DAE.Exp> inOrginalExpl;
2675 input DAE.Exp inCall;
2676 input BackendDAE.DifferentiationType inDiffType;
2677 output list<DAE.Exp> outExpLst;
2678 algorithm
2679
7/8
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 282 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 282 times.
✓ Branch 5 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
309 outExpLst := list( createPartialArguments(tp, inArgs, inDiffedArgs, inOrginalExpl, (DAE.RSUB(inCall, -1, name, tp)), inDiffType )
2680 threaded for tp in inTypesLst, name in inVarNames);
2681 end createPartialArgumentsRecord;
2682
2683 protected function createPartialDifferentiatedExp
2684 "Generates an expression with a sum partial derivatives."
2685 input list<DAE.Exp> inDiffExpl;
2686 input list<DAE.Exp> inDiffExplZero;
2687 input list<DAE.Exp> inOrginalExpl;
2688 input DAE.Exp inCall;
2689 input Integer currentLstElement;
2690 input DAE.Exp inAccum;
2691 output DAE.Exp outExp = inAccum;
2692 protected
2693 Integer i = currentLstElement;
2694 algorithm
2695
2/2
✓ Branch 0 taken 8293 times.
✓ Branch 1 taken 4315 times.
12608 for de in inDiffExpl loop
2696 outExp := match(de, inCall)
2697 local
2698 DAE.Exp e, eone, eArray;
2699 list<list<DAE.Exp>> arrayArgs;
2700 list<DAE.Exp> expl, expLst, dexpLst;
2701 DAE.Type tp;
2702 DAE.Dimensions dims;
2703 Boolean b;
2704 Absyn.Path path;
2705 DAE.CallAttributes attr;
2706
2707 case (_, DAE.CALL(path=path, attr=attr))
2708 guard(Types.isRecord(Expression.typeof(de)))
2709 algorithm
2710 // A record valued argument cannot be seeded component-wise with a one,
2711 // the derivative of the record itself is passed as seed instead. The
2712 // resulting term has to be added to the partial derivatives collected so
2713 // far, it must not replace them.
2714
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 93 times.
97 if isZeroDerivative(de) then
2715 // this argument does not contribute to the derivative
2716 e := outExp;
2717 else
2718 4 dexpLst := List.set(inDiffExplZero, i, de);
2719 4 expLst := listAppend(inOrginalExpl,dexpLst);
2720 4 e := Expression.expAdd(outExp, DAE.CALL(path, expLst, attr));
2721 end if;
2722 then e;
2723
2724 case (DAE.ARRAY(ty = tp,scalar = b,array = expl), _) algorithm
2725 //print("createPartialDifferentiatedExp : i = " + intString(i) + "\n");
2726 2882 eArray := listGet(inDiffExplZero, i);
2727 2882 dexpLst := Expression.arrayElements(eArray);
2728 2882 arrayArgs := prepareArgumentsExplArray(expl, dexpLst, 1, {});
2729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2882 times.
2882 expLst := List.map2(arrayArgs, Expression.makeArray, tp, b);
2730
4/4
✓ Branch 0 taken 7941 times.
✓ Branch 1 taken 2882 times.
✓ Branch 2 taken 7941 times.
✓ Branch 3 taken 2882 times.
10823 arrayArgs := list(List.set(inDiffExplZero, i, exp) for exp in expLst);
2731 2882 arrayArgs := List.map1r(arrayArgs, listAppend, inOrginalExpl);
2732 2882 e := createPartialSum(arrayArgs, expl, inCall, outExp);
2733 then e;
2734
2735 else
2736 algorithm
2737 5314 tp := Expression.typeof(de);
2738 5314 dims := Expression.arrayDimension(tp);
2739 5314 (eone,_) := Expression.makeOneExpression(dims);
2740 5314 dexpLst := List.set(inDiffExplZero, i, eone);
2741 5314 expLst := listAppend(inOrginalExpl,dexpLst);
2742 5314 e := createPartialSum({expLst}, {de}, inCall, outExp);
2743 then e;
2744 end match;
2745 8279 i := i + 1;
2746 end for;
2747 end createPartialDifferentiatedExp;
2748
2749 protected function createPartialSum
2750 "Generates an expression with a sum partial derivatives"
2751 input list<list<DAE.Exp>> inArgsLst;
2752 input list<DAE.Exp> inDiff;
2753 input DAE.Exp inCall;
2754 input DAE.Exp inAccum;
2755 output DAE.Exp outExp = inAccum;
2756 protected
2757 list<DAE.Exp> restDiff = inDiff;
2758 DAE.Exp de, res;
2759 algorithm
2760
2/2
✓ Branch 0 taken 13255 times.
✓ Branch 1 taken 8182 times.
21437 for expLst in inArgsLst loop
2761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13255 times.
13255 de::restDiff := restDiff;
2762
2763 // skip for zero differentiation
2764
2/2
✓ Branch 1 taken 3670 times.
✓ Branch 2 taken 9585 times.
13255 if not Expression.isZero(de) then
2765 res := match inCall
2766 local
2767 Absyn.Path path;
2768 DAE.CallAttributes attr;
2769 DAE.Type ty;
2770 Integer ix;
2771 String name;
2772
2773 case DAE.RSUB(exp=DAE.CALL(path=path, attr=attr), ix=ix, fieldName=name, ty=ty)
2774 558 then DAE.RSUB(DAE.CALL(path, expLst, attr), ix, name, ty);
2775
2776 case DAE.TSUB(exp=DAE.CALL(path=path, attr=attr), ix=ix, ty=ty)
2777 28 then DAE.TSUB(DAE.CALL(path, expLst, attr), ix, ty);
2778
2779 case DAE.CALL(path=path, attr=attr) algorithm
2780 3084 then DAE.CALL(path, expLst, attr);
2781 end match;
2782
2783 3670 res := Expression.expMul(de, res);
2784 3656 outExp := Expression.expAdd(outExp, res);
2785
2786 end if;
2787 end for;
2788
2789 end createPartialSum;
2790
2791 protected function prepareArgumentsExplArray
2792 "Generate an expression with a sum partial derivatives"
2793 input list<DAE.Exp> inWorkLst;
2794 input list<DAE.Exp> inArgs;
2795 input Integer inCurrentArg;
2796 input list<list<DAE.Exp>> inAccum;
2797 output list<list<DAE.Exp>> outExpLstLst;
2798 algorithm
2799 outExpLstLst := match inWorkLst
2800 local
2801 list<DAE.Exp> rest, args;
2802 DAE.Exp e, eone;
2803 DAE.Type tp;
2804 DAE.Dimensions dims;
2805
2806 case {}
2807 2882 then listReverse(inAccum);
2808
2809 case e::rest algorithm
2810 7941 tp := Expression.typeof(e);
2811 7941 dims := Expression.arrayDimension(tp);
2812 7941 (eone,_) := Expression.makeOneExpression(dims);
2813 7941 args := List.set(inArgs, inCurrentArg, eone);
2814 7941 then prepareArgumentsExplArray(rest, inArgs, inCurrentArg+1, args::inAccum);
2815 end match;
2816 end prepareArgumentsExplArray;
2817
2818 protected function differentiatePartialFunction "Author: wbraun"
2819 input DAE.Function inFunction;
2820 input DAE.ComponentRef inDiffwrtCref;
2821 input BackendDAE.DifferentiateInputData inInputData;
2822 input BackendDAE.DifferentiationType inDiffType;
2823 input AvlTreePathFunction.Tree inFunctionTree;
2824 input Integer maxIter;
2825 output DAE.Function outDerFunction;
2826 output AvlTreePathFunction.Tree outFunctionTree;
2827 output list<Boolean> outBooleanlst;
2828 algorithm
2829 (outDerFunction, outFunctionTree, outBooleanlst) := matchcontinue inFunction
2830 local
2831 BackendDAE.DifferentiateInputData inputData, diffFuncData;
2832
2833 Absyn.Path path, dpath;
2834 Boolean isImpure;
2835 DAE.InlineType dinl;
2836 AvlTreePathFunction.Tree functions;
2837 DAE.Type dtp;
2838 String str;
2839
2840 list<DAE.Element> funcbodyDer;
2841 list<DAE.Element> inputVars, inputVarsNoDer, inputVarsDer;
2842 list<DAE.Element> outputVars, outputVarsNoDer, outputVarsDer;
2843 list<DAE.Element> protectedVars, protectedVarsNoDer, protectedVarsDer, newProtectedVars;
2844 list<DAE.Statement> bodyStmts, derbodyStmts;
2845
2846 DAE.Function func,dfunc;
2847
2848 String funcname, funstring;
2849 list<Boolean> blst;
2850 SCode.Visibility visibility;
2851
2852 // differentiate function
2853 case func algorithm
2854 // debug
2855
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
75 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2856 ✗ funstring := Tpl.tplString(DAEDumpTpl.dumpFunction, func);
2857 ✗ print("### Differentiate differentiateFunctionCallPartial: \n" + funstring + "\n\n");
2858 end if;
2859
2860 75 inputVars := DAEUtil.getFunctionInputVars(func);
2861 75 outputVars := DAEUtil.getFunctionOutputVars(func);
2862 75 protectedVars := DAEUtil.getFunctionProtectedVars(func);
2863 75 bodyStmts := DAEUtil.getFunctionAlgorithmStmts(func);
2864 75 visibility := DAEUtil.getFunctionVisibility(func);
2865
2866 75 (functions, inputVarsDer, inputVarsNoDer, outputVarsDer, outputVarsNoDer, blst) := getFunctionInOutVars(func, inFunctionTree, inDiffwrtCref, maxIter);
2867
2868 // prepare diffData
2869 75 path := DAEUtil.functionName(func);
2870 75 funcname := BackendUtil.modelicaStringToCStr(AbsynUtil.pathString(path), false);
2871 diffFuncData := BackendDAE.emptyInputData;
2872 75 diffFuncData.matrixName := SOME(funcname);
2873 75 diffFuncData.diffedFunctions := inInputData.diffedFunctions;
2874
2875 //add protected variables to dependent Vars
2876 75 (inputData,_) := addElementVars2Dep(inputVarsNoDer, functions, diffFuncData);
2877 75 (inputData,_) := addElementVars2Dep(outputVarsNoDer, functions, inputData);
2878
2879 75 (protectedVarsDer, functions, protectedVarsNoDer, _) := differentiateElementVars(protectedVars, inDiffwrtCref, inputData, BackendDAE.DIFFERENTIATION_FUNCTION(), functions, {}, {}, {}, maxIter, false);
2880
2881 //add protected variables to dependent Vars
2882 75 (inputData,_) := addElementVars2Dep(protectedVarsNoDer, functions, inputData);
2883
2884
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
75 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2885 ✗ dumpInputData(inputData);
2886 end if;
2887
2888 75 inputData.knownVars := addFunctionConstantsAndParameters(inputData.knownVars, func);
2889
2890 // differentiate algorithm statemeants
2891 //print("Function diff: statemeants");
2892 75 (derbodyStmts, functions) := differentiateStatements(listReverse(bodyStmts), inDiffwrtCref, inputData, BackendDAE.DIFFERENTIATION_FUNCTION(), {}, functions, maxIter);
2893
2894
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
75 if Flags.isSet(Flags.DEBUG_DIFFERENTIATION_VERBOSE) then
2895 ✗ funstring := DAEDump.ppStmtListStr(derbodyStmts, 0);
2896 ✗ print("### Differentiate differentiateFunctionCallPartial stmts: \n" + funstring + "\n\n");
2897 end if;
2898
2899 // create function and add it to function tree
2900 75 (dpath, dtp) := getDiffedTypeandName(func, inputVarsDer, outputVarsDer, blst);
2901
2902 //change output vars to protected vars and direction bidir
2903 75 newProtectedVars := List.map1(outputVars, DAEUtil.setElementVarVisibility, DAE.PROTECTED());
2904 75 newProtectedVars := List.map1(newProtectedVars, DAEUtil.setElementVarDirection, DAE.BIDIR());
2905
2906 150 funcbodyDer := listAppend(newProtectedVars, {DAE.ALGORITHM(DAE.ALGORITHM_STMTS(derbodyStmts), DAE.emptyElementSource)});
2907 75 funcbodyDer := listAppend(protectedVarsDer, funcbodyDer);
2908 75 funcbodyDer := listAppend(protectedVars, funcbodyDer);
2909 75 funcbodyDer := listAppend(outputVarsDer, funcbodyDer);
2910 75 funcbodyDer := listAppend(inputVarsDer, funcbodyDer);
2911 75 funcbodyDer := listAppend(inputVars, funcbodyDer);
2912
2913 75 isImpure := DAEUtil.getFunctionImpureAttribute(func);
2914 75 dinl := DAEUtil.getFunctionInlineType(func);
2915
1/2
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
225 dfunc := DAE.FUNCTION(dpath, {DAE.FUNCTION_DEF(funcbodyDer)}, dtp, visibility, false, isImpure, dinl, {}, DAE.emptyElementSource, NONE());
2916
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 then (dfunc, functions, blst);
2917
2918 else
2919 algorithm
2920 ✗ true := Flags.isSet(Flags.FAILTRACE);
2921 ✗ path := DAEUtil.functionName(inFunction);
2922 ✗ str := "\nDifferentiate.differentiatePartialFunction failed for function: " + AbsynUtil.pathString(path) + "\n";
2923 ✗ Debug.trace(str);
2924 ✗ then fail();
2925 end matchcontinue;
2926 end differentiatePartialFunction;
2927
2928 protected function getDiffedTypeandName
2929 input DAE.Function inFunction;
2930 input list<DAE.Element> inputVarsDer;
2931 input list<DAE.Element> outputVarsDer;
2932 input list<Boolean> blst;
2933 output Absyn.Path diffedName;
2934 output DAE.Type diffedType;
2935 algorithm
2936 77 diffedType := Types.extendsFunctionTypeArgs(DAEUtil.getFunctionType(inFunction), inputVarsDer, outputVarsDer, blst);
2937 77 diffedName := AbsynUtil.stringPath("$DER" + BackendUtil.modelicaStringToCStr(AbsynUtil.pathString(DAEUtil.functionName(inFunction)), false));
2938 end getDiffedTypeandName;
2939
2940 protected function getFunctionInOutVars
2941 input DAE.Function inFunction;
2942 input AvlTreePathFunction.Tree inFunctionTree;
2943 input DAE.ComponentRef inDiffwrtCref;
2944 input Integer maxIter;
2945 output AvlTreePathFunction.Tree functions = inFunctionTree;
2946 output list<DAE.Element> inputVarsDer;
2947 output list<DAE.Element> inputVarsNoDer;
2948 output list<DAE.Element> outputVarsDer;
2949 output list<DAE.Element> outputVarsNoDer;
2950 output list<Boolean> blst;
2951 protected
2952 list<DAE.Element> inputVars, outputVars;
2953 BackendDAE.DifferentiateInputData diffData;
2954 algorithm
2955 77 inputVars := DAEUtil.getFunctionInputVars(inFunction);
2956 77 outputVars := DAEUtil.getFunctionOutputVars(inFunction);
2957 diffData := BackendDAE.emptyInputData;
2958 77 diffData.matrixName := SOME(BackendUtil.modelicaStringToCStr(AbsynUtil.pathString(DAEUtil.functionName(inFunction)), false));
2959
2960 77 (inputVarsDer, functions, inputVarsNoDer, blst) := differentiateElementVars(inputVars, inDiffwrtCref, diffData, BackendDAE.DIFFERENTIATION_FUNCTION(), functions, {}, {}, {}, maxIter, true);
2961 77 (outputVarsDer, functions, outputVarsNoDer, _) := differentiateElementVars(outputVars, inDiffwrtCref, diffData, BackendDAE.DIFFERENTIATION_FUNCTION(), functions, {}, {}, {}, maxIter, false);
2962 end getFunctionInOutVars;
2963
2964 protected function differentiateElementVars
2965 input list<DAE.Element> inElements; // in as DAE.VAR(_)
2966 input DAE.ComponentRef inDiffwrtCref;
2967 input BackendDAE.DifferentiateInputData inInputData;
2968 input BackendDAE.DifferentiationType inDiffType;
2969 input AvlTreePathFunction.Tree inFunctionTree;
2970 input list<DAE.Element> inElementsDer;
2971 input list<DAE.Element> inElementsNoDer;
2972 input list<Boolean> inBooleanLst;
2973 input Integer maxIter;
2974 input Boolean elementListInputs; // filter discrete variables out for inputs
2975 output list<DAE.Element> outElements;
2976 output AvlTreePathFunction.Tree outFunctionTree;
2977 output list<DAE.Element> outElementsNoDer;
2978 output list<Boolean> outBooleanLst;
2979 algorithm
2980 (outElements, outFunctionTree, outElementsNoDer, outBooleanLst) := matchcontinue(inElements, inInputData)
2981 local
2982 BackendDAE.Variables timevars;
2983 list<DAE.Element> rest, vars, elementsNoDer;
2984 DAE.Element var, var1;
2985 DAE.ComponentRef cref, dcref;
2986 list<DAE.ComponentRef> crefLst;
2987 DAE.Exp e;
2988 AvlTreePathFunction.Tree functions;
2989 DAE.Type tp;
2990 DAE.Exp binding, dbinding;
2991 list<Boolean> blst;
2992 String matrixName;
2993
2994 case ({}, _)
2995 229 then (MetaModelica.Dangerous.listReverseInPlace(inElementsDer), inFunctionTree, MetaModelica.Dangerous.listReverseInPlace(inElementsNoDer), MetaModelica.Dangerous.listReverseInPlace(inBooleanLst));
2996
2997 case ((var1 as DAE.VAR(componentRef = cref, ty= (DAE.T_COMPLEX(complexClassType=ClassInf.RECORD())), binding=SOME(binding)))::rest, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName))) algorithm
2998 ✗ dcref := createDiffedCrefName(cref, matrixName);
2999 ✗ var := DAEUtil.replaceCrefInVar(dcref, var1);
3000 ✗ (dbinding,_) := differentiateExp(binding, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
3001 ✗ var := DAEUtil.replaceBindungInVar(dbinding, var);
3002 vars := var::inElementsDer;
3003 blst := true::inBooleanLst;
3004 ✗ (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, vars, inElementsNoDer, blst, maxIter, elementListInputs);
3005 then (vars, functions, elementsNoDer, blst);
3006
3007 case ((var1 as DAE.VAR(componentRef = cref, ty= (DAE.T_COMPLEX(complexClassType=ClassInf.RECORD()))))::rest, BackendDAE.DIFFINPUTDATA(matrixName=SOME(matrixName))) algorithm
3008 63 dcref := createDiffedCrefName(cref, matrixName);
3009 63 var := DAEUtil.replaceCrefInVar(dcref, var1);
3010
3011 //crefLst = List.map1(varLst,Expression.generateCrefsFromExpVar,dcref);
3012 //tpLst = List.map(varLst,Types.getVarType);
3013 //newVars = List.threadMap1(crefLst, tpLst, DAEUtil.replaceCrefandTypeInVar, var);
3014 //elementsNoDer = List.append_reverse(newVars,inElementsNoDer);
3015
3016 vars := var::inElementsDer;
3017 blst := true::inBooleanLst;
3018 63 (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, vars, inElementsNoDer, blst, maxIter, elementListInputs);
3019 then (vars, functions, elementsNoDer, blst);
3020
3021 case((var as DAE.VAR(binding=SOME(binding)))::rest, BackendDAE.DIFFINPUTDATA(independenentVars=SOME(timevars))) algorithm
3022 // check if bindung depends on independentVars
3023 ✗ crefLst := Expression.extractCrefsFromExp(binding);
3024 ✗ ({},{}) := BackendVariable.getVarLst(crefLst, timevars);
3025
3026 vars := var::inElementsNoDer;
3027 blst := false::inBooleanLst;
3028 ✗ (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, inElementsDer, vars, blst, maxIter, elementListInputs);
3029 then (vars, functions, elementsNoDer, blst);
3030
3031 case((var1 as DAE.VAR(componentRef = cref, ty=tp, binding=SOME(binding)))::rest, _) algorithm
3032
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 58 times.
135 if elementListInputs then
3033
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 25 times.
77 true := Types.isRealOrSubTypeReal(tp);
3034 end if;
3035 83 e := Expression.crefExp(cref);
3036 83 (e, functions) := differentiateCrefs(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
3037 83 dcref := Expression.expCref(e);
3038 83 var := DAEUtil.replaceCrefInVar(dcref, var1);
3039 83 (dbinding, functions) := differentiateExp(binding, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
3040 83 var := DAEUtil.replaceBindungInVar(dbinding, var);
3041 vars := var::inElementsDer;
3042 blst := true::inBooleanLst;
3043 83 (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, functions, vars, inElementsNoDer, blst, maxIter, elementListInputs);
3044 then (vars, functions, elementsNoDer, blst);
3045
3046 case((var1 as DAE.VAR(componentRef = cref, ty=tp))::rest, _) algorithm
3047
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 220 times.
400 if elementListInputs then
3048
2/2
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 126 times.
180 true := Types.isRealOrSubTypeReal(tp);
3049 end if;
3050 346 e := Expression.crefExp(cref);
3051 346 (e, functions) := differentiateCrefs(e, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, maxIter);
3052 346 dcref := Expression.expCref(e);
3053 346 var := DAEUtil.replaceCrefInVar(dcref, var1);
3054 vars := var::inElementsDer;
3055 blst := true::inBooleanLst;
3056 346 (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, functions, vars, inElementsNoDer, blst, maxIter, elementListInputs);
3057 then (vars, functions, elementsNoDer, blst);
3058
3059 case((var as DAE.VAR())::rest, _) algorithm
3060 elementsNoDer := var::inElementsNoDer;
3061 blst := false::inBooleanLst;
3062 54 (vars, functions, elementsNoDer, blst) := differentiateElementVars(rest, inDiffwrtCref, inInputData, inDiffType, inFunctionTree, inElementsDer, elementsNoDer, blst, maxIter, elementListInputs);
3063 then (vars, functions, elementsNoDer, blst);
3064 end matchcontinue;
3065 end differentiateElementVars;
3066
3067 protected function differentiateFunction1 "Author: Frenkel TUD"
3068 input Absyn.Path inFuncName;
3069 input DAE.FunctionDefinition inMapper;
3070 input DAE.Type inTp;
3071 input list<DAE.Exp> expl;
3072 input BackendDAE.DifferentiateInputArguments inDiffArgs;
3073 output Absyn.Path outFuncName;
3074 output list<Boolean> blst;
3075 algorithm
3076 (outFuncName,blst) := matchcontinue (inMapper, inTp, inDiffArgs)
3077 local
3078 AvlTreePathFunction.Tree functions;
3079 Absyn.Path default,fname,da,inDFuncName;
3080 list<tuple<Integer,DAE.derivativeCond>> cr;
3081 Integer derivativeOrder;
3082 list<DAE.FuncArg> funcArg;
3083 list<DAE.Type> tplst;
3084 list<Boolean> bl;
3085 list<Absyn.Path> lowerOrderDerivatives;
3086 DAE.FunctionDefinition mapper;
3087 DAE.Type tp;
3088 array<Boolean> ba;
3089
3090 // check conditions, order=1
3091 case (DAE.FUNCTION_DER_MAPPER(derivativeFunction=inDFuncName,derivativeOrder=derivativeOrder,conditionRefs=cr), DAE.T_FUNCTION(funcArg=funcArg), _)
3092 guard intEq(1,derivativeOrder)
3093 algorithm
3094 6708 tplst := List.map(funcArg,Types.funcArgType);
3095 6708 ba := Array.mapList(tplst, diffableTypes);
3096 6708 bl := checkDerFunctionConds(ba,cr,expl,inDiffArgs);
3097 6706 then
3098 (inDFuncName,bl);
3099 // check conditions, order>1
3100 case (DAE.FUNCTION_DER_MAPPER(derivativeFunction=inDFuncName,derivativeOrder=derivativeOrder,conditionRefs=cr), tp, (_,_,_,functions))
3101 guard not intEq(1,derivativeOrder)
3102 algorithm
3103 // get n-1 func name
3104 15 fname := getlowerOrderDerivative(inFuncName,functions);
3105 // get mapper
3106 15 (mapper,tp) := getFunctionMapper(fname,functions);
3107 // get bool list
3108 15 (_,blst) := differentiateFunction1(fname,mapper,tp,expl,inDiffArgs);
3109 // count true
3110 15 (bl,_) := List.split1OnTrue(blst, valueEq, true);
3111 15 ba := arrayAppend(arrayCreate(listLength(blst), false), listArray(bl));
3112 15 bl := checkDerFunctionConds(ba,cr,expl,inDiffArgs);
3113 15 then
3114 (inDFuncName,bl);
3115 // conditions failed use default
3116 case (DAE.FUNCTION_DER_MAPPER(derivedFunction=fname,derivativeOrder=derivativeOrder,defaultDerivative=SOME(default),lowerOrderDerivatives=lowerOrderDerivatives), tp, _)
3117 algorithm
3118 ✗ (da,bl) := differentiateFunction1(inFuncName,DAE.FUNCTION_DER_MAPPER(fname,default,derivativeOrder,{},SOME(default),lowerOrderDerivatives),tp,expl,inDiffArgs);
3119 then
3120 (da,bl);
3121 end matchcontinue;
3122 end differentiateFunction1;
3123
3124 protected function checkDerivativeFunctionInputs "Author: Frenkel TUD"
3125 input list<Boolean> blst;
3126 input DAE.Type tp;
3127 input DAE.Type dtp;
3128 output Boolean outBoolean;
3129 output list<DAE.Type> outExpectedTypeLst;
3130 algorithm
3131 (outBoolean,outExpectedTypeLst) := matchcontinue(tp, dtp)
3132 local
3133 list<DAE.FuncArg> falst,falst1,falst2,dfalst;
3134 list<DAE.Type> tlst,dtlst;
3135 Boolean ret;
3136
3137 case (DAE.T_FUNCTION(funcArg=falst), DAE.T_FUNCTION(funcArg=dfalst)) algorithm
3138 // generate expected function inputs
3139 6692 (falst1,_) := List.splitOnBoolList(falst,blst);
3140 6692 falst2 := listAppend(falst,falst1);
3141 // compare with derivative function inputs
3142 6692 tlst := List.map(falst2,Types.funcArgType);
3143 6692 dtlst := List.map(dfalst,Types.funcArgType);
3144 6692 ret := List.isEqualOnTrue(tlst,dtlst,Types.equivtypes);
3145 then (ret,tlst);
3146
3147 case (_, _)
3148 algorithm
3149 ✗ true := Flags.isSet(Flags.FAILTRACE);
3150 ✗ Debug.trace("-Differentiate.checkDerivativeFunctionInputs failed\n");
3151 ✗ then fail();
3152 end matchcontinue;
3153 end checkDerivativeFunctionInputs;
3154
3155 protected function checkDerFunctionConds "Author: Frenkel TUD"
3156 input array<Boolean> inbarr;
3157 input list<tuple<Integer,DAE.derivativeCond>> icrlst;
3158 input list<DAE.Exp> expl;
3159 input BackendDAE.DifferentiateInputArguments inDiffArgs;
3160 output list<Boolean> outblst;
3161 protected
3162 Integer i;
3163 DAE.derivativeCond dc;
3164 DAE.Exp e;
3165 Absyn.Path p1, p2;
3166 array<Boolean> ba = inbarr;
3167 DAE.ComponentRef diffwrtCref;
3168 BackendDAE.DifferentiateInputData inputData;
3169 BackendDAE.DifferentiationType diffType;
3170 AvlTreePathFunction.Tree functionTree;
3171 algorithm
3172 6723 (diffwrtCref, inputData, diffType, functionTree) := inDiffArgs;
3173
3174
2/2
✓ Branch 0 taken 5015 times.
✓ Branch 1 taken 6721 times.
11736 for tpl in icrlst loop
3175 5015 (i, dc) := tpl;
3176
3177 () := matchcontinue dc
3178 // Zero derivative, check that it's actually zero.
3179 case DAE.ZERO_DERIVATIVE()
3180 algorithm
3181 // Get expression.
3182 878 e := listGet(expl, i);
3183 // Differentiate exp.
3184 878 (e, functionTree) := differentiateExp(e, diffwrtCref, inputData, diffType, functionTree, defaultMaxIter);
3185
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 876 times.
878 true := isZeroDerivative(e);
3186 then
3187 ();
3188
3189 case DAE.NO_DERIVATIVE(binding = DAE.CALL(path = p1))
3190 algorithm
3191 // Get expression.
3192
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 DAE.CALL(path = p2) := listGet(expl, i);
3193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := AbsynUtil.pathEqual(p1, p2);
3194 then
3195 ();
3196
3197 case DAE.NO_DERIVATIVE(binding = DAE.ICONST()) then ();
3198
3199 else
3200 algorithm
3201
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
3202 ✗ Debug.traceln("-Differentiate.checkDerFunctionConds failed");
3203 ✗ then
3204 fail();
3205
3206 end matchcontinue;
3207
3208 // Remove input from array.
3209 5013 arrayUpdate(ba, i, false);
3210 end for;
3211
3212 6721 outblst := arrayList(ba);
3213 end checkDerFunctionConds;
3214
3215 protected function zeroOfType
3216 "Zero seed of the given type, for arguments and record components that have no
3217 derivative of their own. Differentiation yields a real zero for those, which
3218 is not type correct in a String, Boolean, enumeration or record slot."
3219 input DAE.Type inType;
3220 output DAE.Exp outZero;
3221 algorithm
3222 outZero := match inType
3223 local
3224 Absyn.Path path;
3225 String name;
3226 list<DAE.Var> varLst;
3227
3228 case DAE.T_STRING() then DAE.SCONST("");
3229 case DAE.T_BOOL() then DAE.BCONST(false);
3230
3231 case DAE.T_ENUMERATION(path = path, names = name :: _)
3232 ✗ then DAE.ENUM_LITERAL(AbsynUtil.suffixPath(path, name), 1);
3233
3234 case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = path), varLst = varLst)
3235
4/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 4 times.
56 then DAE.CALL(path, list(zeroOfType(DAEUtil.varType(v)) for v in varLst),
3236 DAE.CALL_ATTR(inType, false, false, false, false, DAE.NO_INLINE(), DAE.NO_TAIL(), DAE.NoReturn.RETURNS));
3237
3238 48 else Expression.makeConstZero(inType);
3239 end match;
3240 end zeroOfType;
3241
3242 protected function typedZeroSeed
3243 "The zero seeds of the arguments of a partially differentiated call are made
3244 by differentiating them with respect to a dummy variable, which yields a real
3245 zero for an argument that has no derivative of its own. A record, String,
3246 Boolean or enumeration argument needs a seed of its own type, a real zero in
3247 such a slot does not compile."
3248 input DAE.Exp inArg;
3249 input DAE.Exp inZero;
3250 output DAE.Exp outZero = inZero;
3251 protected
3252 DAE.Type ty;
3253 algorithm
3254
2/2
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 7704 times.
7813 if Expression.isZero(inZero) then
3255 7704 ty := Expression.typeof(inArg);
3256
5/8
✓ Branch 1 taken 7700 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 7700 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7700 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7700 times.
✗ Branch 11 not taken.
7704 if Types.isRecord(ty) or Types.isString(ty) or Types.isBoolean(ty) or Types.isEnumeration(ty) then
3257 4 outZero := zeroOfType(ty);
3258 end if;
3259 end if;
3260 end typedZeroSeed;
3261
3262 protected function isZeroDerivative
3263 "Returns true if the given differentiated expression is zero. In contrast to
3264 Expression.isZero this also handles record valued derivatives, which are
3265 built as record constructors with one zero per component, and the seeds of
3266 String, Boolean and enumeration components, which have no derivative."
3267 input DAE.Exp inExp;
3268 output Boolean outZero;
3269 algorithm
3270 outZero := match inExp
3271 local
3272 list<DAE.Exp> expl;
3273 Absyn.Path path, rpath;
3274
3275 case DAE.RECORD(exps = expl)
3276 93 then List.all(expl, isZeroDerivative);
3277
3278 // a record constructor call, i.e. the call path is the record path
3279 case DAE.CALL(path = path, expLst = expl, attr = DAE.CALL_ATTR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = rpath))))
3280 guard AbsynUtil.pathEqual(path, rpath)
3281 1 then List.all(expl, isZeroDerivative);
3282
3283 case DAE.ARRAY(array = expl)
3284 807 then List.all(expl, isZeroDerivative);
3285
3286 // the seed of a String, Boolean or enumeration component, which has no
3287 // derivative of its own. A component reference is not one of these, a
3288 // Jacobian differentiates such a component to a seed variable.
3289 case DAE.SCONST() then true;
3290 case DAE.BCONST() then true;
3291 case DAE.ENUM_LITERAL() then true;
3292
3293 4602 else Expression.isZero(inExp);
3294 end match;
3295 end isZeroDerivative;
3296
3297 protected function getlowerOrderDerivative "Author: Frenkel TUD"
3298 input Absyn.Path fname;
3299 input AvlTreePathFunction.Tree functions;
3300 output Absyn.Path outFName;
3301 algorithm
3302 outFName := match functions
3303 local
3304 list<DAE.FunctionDefinition> flst;
3305 list<Absyn.Path> lowerOrderDerivatives;
3306 Absyn.Path name;
3307 case _
3308 algorithm
3309
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
15 SOME(DAE.FUNCTION(functions=flst)) := AvlTreePathFunction.get(functions,fname);
3310
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 DAE.FUNCTION_DER_MAPPER(lowerOrderDerivatives=lowerOrderDerivatives) := getFunctionMapper1(flst);
3311 15 name := List.last(lowerOrderDerivatives);
3312 then name;
3313 end match;
3314 end getlowerOrderDerivative;
3315
3316 public function getFunctionMapper "Author: Frenkel TUD"
3317 input Absyn.Path fname;
3318 input AvlTreePathFunction.Tree functions;
3319 output DAE.FunctionDefinition mapper;
3320 output DAE.Type tp;
3321 algorithm
3322 (mapper,tp) := matchcontinue functions
3323 local
3324 list<DAE.FunctionDefinition> flst;
3325 DAE.Type t;
3326 DAE.FunctionDefinition m;
3327 String s;
3328 case _
3329 algorithm
3330
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 57588 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57588 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57588 times.
77969 SOME(DAE.FUNCTION(functions=flst,type_=t)) := AvlTreePathFunction.get(functions,fname);
3331 57588 m := getFunctionMapper1(flst);
3332 then (m,t);
3333 case _
3334 algorithm
3335
1/2
✓ Branch 1 taken 58611 times.
✗ Branch 2 not taken.
58611 true := Flags.isSet(Flags.FAILTRACE);
3336 ✗ s := AbsynUtil.pathString(fname);
3337 ✗ s := stringAppend("-Differentiate.getFunctionMapper failed for function ",s);
3338 ✗ Debug.traceln(s);
3339 ✗ then
3340 fail();
3341 end matchcontinue;
3342 end getFunctionMapper;
3343
3344 protected function getFunctionMapper1 "Author: Frenkel TUD"
3345 input list<DAE.FunctionDefinition> inFuncDefs;
3346 output DAE.FunctionDefinition mapper;
3347 algorithm
3348 mapper := matchcontinue inFuncDefs
3349 local
3350 DAE.FunctionDefinition m;
3351 list<DAE.FunctionDefinition> funcDefs;
3352
3353 case (m as DAE.FUNCTION_DER_MAPPER())::_ then m;
3354 case _::funcDefs
3355 algorithm
3356 57825 m := getFunctionMapper1(funcDefs);
3357 then m;
3358 case _
3359 algorithm
3360
1/2
✓ Branch 1 taken 76682 times.
✗ Branch 2 not taken.
76682 true := Flags.isSet(Flags.FAILTRACE);
3361 ✗ Debug.trace("-Differentiate.getFunctionMapper1 failed\n");
3362 ✗ then
3363 fail();
3364 end matchcontinue;
3365 end getFunctionMapper1;
3366
3367 protected function diffableTypes
3368 input DAE.Type inType;
3369 output Boolean out = Types.isRealOrSubTypeReal(inType) or Types.isRecord(inType);
3370 end diffableTypes;
3371
3372
3373 //
3374 // util functions for Types: DifferentiateInputData, DifferentiateInputArguments, DifferentiationType
3375 //
3376
3377 protected function addDependentVars
3378 input list<BackendDAE.Var> inVarsLst;
3379 input BackendDAE.DifferentiateInputData inDiffData;
3380 output BackendDAE.DifferentiateInputData outDiffData = inDiffData;
3381 protected
3382 BackendDAE.Variables depVars;
3383 algorithm
3384
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 150 times.
225 if isSome(outDiffData.dependenentVars) then
3385 150 depVars := BackendVariable.addVars(inVarsLst, Util.getOption(outDiffData.dependenentVars));
3386 else
3387 75 depVars := BackendVariable.listVar(inVarsLst);
3388 end if;
3389 225 outDiffData.dependenentVars := SOME(depVars);
3390 end addDependentVars;
3391
3392 protected function addAllVars
3393 input list<BackendDAE.Var> inVarsLst;
3394 input BackendDAE.DifferentiateInputData inDiffData;
3395 output BackendDAE.DifferentiateInputData outDiffData = inDiffData;
3396 protected
3397 BackendDAE.Variables allVars;
3398 algorithm
3399 ✗ if isSome(outDiffData.allVars) then
3400 ✗ allVars := BackendVariable.addVars(inVarsLst, Util.getOption(outDiffData.allVars));
3401 else
3402 ✗ allVars := BackendVariable.listVar(inVarsLst);
3403 end if;
3404 ✗ outDiffData.allVars := SOME(allVars);
3405 end addAllVars;
3406
3407 protected function addGlobalVars
3408 input list<BackendDAE.Var> inVarsLst;
3409 input BackendDAE.DifferentiateInputData inDiffData;
3410 output BackendDAE.DifferentiateInputData outDiffData = inDiffData;
3411 protected
3412 BackendDAE.Variables glVars;
3413 algorithm
3414
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if isSome(outDiffData.knownVars) then
3415 4 glVars := BackendVariable.addVars(inVarsLst, Util.getOption(outDiffData.knownVars));
3416 else
3417 2 glVars := BackendVariable.listVar(inVarsLst);
3418 end if;
3419 6 outDiffData.knownVars := SOME(glVars);
3420 end addGlobalVars;
3421
3422 protected function lowerVarsElementVars
3423 input list<DAE.Element> inElementLstVars;
3424 input AvlTreePathFunction.Tree functions;
3425 output list< BackendDAE.Var> varsLst;
3426 output list< BackendDAE.Equation> eqnsLst;
3427 output list< BackendDAE.Equation> reqnsLst;
3428 protected
3429 list<BackendDAE.Var> vars, knvars, exvars;
3430 algorithm
3431 try
3432 225 (vars, knvars, exvars, eqnsLst, reqnsLst) :=
3433 BackendDAECreate.lowerVars(inElementLstVars, functions);
3434 225 varsLst := listAppend(exvars, listAppend(vars, knvars));
3435 else
3436 ✗ true := Flags.isSet(Flags.FAILTRACE);
3437 ✗ Debug.traceln("- Differentiate.lowerVarsElementVars failed.");
3438 ✗ fail();
3439 end try;
3440 end lowerVarsElementVars;
3441
3442 protected function addElementVars2Dep
3443 input list<DAE.Element> inElementLstVars;
3444 input AvlTreePathFunction.Tree inFunctions;
3445 input BackendDAE.DifferentiateInputData inDiffData;
3446 output BackendDAE.DifferentiateInputData outDiffData;
3447 output list< BackendDAE.Equation> outEqnsLst;
3448 protected
3449 list<BackendDAE.Var> varsLst;
3450 algorithm
3451 try
3452 225 (varsLst, outEqnsLst) := lowerVarsElementVars(inElementLstVars, inFunctions);
3453 225 outDiffData := addDependentVars(varsLst, inDiffData);
3454 else
3455 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Differentiate.addElementVars2Dep failed"});
3456 ✗ fail();
3457 end try;
3458 end addElementVars2Dep;
3459
3460 protected function dumpInputData
3461 input BackendDAE.DifferentiateInputData inDiffData;
3462 protected
3463 Option<BackendDAE.Variables> independenentVars;
3464 Option<BackendDAE.Variables> dependenentVars;
3465 Option<BackendDAE.Variables> knownVars;
3466 Option<BackendDAE.Variables> allVars;
3467 list<BackendDAE.Var> controlVars;
3468 list<.DAE.ComponentRef> diffCrefs;
3469 Option<String> matrixName;
3470 algorithm
3471 ✗ print("### dumpInputData ###\n");
3472 ✗ if isSome(inDiffData.matrixName) then
3473 ✗ print("### for " + Util.getOption(inDiffData.matrixName) +" ###\n");
3474 end if;
3475 ✗ if isSome(inDiffData.independenentVars) then
3476 ✗ print("independentVars:\n");
3477 ✗ BackendDump.printVariables(Util.getOption(inDiffData.independenentVars));
3478 end if;
3479 ✗ if isSome(inDiffData.dependenentVars) then
3480 ✗ print("dependenentVars:\n");
3481 ✗ BackendDump.printVariables(Util.getOption(inDiffData.dependenentVars));
3482 end if;
3483 ✗ if isSome(inDiffData.knownVars) then
3484 ✗ print("knownVars:\n");
3485 ✗ BackendDump.printVariables(Util.getOption(inDiffData.knownVars));
3486 end if;
3487 ✗ if isSome(inDiffData.allVars) then
3488 ✗ print("allVars:\n");
3489 ✗ BackendDump.printVariables(Util.getOption(inDiffData.allVars));
3490 end if;
3491 ✗ if not listEmpty(inDiffData.controlVars) then
3492 ✗ print("controlVars:\n");
3493 ✗ BackendDump.printVarList(inDiffData.controlVars);
3494 end if;
3495 ✗ if not listEmpty(inDiffData.diffCrefs) then
3496 ✗ print("diffCrefs:\n" + ComponentReferenceBasics.printComponentRefListStr(inDiffData.diffCrefs) + "\n");
3497 end if;
3498 end dumpInputData;
3499
3500 protected function isParamOrConstant
3501 input DAE.ComponentRef cref;
3502 input BackendDAE.DifferentiateInputData diffData;
3503 output Boolean b;
3504 algorithm
3505 b := match diffData
3506 local
3507 BackendDAE.Variables knownVars;
3508 Option<list<BackendDAE.Var>> var_lst;
3509 BackendDAE.Var var;
3510 case BackendDAE.DIFFINPUTDATA(knownVars = SOME(knownVars)) algorithm
3511 513 var_lst := BackendVariable.getVarTryHard(cref, knownVars);
3512
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 513 times.
✓ Branch 2 taken 488 times.
✓ Branch 3 taken 25 times.
513 if isSome(var_lst) then
3513
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 488 times.
488 var :: _ := Util.getOption(var_lst);
3514 488 b := BackendVariable.isParamOrConstant(var);
3515 else
3516 b := false;
3517 end if;
3518 then b;
3519 else false;
3520 end match;
3521 end isParamOrConstant;
3522
3523 annotation(__OpenModelica_Interface="backend");
3524 end Differentiate;
3525