OpenModelica - Ich versuche, ein Buchbeispiel auszuführen, habe aber Probleme mit innerer Entfernung

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

  •  29-07-2022
  •  | 
  •  

Frage

Ich führe OpenModelica durch und versuche, ein Beispiel von der Einführung in die physische Modellierung mit Modelica auszuführen. Ich habe Beispiele 9.1 - 9.4 in ein Paket kopiert. Die Datei sieht jetzt so aus:

    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;

Aber wenn ich nach Omshell gehe und versuche, es auszuführen, bekomme ich Folgendes:

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

>> 

Daher gibt es eindeutig etwas mit dem Umfang, den ich nicht korrekt habe. Der gesamte Code mit Ausnahme des Pakets wird gerade direkt aus dem Buch kopiert. Ich glaube, dass das Paket notwendig ist, um es in eine einzige Datei zu bringen (obwohl ich einige andere Möglichkeiten versucht habe, dies ohne Erfolg zu tun). Vorschläge werden geschätzt.

Vielen Dank,

War es hilfreich?

Lösung

Dies ist ein Fehler in OpenModelica. Es sollte gut funktionieren, wenn es sich um eine innere Komponente oder Klasse handelt, jedoch nicht für Funktionen.

Ich habe einen Fehlerbericht darüber hinzugefügt und wir werden ihn beheben:https://trac.openmodelica.org/openmodelica/ticket/2467

Im Moment können Sie ein inneres/äußeres Paket verwenden, das gut funktionieren sollte.

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;

Andere Tipps

Ok, ich denke, das Problem hier ist, dass Sie versuchen, mit dynamischem Scoping eine Funktion auf dem Instanzbaum zu "übergeben" (dh inner und outer). Ich habe die Spezifikation zu diesem bestimmten Punkt nicht gelesen, aber ich glaube nicht, dass dies funktionieren wird. Der Grund ist das normalerweise inner und outer werden in Verbindung mit Dingen verwendet, die instanziiert sind (Variablen, Modelle usw.).

Die Sache zu verstehen ist so konzeptionell beide constant Variablen und function Definitionen werden nicht instanziiert. In der Lage sein, a zu behandeln function Als Instanz (ein erstklassiger Wert) hat mehrere nützliche Konsequenzen, werden jedoch auch einige semantische Komplikationen einführt. In jüngsten Versionen der Sprache wurde Arbeit geleistet, um Funktionen als erstklassige Bürger zu behandeln. Der Hauptgebrauchsfall bestand darin, Funktionen als Argumente an andere Funktionen weiterzugeben. Aber ich denke, diese neuen Semantik machen nicht mehr als erstklassige Werte (wie Ihr Beispiel demonstrieren würde). Dies kann jedoch mit OpenModelica in Frage stehen. Ich kann nicht definitiv sagen.

Eine Möglichkeit, mit der Sie umgehen könnten, wäre die Verwendung von austauschbarem und neuem Einbau. Also in deinem Particle Modell, definieren gravity so was:

public
  replaceable function gravity = GravityField;

Dann instanziieren Sie es wie folgt:

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;

Beachten Sie, ich habe diese Lösung nicht getestet. Zum Beispiel Ihre Particle Modell könnte das erfordern, das partial Qualifikationsspiel (da Sie außerordentlich überschreiben müssten gravity zu einem Nichtspartial Implementierung).

Ich hoffe das hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top