modelicasystemmodeler

Modelica - Increment doesn't follow conditions


I am creating a Max Per Interval block in Wolfram System Modeler.

To make it easy for me to explain, I just set the Max value to 10.

block HighWaterMarkPerInterval
  extends Modelica.Blocks.Interfaces.SISO;
protected
  Integer index;
  Real currentMax;
  Real endTimes[1, 45] = [30812532.2, 32037805, 33265581.8, 34493233.8, 35720861.5, 36948483, 38176307.7, 39426940.6, 40654485.4, 41882212.1, 43109672.7, 44337076, 45564265.7, 46793039.6, 48045130.9, 50749960.3, 52040090.6, 53558507.7, 54814537.3, 56331978.2, 57587753.3, 59105952.9, 60362517.8, 61879307.8, 63136031.5, 64363411.4, 65590464.3, 67738027.40000001, 84725789.8, 87831338.09999999, 89030965.40000001, 90258821.8, 91486663.5, 92714210.3, 93941727.7, 95166770.3, 97283519, 99434222.90000001, 100658067.1, 102807019, 104030032.7, 106179193, 107402090, 109550214.2, 110771545.3];
algorithm
  if endTimes[1, index] < time then
    index := pre(index) + 1;
    currentMax := 0;
  else
    currentMax := 10; // Constant to until I get logic working
  end if;
initial algorithm
  index := 0;
equation
  y = currentMax;
end HighWaterMarkPerInterval;

When ran, index increments to infinity right off the bat. I figure there is something wrong with my logic, but I can't figure it.

The code is supposed to check to see if we are still in the interval time, and when we cross over into the next interval time it sets the "currentMax" value to zero. Which will reset the Max value I've implemented in another block.

Any help would be appreciated. Thanks.

EDIT: Code section form example.

model HighWaterMarkPerInterval
  annotation(Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})));
  extends Modelica.Blocks.Interfaces.SISO;
  Modelica.Blocks.Math.Max maxblock(u1 = currentMax, u2 = u);
  Real flybyEnds[1, 45] = [30813151,32038322,33266015, truncated for space saving...];
  Integer index;
  Real currentMax;
initial equation
  index = 1;
  currentMax = 0;  
algorithm
  // When we are in the interval continually grab max block output and output currentMax
  when {time>=flybyEnds[1, index-1], time <=flybyEnds[1,index]} then 
    currentMax := pre(maxblock.y);
    y := currentMax;
  end when;
  // When we move to the next interval reset current max and move to the next interval
  when time > flybyEnds[1, index] then
    currentMax := 0;
    index := pre(index) + 1;
  end when;
end HighWaterMarkPerInterval;

Solution

  • You need to use when, not if. You can find a discussion about both and the differences between them in Modelica by Example.

    This issue has also been discussed on SO both here and here.

    Here is an example (completely untested, but it shows the basic idea):

    model HighWaterMarkPerInterval
      extends Modelica.Blocks.Interfaces.SISO;
      parameter Modelica.SIunits.Time sample_rate=3600;
      Real flybyEnds[45] = {30813151,32038322,33266015,...};
      Integer index;
      Real currentMax;
    initial algorithm
      // Specify the first time we are interested in...
      index := 1;
    algorithm 
      // At the start of the simulation, the initial max for the current
      // interval [0,30813151] is whatever u is.  The initial output value
      // is also the initial value for u
      when initial() then
        currentMax := u
        y := u;
      end when;
    
      // Check at some sample rate (faster than the flyby interval!)
      // if u > currentMax...
      when sample(sample_rate, sample_rate) then
        // New currentMax is the larger of either currentMax or u
        // when the sample took place
        currentMax := max(pre(currentMax), pre(u));
      end when;
    
      // At the end of the "flyby", record the maximum found since
      // the last flyby and specify the next flyby index.
      when time>=flybyEnd[index] then
        // New output is the value of currentMax from this interval
        y := pre(currentMax);
        // Now reset currentMax
        currentMax := pre(u);
        // Increment index up to the length of flybyEnd
        index := min(pre(index)+1, size(flybyEnd,1));
      end when;
    end HighWaterMarkPerInterval;