Opened 11 years ago

Closed 7 months ago

#2538 closed defect (fixed)

Support for partial derivatives of functions

Reported by: Adrian Pop Owned by: Per Östlund
Priority: blocker Milestone: Future
Component: New Instantiation Version: trunk
Keywords: Cc: Karim Adbdelhak, Andreas Heuermann

Description

It seems we have no support for partial derivatives of functions.
See the attached model and Modelica Spec 3.2 revision 2, Section 12.7.2.

The question is how we should handle this?
We save the information for the back-end?

We have a function definition such as:

function df_dqflow = der(flowCharacteristic, q_flow);

Use this script:

loadFile("tfm.mo"); getErrorString();
simulate(ThermoPower.Test.GasComponents.TestFanMech); getErrorString();

Attachments (1)

tfm.mo (289.5 KB ) - added by Adrian Pop 11 years ago.

Download all attachments as: .zip

Change History (34)

by Adrian Pop, 11 years ago

Attachment: tfm.mo added

comment:1 by Adrian Pop, 11 years ago

When we try to simulate this model we get:

ThermoPower/Gas.mo:3223:7-3226:21:writable] Error: Class df_dqflow not found in scope ThermoPower.Gas.FanMech (looking for a function or record).
Error: Error occurred while flattening model ThermoPower.Test.GasComponents.TestFanMech

comment:2 by Adrian Pop, 11 years ago

Owner: changed from somebody to Adrian Pop
Status: newassigned
Summary: Partial derivatives of functions supportSupport for partial derivatives of functions

comment:3 by Adrian Pop, 11 years ago

Cc: Willi Braun Lennart Ochel Martin Sjölund added

Any comments/suggestions on how to handle partial derivatives of functions?
The specification seems to be rather vague about this.

comment:4 by Francesco Casella, 11 years ago

My understanding is that Automatic Differentiation techniques should be used in order to process the algorithm of the function, resulting in the algorithm that computes the derivatives. Dymola has been doing that for 10 years now, we've used this feature in the past for terrain representation in vehicle simulation.

Please note I will remove these partial derivatives from ThermoPower right away (they are used for simplified models in homotopy, but I can figure out other simplified models that don't need this information). As long as you keep using Adrian's provided .mo file for testing, it's ok.

comment:5 by Willi Braun, 11 years ago

Basically our differentiation model is also able to differentiate that, but we just haven't considered such cases so far.

Adrian, we need to call the differentiate module at a certain point in the frontend to generate a new differentiated function. So I would create an interface function therefore in the differentiation module.

Last edited 11 years ago by Willi Braun (previous) (diff)

comment:6 by Adrian Pop, 11 years ago

Willi introduced a new interface Differentiate.differentiateFunctionPartial in r18683.
I'll use this in the front-end to generate a new function with the given name and
add it to the environment (a bit of a question on how here) and to the function tree.

comment:7 by Martin Sjölund, 10 years ago

Milestone: 1.9.11.9.2

This ticket was not closed for 1.9.1, which has now been released. It was batch modified for milestone 1.9.2 (but maybe an empty milestone was more appropriate; feel free to change it).

comment:8 by Martin Sjölund, 10 years ago

Milestone: 1.9.21.9.3

Milestone changed to 1.9.3 since 1.9.2 was released.

comment:9 by Martin Sjölund, 9 years ago

Adrian: How did this work go?

comment:10 by Adrian Pop, 9 years ago

No idea. Maybe Willi knows more.

comment:11 by Adrian Pop, 9 years ago

Ah, we dö not yet handle it in the frontend but i guess should be easy to add.
I will have a look.

comment:12 by Martin Sjölund, 9 years ago

Milestone: 1.9.31.9.4

Moved to new milestone 1.9.4

comment:13 by Martin Sjölund, 9 years ago

Milestone: 1.9.41.9.5

Milestone pushed to 1.9.5

comment:14 by Martin Sjölund, 9 years ago

Milestone: 1.9.51.10.0

Milestone renamed

comment:15 by Martin Sjölund, 8 years ago

Milestone: 1.10.01.11.0

Ticket retargeted after milestone closed

comment:16 by Martin Sjölund, 8 years ago

Milestone: 1.11.01.12.0

Milestone moved to 1.12.0 due to 1.11.0 already being released.

comment:17 by Francesco Casella, 7 years ago

Milestone: 1.12.0Future

The milestone of this ticket has been reassigned to "Future".

If you think the issue is still valid and relevant for you, please select milestone 1.13.0 for back-end, code generation and run-time issues, or 2.0.0 for front-end issues.

If you are aware that the problem is no longer present, please select the milestone corresponding to the version of OMC you used to check that, and set the status to "worksforme".

In both cases, a short informative comment would be welcome.

comment:18 by Francesco Casella, 6 years ago

Simpler test model:

model TestDerivative
  function f
    input Real x;
    input Real y;
    output Real z;
  algorithm
    z := 1;
    z := z + x*y;
  end f;
  
  function dfdx = der(f,x);
  
  Real x = time;
  Real df;
equation
  df = dfdx(x, x^2);
end TestDerivative;

Gives the following error with both OF and NF:

[1] 01:14:09 Translation Error
[TestDerivative: 16:3-16:20]: Class dfdx not found in scope TestDerivative
(looking for a function or record).

comment:19 by Francesco Casella, 5 years ago

Component: FrontendNew Instantiation
Milestone: Future2.0.0
Priority: highblocker

I think this should be resolved in 2.0.0. We do have all the needed primitives in the backend, as I understand it's just a matter of connecting the dots from the NF.

comment:20 by Francesco Casella, 5 years ago

Cc: Karim Adbdelhak Andreas Heuermann added; Francesco Casella Willi Braun Lennart Ochel Martin Sjölund removed
Milestone: 2.0.01.16.0
Owner: changed from Adrian Pop to Per Östlund

@perost, can you coordinate with @Karim and @AnHeuermann to get this done?

It should be rather straightforward.

in reply to:  20 ; comment:21 by Per Östlund, 5 years ago

Replying to casella:

It should be rather straightforward.

That depends on what kind of support we need for partial derivatives of functions in the NF. The Differentiate module is made for the old DAE structures, so using it in the NF is not really possible (the NF can translate to OF format, but too much is lost in that translation which makes translating back to NF format very nontrivial).

This means that if we want the NF to be able to generate the body of a partial derivative we'd have to rewrite the Differentiate module using the NF structures. This is needed if we want the NF to be able to evaluate partial derivatives of functions.

If we don't care about being able to evaluate such functions I guess we can just pass them through the frontend, in which case we only need to know their type (which is the same as the function being derived?).

Then we can generate the partial derivatives either during the conversion to DAE or somewhere in the backend. Differentiate.differentiatePartialFunction takes some backend structures as argument that the NF can't generate, so I guess where to do it depends on how important those arguments are.

in reply to:  21 comment:22 by Francesco Casella, 5 years ago

Replying to perost:

If we don't care about being able to evaluate such functions

I think this is definitely the case. Of course it may be good for efficiency reason to be able do so in some cases, but if we can't, it's no big deal.

I guess we can just pass them through the frontend,

That was my idea. The machinery to compute total derivatives of functions is only there, computing partial derivatives is actually a special case of that, so it should be easy to implement.

in which case we only need to know their type (which is the same as the function being derived?).

Not exactly, the unit of the differentiated funtion output is of course the unit of the original function output divided by the unit of the variable w.r.t. which the function is differentiated. As far as I understand, everything else should be the same.

Then we can generate the partial derivatives either during the conversion to DAE or somewhere in the backend. Differentiate.differentiatePartialFunction takes some backend structures as argument that the NF can't generate, so I guess where to do it depends on how important those arguments are.

Never mind that, let's leave the job to the backend, you only need to prepare the patient on the operating table.

comment:23 by Karim Adbdelhak, 5 years ago

Differentiating a function w.r.t. a cref should not be a problem, as long as we know all the dependencies. But i don't really understand what is supposed to happen in your example.

If we differentiate the function

  function f
    input Real x;
    input Real y;
    output Real z;
  algorithm
    z := 1;
    z := z + x*y;
  end f;

like you imply with this call w.r.t x

  function dfdx = der(f,x);

It would look somewhat like this:

  function dfdx
    input Real x;
    input Real y;
    output Real z;
  algorithm
    z := 0;
    z := z + y;
  end dfdx;

so the equation

  df = dfdx(x, x^2);

could be simplified to be

  df = x^2;

Is that what you would expect?

Version 0, edited 5 years ago by Karim Adbdelhak (next)

comment:24 by Francesco Casella, 5 years ago

I'm not an expert in AD, but what I understand is that you keep the original algorithm and add the instructions to compute the derivatives alongside it. Hence, if you take

  function f
    input Real x;
    input Real y;
    output Real z;
  algorithm
    z := 1;
    z := z*x + z*y + x*y;
    z := z*z;
  end f;

then der(f,x) can be computed as

  function df
    input Real x;
    input Real y;
    output Real dz_x;
  algorithm
    dz_x := 0;
    z    := 1;

    dz_x := z   +   0 + y
    z    := z*x + z*y + x*y;

    dz_x := 2*z*dz_dx;
    z    := z*z;
  end f;

Indeed, if you simbolically substitute all the steps, the first function returns (x + y + x*y)^2, whose derivative w.r.t. x is 2*(x + y + x*y)*(1+y).

Then, for example, df_dx(x = 2, y = 3) = 2*(2 + 3 + 6)*(1 + 3) = 88, which is the same result you get when running the differentiated function:

dz_x := 0;
z := 1;
dz_x := 1 + 3 := 4;
z := 1*2 + 1*3 + 2*3 = 11;
dz_dx := 2*11*4 := 88
z := 2*11 = 22; // this is actually useless

Mind you, there is no der(x,y) term, those are two independent variables of the function.

I'm also not expecting that the partial derivative function is further simplified or inlined or symbolically processed in any way. It should simply be compiled into executable code that returns the appropriate values.

Last edited 4 years ago by Francesco Casella (previous) (diff)

comment:26 by Karim Adbdelhak, 5 years ago

Yea you are totally right!

comment:27 by Francesco Casella, 4 years ago

Milestone: 1.16.01.17.0

1.16.0 feature freeze is imminent, new developments postponed to 1.17.0

in reply to:  21 comment:28 by Francesco Casella, 4 years ago

Replying to perost:

If we don't care about being able to evaluate such functions I guess we can just pass them through the frontend, in which case we only need to know their type

Yes! There will never be the need of evaluating such functions in the front end in practice.

(which is the same as the function being derived?).

Yes, except that the unit of the output is the unit of the original output divided by the unit of the variable you are differentiating with respect to

Last edited 4 years ago by Francesco Casella (previous) (diff)

comment:29 by Francesco Casella, 4 years ago

@Karim, I will need this feature for the project dealing with the CO2 mixture and Peng-Robinson equation, do you think you can do that?

comment:30 by Francesco Casella, 4 years ago

Milestone: 1.17.01.18.0

Rescheduled to 1.18.0

comment:31 by Francesco Casella, 3 years ago

Milestone: 1.18.0

Ticket retargeted after milestone closed

comment:32 by Francesco Casella, 3 years ago

Milestone: 1.19.0

1.18.0 blocker tickets moved to 1.19.0

comment:33 by Francesco Casella, 7 months ago

Milestone: 1.19.0Future
Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.