How to introduce scaling of parameters to MSL CombiTimeTable?

104 views Asked by At

I want to use MSL CombiTimeTable and be able to scale the parameters here from a scaling factor provided by another block or model. (The idea is to give flexibility for the user to express switching time points in sort of different units, eg. either as 60 seconds or as the liquid volume 120 mL that takes 120/2 seconds to pass by if the flow rate is 2 mL/s). The scaling is the same throughout a simulation. I hesitate whether to see scaling as a signal or a parameter but chose it to be a signal. Then I embed CombiTimeTable in a block with an interface of a scaling-signal and two parameter, see below.

model Test

    import Modelica.Blocks.Sources; 
    import Modelica.Blocks.Types; 
    import Modelica.Blocks.Interfaces.RealInput;
    import Modelica.Blocks.Interfaces.RealOutput;

    block ControlStep
        output RealOutput out;
        input RealInput scaling;        
        parameter Real start;
        parameter Real stop;
        Sources.CombiTimeTable loading(
            smoothness=Types.Smoothness.ConstantSegments,
            extrapolation=Types.Extrapolation.HoldLastPoint,
            table=[0, 0; start/scaling, 1; stop/scaling, 0]);
    equation
        out = loading.y[1]; 
    end ControlStep;

    model System
        ControlStep control_sample(start=0, stop=120);
        parameter Boolean scale_volume = true;
        Real F, Y, scaling;
    equation
        F = 2; 
        scaling = if scale_volume then F else 1;
        control_sample.scaling = scaling;
        Y = control_sample.out;
    end System;

 end Test;

Before I start a simulation I give values to parameters start and stop and also a parameter for if they should be given in terms of time or in terms of a scaled number. The code works for JModelica, but I am not very confident that the code have a sound structure. Here is some "initial" work to be done at start of simulation and I think of the concepts "initial algorithm" or "initial equation". The initial work is in my example spread out in two places as you see and consists of (expressed in a procedural way):

  1. Evaluate the value of the parameter"scale_volume"
  2. Get the value of F (here just equals 2 but generally defined based on several other parameters)
  3. Get the value of the variable scaling, i.e. F or 1
  4. Calculate the values in the table of CombiTimeTable

Would appreciate some comments, corrections, or suggestions of improvements even though the code do work in JModelica but actually not in OpenModelica.

1

There are 1 answers

7
marco On BEST ANSWER

If scaling is no parameter you have a variability problem. I am surprised that JMoedlica accepts that.

In the assignment

loading(
  ...
            table=[0, 0; start/scaling, 1; stop/scaling, 0]);

you compute the parameter table from scaling. Hence, scaling must be a constant or a parameter.

If we change scaling and all related variables to parameters or final parameters, the code runs in OpenModelica v1.18.1 and in Dymola 2022x.

model Test

    import Modelica.Blocks.Sources;
    import Modelica.Blocks.Types;
    import Modelica.Units.SI.Time;

    block ControlStep
        parameter Real scaling;
        parameter Time start;
        parameter Time stop;
        Sources.CombiTimeTable loading(
            smoothness=Types.Smoothness.ConstantSegments,
            extrapolation=Types.Extrapolation.HoldLastPoint,
            table=[0, 0; start/scaling, 1; stop/scaling, 0]);
    end ControlStep;

    model System
        ControlStep control_sample(start=0, stop=120, scaling=scaling);
        parameter Boolean scale_volume = true;
        final parameter Real scaling = if scale_volume then F else 1;
        parameter Real F = 2;
        Real Y;
    equation 
        Y = control_sample.loading.y[1];
      annotation (experiment(StopTime=200));
    end System;

end Test;

Regarding your statement:

The scaling is the same throughout a simulation. I hesitate whether to see scaling as a signal or a parameter but chose it to be a signal.

Definitely use a parameter for that. This allows the Modelica translator to optimize your equations accordingly and in general should result in a faster model (at least a little).

Alternative: use timescale parameter

The CombiTimeTable also has a parameter which performs scaling: timeScale

For your minimal example using timeScale=1/scaling will give the same result as your approach.

model Test

    import Modelica.Blocks.Sources;
    import Modelica.Blocks.Types;
    import Modelica.Units.SI.Time;

    block ControlStep
        parameter Real scaling;
        parameter Time start;
        parameter Time stop;
        Sources.CombiTimeTable loading(
            timeScale=1/scaling,
            smoothness=Types.Smoothness.ConstantSegments,
            extrapolation=Types.Extrapolation.HoldLastPoint,
            table=[0, 0; start, 1; stop, 0]);
    end ControlStep;

    model System
        ControlStep control_sample(start=0, stop=120, scaling=scaling);
        parameter Boolean scale_volume = true;
        final parameter Real scaling = if scale_volume then F else 1;
        parameter Real F = 2;
        Real Y;
    equation 
        Y = control_sample.loading.y[1];
      annotation (experiment(StopTime=200));
    end System;

end Test;