Modelica - Приращение не следует условиям

Я создаю блок Max Per Interval в Wolfram System Modeler.

Чтобы облегчить мне объяснение, я просто установил максимальное значение на 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;

При запуске индекс сразу же увеличивается до бесконечности. Я полагаю, что с моей логикой что-то не так, но я не могу этого понять.

Код должен проверять, находимся ли мы все еще в интервале времени, и когда мы переходим к следующему интервалу времени, он устанавливает значение «currentMax» равным нулю. Это сбросит максимальное значение, которое я реализовал в другом блоке.

Любая помощь будет оценена по достоинству. Спасибо.

РЕДАКТИРОВАТЬ: пример формы раздела кода.

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;

person user3791725    schedule 06.02.2015    source источник


Ответы (1)


Вам нужно использовать when, а не if. Вы можете найти обсуждение обоих и различий между ними в Modelica by Example.

Эта проблема также обсуждалась в SO как здесь, так и здесь.

Вот пример (полностью непроверенный, но он показывает основную идею):

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;
person Michael Tiller    schedule 06.02.2015
comment
Раньше я пробовал реализовать when, но не могу понять, как его сбросить с помощью функции when. Мне понадобится функциональность оператора when-else, чтобы делать то, что я пытаюсь сделать, если он правильно понимает. - person user3791725; 07.02.2015
comment
Можете ли вы объяснить, что вы имеете в виду под его сбросом? - person Michael Tiller; 07.02.2015
comment
Да, прости. currentMax должен сбрасываться каждые endTime. Я пытаюсь вычислить значение currentMax для каждого интервала, а не максимальную отметку за всю симуляцию. endTimes соответствуют времени окончания интервала. - person user3791725; 08.02.2015
comment
Вам следует взглянуть на этот пример. Я думаю, он объяснит вам все, что вы хотите сделать. Он подсчитывает количество оборотов вала в течение заданного интервала времени для оценки скорости. Похоже на то, что вы хотите сделать. - person Michael Tiller; 09.02.2015
comment
Мне жаль. Я не понимаю часть логики Modelica в этом примере. Я загрузил черновик того, что у меня получилось. Спасибо большое за вашу помощь. - person user3791725; 10.02.2015
comment
Ваша проблема заключается в предположении, что вы можете постоянно получать максимальное значение. Вы не можете этого сделать в Modelica. Что вам нужно сделать, так это просто проверять через некоторый регулярный интервал (например, используя образец), чтобы увидеть, не превышает ли текущее значение вашего последнего максимума (в этом интервале), а затем записать его. Очевидно, что ваша частота дискретизации должна быть выше, чем интервал пролета. Вы понимаете, к чему я клоню? - person Michael Tiller; 11.02.2015
comment
Я понимаю, к чему вы клоните. Думаю, я просто этого недостаточно понимаю. Я пробовал реализовать sample(0, flybyEnds[1,index], чтобы он мог рассчитывать для каждого интервала. Неужели так не работает? Я немного уточню. Каждый интервал - это не одно и то же время, поэтому можно ли sample обновлять динамически? - person user3791725; 12.02.2015
comment
Вы не понимаете, как здесь используется sample. Он не предназначен для фиксации интервала пролета. Он предназначен для выборки в пределах интервала пролета. Вы пытаетесь записать экстремум, но нет возможности его явно обнаружить. Таким образом, sample используется для проверки, больше ли текущее значение, чем любое ранее выбранное значение выборки в текущем интервале fly by. Эта проверка выполняется с помощью sample, потому что в Modelica она не может выполняться непрерывно. Таким образом, период выборки должен быть намного короче, чем интервал пролета. - person Michael Tiller; 21.02.2015
comment
Спасибо. В этом есть большой смысл. - person Shawnic Hedgehog; 23.02.2015
comment
Я ценю помощь! Думаю, теперь я понимаю, как правильно использовать sample. Фрагмент кода определенно дает перспективу, и у меня есть рабочий код. - person user3791725; 23.02.2015