Использование условных операторов в Dymola

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

Вот код, который у меня есть на данный момент. Есть ли у вас идеи, в чем может быть проблема?

model Trial

  Real p(start=rand()/32767);
  Real E(start=1);

equation 

when (sample(1,3600)) then//sample(start+interval) ce qui donne "start + i*interval"
    p = rand()/32767;

    if E == 1 then
      if p < 0.2 then
        E = 2;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif E == 2 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif E == 3 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 4;
      end if;

    elseif E == 4 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 3;
      end if;
    end if;

end when;

  annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
        coordinateSystem(preserveAspectRatio=false)),
    experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;


56
2

Ответы:

Есть ряд проблем. Сначала исправленный код:

model Trial
  impure function rand
    output Integer i;
    external "C";
  end rand;
  Real p(start=rand()/32767);
  Integer E(start=1);

equation 

when (sample(1,3600)) then//sample(start+interval) ce qui donne "start + i*interval"
    p = rand()/32767;

    if pre(E) == 1 then
      if p < 0.2 then
        E = 2;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif pre(E) == 2 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif pre(E) == 3 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 4;
      end if;

    else
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 3;
      end if;
    end if;

end when;


  annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
        coordinateSystem(preserveAspectRatio=false)),
    experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;

Далее список изменений:

  • Должны быть объявлены функции, в частности функции, которые не возвращают Real.
  • E — целое число, а не действительное число, что также позволяет сравнивать.
  • Уравнения в Modelica работают иначе, чем алгоритмы на других языках. Используйте pre(E) для доступа к предыдущему значению E.
  • Операторы if должны заканчиваться предложением else, даже если они логически исчерпывают все возможности (если только условие не является вычислимым выражением параметра).
  • Функции, которые возвращают разные значения для одного и того же ввода, следует объявлять как impure.

Решено

Предлагаю вам посмотреть Modelica.Math.Random.Examples.GenerateRandomNumbers. На основе этого примера у меня получилось:

model Trial

  parameter Integer id=Modelica.Math.Random.Utilities.initializeImpureRandom(globalSeed) "A unique number used to sort equations correctly";
  parameter Integer globalSeed=30020 "Global seed to initialize random number generator";

  Real p(start=Modelica.Math.Random.Utilities.impureRandom(id=id));
  Integer E(start=1, fixed=true);

equation 

  when (sample(1, 3600)) then
    //sample(start+interval) ce qui donne "start + i*interval"
    p = Modelica.Math.Random.Utilities.impureRandom(id=id);

    if pre(E) == 1 then
      if p < 0.2 then
        E = 2;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif pre(E) == 2 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 3;
      else
        E = 4;
      end if;

    elseif pre(E) == 3 then
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 4;
      end if;

    else
      // if E == 4 
      if p < 0.2 then
        E = 1;
      elseif p < 0.6 then
        E = 2;
      else
        E = 3;
      end if;
    end if;

  end when;

  annotation (
    Icon(coordinateSystem(preserveAspectRatio=false)),
    Diagram(coordinateSystem(preserveAspectRatio=false)),
    experiment(StopTime=86400, __Dymola_Algorithm = "Dassl"));
end Trial;

Я еще поправил:

  • объявление E : Real to Integer + fixed=true,
  • условия, зависящие от значения E: pre(E) позволяет избежать алгебраического цикла,
  • последний оператор if должен быть else.