OpenModelica - я пытаюсь запустить пример книги, но у нее проблемы с внутренними странами

StackOverflow https://stackoverflow.com/questions/19841314

  •  29-07-2022
  •  | 
  •  

Вопрос

Я запускаю OpenModelica и пытаюсь запустить пример от введения в физическое моделирование с Modelica. Я скопировал примеры 9.1 - 9.4 в упаковку. Файл теперь выглядит так:

    package gravityPackage
  //Test of gravity taken from Intro to Physical modeling with Modelica
  //
  //
  //
  //
  //
  model ParticleField
    inner function gravity = TwoBodyField;
    Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0});
    Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0});
    Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0});
  end ParticleField;
  function TwoBodyField
    extends GravityField;
  protected
    Modelica.SIunits.Position b1[3],b2[3];
    Modelica.SIunits.Velocity n1[3],n2[3];
  algorithm
    b1:={0,0,0};
    b2:={0,1,0};
    n1:=-(x - b1) / sqrt((x - b1) * (x - b1));
    n2:=-(x - b2) / sqrt((x - b2) * (x - b2));
    g:=n1 / ((x - b1) * (x - b1)) + n2 / ((x - b2) * (x - b2));
  end TwoBodyField;
  partial function GravityField
    input Modelica.SIunits.Position x[3];
    output Modelica.SIunits.Acceleration g[3];
  end GravityField;
  model Particle
    parameter Modelica.SIunits.Position x_init[3];
    parameter Modelica.SIunits.Velocity v_init[3];
  protected
    outer function gravity = GravityField;
    //outer function gravity=ParticleField;
    //outer function gravity=TwoBodyField;
    Modelica.SIunits.Position x[3](start = x_init);
    Modelica.SIunits.Velocity v[3](start = v_init);
    Modelica.SIunits.Acceleration a[3];
  equation
    v = der(x);
    a = der(v);
    a = gravity(x);
  end Particle;
end gravityPackage;

Но, если я пойду в OMSHELL и попробую запустить его, я понимаю:

    >> loadFile("gravityPackage.mo")
true


>> simulate(gravityPackage.ParticleField) 
record SimulationResult
    resultFile = "",
    simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 0.000001, method = 'dassl', fileNamePrefix = 'gravityPackage.ParticleField', options = '', outputFormat = 'mat', variableFilter = '.*', measureTime = false, cflags = '', simflags = ''",
    messages = "Simulation failed for model: gravityPackage.ParticleField
[gravityPackage.mo:34:11-34:42:writable] Warning: No corresponding 'inner' declaration found for class gravity declared as 'outer '.
 Continuing flattening by only considering the 'outer' class declaration.
[gravityPackage.mo:43:5-43:19:writable] Error: Failed to instantiate equation 
a = gravity(x);.
Error: Error occurred while flattening model gravityPackage.ParticleField
",
    timeFrontend = 0.0,
    timeBackend = 0.0,
    timeSimCode = 0.0,
    timeTemplates = 0.0,
    timeCompile = 0.0,
    timeSimulation = 0.0,
    timeTotal = 0.0
end SimulationResult;

>> 

Итак, очевидно, что есть что -то связанное с областью объема, что я не получаю правильного. Весь код, за исключением пакета, просто скопирован непосредственно из книги. Я полагаю, что пакет необходим, чтобы довести его в один файл (хотя я попробовал несколько других способов сделать это без успеха). Любые предложения оценены.

Спасибо,

Это было полезно?

Решение

Это ошибка в OpenModelica. Он должен работать нормально, если является внутренним компонентом или классом, но не для функций.

Я добавил об этом сообщение об ошибке, и мы это исправим:https://trac.openmodelica.org/openmodelica/ticket/2467

На данный момент вы можете использовать внутренний/внешний пакет, который должен работать нормально.

package gravityPackage

package Functions
  function TwoBodyField
    extends GravityField;
  protected
    Modelica.SIunits.Position b1[3],b2[3];
    Modelica.SIunits.Velocity n1[3],n2[3];
  algorithm
    b1:={0,0,0};
    b2:={0,1,0};
    n1:=-(x - b1) / sqrt((x - b1) * (x - b1));
    n2:=-(x - b2) / sqrt((x - b2) * (x - b2));
    g:=n1 / ((x - b1) * (x - b1)) + n2 / ((x - b2) * (x - b2));
  end TwoBodyField;

  partial function GravityField
    input Modelica.SIunits.Position x[3];
    output Modelica.SIunits.Acceleration g[3];
  end GravityField;

end Functions;

model ParticleField
    inner package funcs = Functions;
    Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0});
    Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0});
    Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0});
  end ParticleField;

  model Particle
    parameter Modelica.SIunits.Position x_init[3];
    parameter Modelica.SIunits.Velocity v_init[3];
  protected
    outer package funcs = Functions;
    function gravity = funcs.TwoBodyField;
    //outer function gravity=ParticleField;
    //outer function gravity=TwoBodyField;
    Modelica.SIunits.Position x[3](start = x_init);
    Modelica.SIunits.Velocity v[3](start = v_init);
    Modelica.SIunits.Acceleration a[3];
  equation
    v = der(x);
    a = der(v);
    a = gravity(x);
  end Particle;

end gravityPackage;

Другие советы

Итак, я думаю, что проблема здесь в том, что вы пытаетесь «передать» функцию вверх по дереву экземпляров, используя динамическую область (т.е. inner а также outer) Я не читал спецификацию по этому конкретному моменту, но я не думаю, что это сработает. Причина в том, что обычно inner а также outer используются в сочетании с созданиями вещей (переменные, модели и т. Д.).

Итак, что нужно понять, это концептуально оба constant переменные и function Определения не создаются. Возможность лечить function В качестве экземпляра (первоклассное значение) имеет несколько полезных последствий, но он также вводит некоторые семантические осложнения. Была проделана работа в последних версиях языка, чтобы попытаться рассматривать функции как граждан первого класса. Основным вариантом использования было передаче функций в качестве аргументов для других функций. Но я думаю, что эта новая семантика останавливается на том, чтобы сделать функции действительно первого класса значений (как будет продемонстрировать ваш пример). Тем не менее, это может решать OpenModelica. Я не могу сказать окончательно.

Один из способов справиться с этим - использовать замену и ремонт. Так в твоем Particle модель, определить gravity как это:

public
  replaceable function gravity = GravityField;

Затем создайте его следующим образом:

model ParticleField
  Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0}, redeclare function gravity = TwoBodyField);
  Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0}, redeclare function gravity = TwoBodyField);
  Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0}, redeclare function gravity = TwoBodyField);
end ParticleField;

Обратите внимание, я не проверил это решение. Например, ваш Particle Модель может потребовать partial квалификатор (так как вам придется переопределить gravity к неpartial реализация).

Надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top