Skip to content

Commit

Permalink
[NB] add function and algorithm differentiation (#8644)
Browse files Browse the repository at this point in the history
* [NB] add function and algorithm differentiation

 - algorithms and statements are differentiated properly
 - functions and function bodys are differentiated
   - recursion is handled
   - multiple occurences are handled
   - ToDo: strip interface variables such that only continuous are differentiated

* [NB] improve function differentiation

  1. if the function is builtin -> use hardcoded logic
  2. if the function is not builtin -> check if there is a 'fitting' derivative defined.
    - 'fitting' means that all the zeroDerivative annotations have to hold
  2.1 fitting function found -> use it
  2.2 fitting function not found -> differentiate the body of the function
  ToDo: respect the 'order' of the derivative when differentiating!
  • Loading branch information
kabdelhak committed Mar 8, 2022
1 parent 55f5d0d commit 1732387
Show file tree
Hide file tree
Showing 12 changed files with 577 additions and 162 deletions.
58 changes: 39 additions & 19 deletions OMCompiler/Compiler/NBackEnd/Classes/NBVariable.mo
Expand Up @@ -305,11 +305,11 @@ public
output Boolean b;
algorithm
b := match Pointer.access(var)
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.DISCRETE_STATE())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.DISCRETE())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.PREVIOUS())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.PARAMETER())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.CONSTANT())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.DISCRETE_STATE())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.DISCRETE())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.PREVIOUS())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.PARAMETER())) then false;
case Variable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(varKind = BackendExtension.CONSTANT())) then false;
else true;
end match;
end isContinuous;
Expand Down Expand Up @@ -818,21 +818,19 @@ public
_ := match ComponentRef.node(cref)
local
InstNode qual;
Pointer<Variable> old_var_ptr;
Variable var;
case qual as InstNode.VAR_NODE()
algorithm
// get the variable pointer from the old cref to later on link back to it
old_var_ptr := BVariable.getVarPointer(cref);
// prepend the seed str and the matrix name and create the new cref_DIFF_DIFF
qual.name := PARTIAL_DERIVATIVE_STR + "_" + name;
cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
var := fromCref(cref);
// update the variable to be a jac var and pass the pointer to the original variable
// ToDo: tmps will get JAC_DIFF_VAR !
var.backendinfo := BackendExtension.BackendInfo.setVarKind(var.backendinfo, BackendExtension.JAC_VAR());
// create the new variable pointer and safe it to the component reference
(var_ptr, cref) := makeVarPtrCyclic(var, cref);

// regular case for jacobians
case qual as InstNode.VAR_NODE() algorithm
// prepend the seed str and the matrix name and create the new cref_DIFF_DIFF
qual.name := PARTIAL_DERIVATIVE_STR + "_" + name;
cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
var := fromCref(cref);
// update the variable to be a jac var and pass the pointer to the original variable
// ToDo: tmps will get JAC_DIFF_VAR !
var.backendinfo := BackendExtension.BackendInfo.setVarKind(var.backendinfo, BackendExtension.JAC_VAR());
// create the new variable pointer and safe it to the component reference
(var_ptr, cref) := makeVarPtrCyclic(var, cref);
then ();

else algorithm
Expand All @@ -841,6 +839,28 @@ public
end match;
end makePDerVar;

function makeFDerVar
"Creates a function derivative cref. Used in NBDifferentiation
for differentiating body vars of a function."
input output ComponentRef cref "old component reference to new component reference";
algorithm
cref := match ComponentRef.node(cref)
local
InstNode qual;

// for function differentiation (crefs are not lowered and only known locally)
case qual as InstNode.COMPONENT_NODE() algorithm
// prepend the seed str, matrix name locally not needed
qual.name := FUNCTION_DERIVATIVE_STR + "_" + qual.name;
cref := ComponentRef.fromNode(qual, ComponentRef.scalarType(cref));
then cref;

else algorithm
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
then fail();
end match;
end makeFDerVar;

function makeStartVar
"Creates a start variable pointer from a cref. Used in NBInitialization.
e.g: angle -> $START.angle"
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NBackEnd/Modules/3_Post/NBJacobian.mo
Expand Up @@ -537,7 +537,6 @@ protected
jacobianHT = optHT, // seed and temporary cref hashtable
diffType = NBDifferentiate.DifferentiationType.JACOBIAN,
funcTree = funcTree,
diffedFunctions = AvlSetPath.new(),
scalarized = seedCandidates.scalarized
);

Expand All @@ -546,6 +545,7 @@ protected

(diffed_eqn_lst, diffArguments) := Differentiate.differentiateEquationPointerList(listReverse(eqn_lst), diffArguments, idx, name, getInstanceName());
diffedEquations := EquationPointers.fromList(diffed_eqn_lst);
funcTree := diffArguments.funcTree;

// create equation data for jacobian
// ToDo: split temporary and auxiliares once tearing is applied
Expand Down
1 change: 0 additions & 1 deletion OMCompiler/Compiler/NBackEnd/Modules/3_Post/NBSolve.mo
Expand Up @@ -385,7 +385,6 @@ public
jacobianHT = NONE(),
diffType = NBDifferentiate.DifferentiationType.SIMPLE,
funcTree = funcTree,
diffedFunctions = AvlSetPath.new(),
scalarized = false
);
(derivative, diffArgs) := Differentiate.differentiateExpressionDump(residual, diffArgs, getInstanceName());
Expand Down
19 changes: 19 additions & 0 deletions OMCompiler/Compiler/NBackEnd/Util/NBBackendUtil.mo
Expand Up @@ -638,5 +638,24 @@ public
end if;
end isOnlyTimeDependentFold;

function isContinuous
input Expression exp;
output Boolean b;
algorithm
b := Expression.fold(exp, isContinuousFold, true);
end isContinuous;

function isContinuousFold
input Expression exp;
input output Boolean b;
algorithm
if b then
b := match exp
case Expression.CREF() then BVariable.checkCref(exp.cref, BVariable.isContinuous);
else true;
end match;
end if;
end isContinuousFold;

annotation(__OpenModelica_Interface="backend");
end NBBackendUtil;

0 comments on commit 1732387

Please sign in to comment.