OpenModelica: estoy tratando de ejecutar un ejemplo de libro pero tengo problemas internos

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

  •  29-07-2022
  •  | 
  •  

Pregunta

Estoy ejecutando OpenModelica e intento ejecutar un ejemplo desde la introducción al modelado físico con Modelica. He copiado los ejemplos 9.1 - 9.4 en un paquete. El archivo ahora se ve así:

    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;

Pero, si voy a Omshell e intento ejecutarlo, entiendo esto:

    >> 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;

>> 

Entonces, claramente hay algo relacionado con el alcance que no me estoy poniendo correcto. Todo el código, excepto el paquete, se acaba de copiar directamente del libro. Creo que el paquete es necesario para llevarlo a un solo archivo (aunque intenté algunas otras formas de hacerlo sin éxito). Se agradecen cualquier sugerencia.

Gracias,

¿Fue útil?

Solución

Este es un error en OpenModelica. Debería funcionar bien si es un componente o clase interno, pero no para funciones.

Agregué un informe de error al respecto y lo solucionaremos:https://trac.openmodelica.org/openmodelica/ticket/2467

Por ahora puede usar un paquete interno/exterior, eso debería funcionar bien.

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;

Otros consejos

Ok, creo que el problema aquí es que estás tratando de "pasar" una función en el árbol de instancias usando el alcance dinámico (es decir inner y outer). No he leído la especificación sobre este punto en particular, pero no creo que esto funcione. La razón es que normalmente inner y outer se utilizan junto con cosas que están instanciadas (variables, modelos, etc.).

Entonces, lo que debe entender es que conceptualmente ambos constant variables y function Las definiciones no están instanciadas. Ser capaz de tratar un function Como instancia (un valor de primera clase) tiene varias consecuencias útiles, pero también introduce algunas complicaciones semánticas. Se ha realizado trabajo en versiones recientes del lenguaje para tratar de tratar las funciones como ciudadanos de primera clase. El caso de uso principal era aprobar funciones como argumentos a otras funciones. Pero creo que estas nuevas semánticas se detienen en hacer funciones realmente valores de primera clase (como lo demostraría su ejemplo). Sin embargo, esto puede estar en problemas con OpenModelica. No puedo decir definitivamente.

Una forma de lidiar con esto sería usar reemplazable y redeclare. Entonces en tu Particle modelo, definir gravity como esto:

public
  replaceable function gravity = GravityField;

Luego, instanciéelo de la siguiente manera:

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;

Tenga en cuenta que no he probado esta solución. Por ejemplo, tu Particle el modelo puede requerir el partial calificador (ya que tendrías que anular gravity a un nopartial implementación).

Espero que eso ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top