Search code examples
modelicaopenmodelica

How do I define relations between parameters and retain flexible use?


How do I define relations between multiple parameters in such a way that I can choose which parameters from the set to define, some equations defining the rest?

For example, I have a model with 3 parameters for the radius, height and volume of a cylinder, and they are related via the equation for volume V=r^2*h. I want to be able to choose on model instantiation if I define r and h (and V is computed), r, V (and h is computed), or h, V (and r is computed).

In the following minimal example, I have tried the approaches 1-3, but none does what I need. I got the feeling that this has to be a common/solved problem, and I am just missing a certain modelling technique. Can you help?

model test_params "Model for a cylinder"
  model Cylinder
  parameter Real r;
  parameter Real h;
  parameter Real V;
  //Approach 3: binding equation. Works, but what to do if I have V, h and want to know r??
  //parameter Real V=r^2*Modelica.Constants.pi*h;

  Real t;
  initial equation
    //Approach 2, apparently chooses V as 0 before getting to the initialisation equation
    //V=r^2*Modelica.Constants.pi*h; 
    //Parameter cylinder.V has no value, and is fixed during initialization (fixed=true), using available start value (start=0.0) as default value.
    // The initial conditions are over specified. The following 1 initial equations are redundant, so they are removed from the initialization sytem:
    //    cylinder.V = 3.141592653589793 * cylinder.r ^ 2.0 * cylinder.h.
  equation
    t = V;
    // Approach 1
    //V=r^2*Modelica.Constants.pi*h; //Leads to: Too many equations, over-determined system.
  end Cylinder;

  test_params.Cylinder cylinder(h = 1, r = 2)  annotation(
    Placement(visible = true, transformation(origin = {-44, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
end test_params;

This is on OpenModelica 1.14, if that should be relevant.


Solution

  • This can be done using your mentioned approach 2 if you set the dependent parameter as fixed=false parameter.

    model TestParams "Model for a cylinder"
      encapsulated model Cylinder
        import Modelica.Constants.pi;
        parameter Real r;
        parameter Real h;
        parameter Real V;
      initial equation 
        V = r^2*pi*h "Cylinder volume";
      end Cylinder;
    
      TestParams.Cylinder cylinder_1(h=1, r=2, V(fixed=false)) "Compute cylinder V(h, r)"
        annotation (Placement(transformation(origin={-70,50}, extent={{-10,-10},{10,10}})));
      TestParams.Cylinder cylinder_2(h(start=0, fixed=false), r=2, V=13) "Compute cylinder h(r, V)"
        annotation (Placement(transformation(origin={-30,50}, extent={{-10,-10},{10,10}})));
      TestParams.Cylinder cylinder_3(h=1, r(start=0, fixed=false), V=13) "Compute cylinder r(h, V)"
        annotation (Placement(transformation(origin={10,50}, extent={{-10,-10},{10,10}})));
    end TestParams;