3

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;

1 Answers1

4

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;
Community
  • 1
  • 1
Michael Tiller
  • 9,291
  • 3
  • 26
  • 41
  • I've tried implementing `when` in the past, but I cannot figure out how to reset it using the when functionality. I would need the functionality of a `when-else` statement to do what I'm trying to do if It understand correctly. – user3791725 Feb 07 '15 at 00:19
  • Can you explain what you mean by "reset it"? – Michael Tiller Feb 07 '15 at 13:39
  • Yes, sorry. `currentMax` is supposed to reset at every `endTime`. I am trying to calculate a `currentMax` value for every interval rather than a High Water Mark over the entire simulation. The `endTimes` correspond to the interval end times. – user3791725 Feb 07 '15 at 23:45
  • 2
    You should look at [this example](http://book.xogeny.com/behavior/discrete/measuring/#pulse-counting). I think it will explain everything you want to do. It counts the number of rotations of a shaft during a given time interval to estimate speed. Seems pretty similar to what you want to do. – Michael Tiller Feb 09 '15 at 00:31
  • I'm sorry. I do not understand some of the Modelica logic in that example. I uploaded a rough draft of what I got from it. Thank you so much for your help. – user3791725 Feb 10 '15 at 18:35
  • Your problem is with your assumption that you can continuously grab the maximum value. You cannot do that in Modelica. What you'll need to do is simply check at some regular interval (e.g., using sample) to see if the current value is larger than your most recent max (in that interval) and then record it. Obviously, your sample rate needs to be faster than your "flyby" interval. Do you see what I'm getting at? – Michael Tiller Feb 10 '15 at 21:43
  • I see what you're getting at. I guess I just don't understand it enough. I've tried implementing `sample(0, flybyEnds[1,index]` so it can calculate per every interval. Does it not work like that? I'll elaborate a little. Every interval is not the same amount of time, so can `sample` be dynamically updated? – user3791725 Feb 11 '15 at 21:56
  • 3
    You are not understanding the use of `sample` here. It is not meant to capture the flyby interval. It is meant to sample **within** the flyby interval. You are trying to record the extremum, but there is no way to detect that explicitly. So `sample` is being used to check to see if the current value is larger than any previously *sampled* value in the current fly by interval. That check is done with `sample` because it cannot be done "continuously" in Modelica. So the sampling period must be much shorter than the flyby interval. – Michael Tiller Feb 20 '15 at 21:56
  • Thank you. That makes a lot of sense. – Shawnic Hedgehog Feb 23 '15 at 17:45
  • I appreciate the help! I think I understand the correct usage of `sample` now. The code fragment definitely put things into perspective and I have working code. – user3791725 Feb 23 '15 at 17:48