OpenModelica - Sto cercando di eseguire un esempio di libro ma avendo problemi di interiore.

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

  •  29-07-2022
  •  | 
  •  

Domanda

Sto eseguendo OpenModelica e sto cercando di eseguire un esempio dall'introduzione alla modellazione fisica con Modelica. Ho copiato esempi 9.1 - 9.4 in un pacchetto. Il file ora sembra così:

    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;

Ma, se vado a Omshell e provo a eseguirlo, ottengo questo:

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

>> 

Quindi, chiaramente c'è qualcosa di correlato all'ambito che non sto ottenendo corretto. Tutto il codice, ad eccezione del pacchetto, è appena copiato direttamente dal libro. Credo che il pacchetto sia necessario per inserirlo in un singolo file (anche se ho provato alcuni altri modi per farlo senza successo). Eventuali suggerimenti sono apprezzati.

Grazie,

È stato utile?

Soluzione

Questo è un bug in OpenModelica. Dovrebbe funzionare bene se è un componente interiore o una classe ma non per le funzioni.

Ho aggiunto un report di bug al riguardo e lo risolveremo:https://trac.openmodelica.org/openmodelica/ticket/2467

Per ora puoi usare un pacchetto interno/esterno, che dovrebbe funzionare bene.

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;

Altri suggerimenti

Ok, quindi penso che il problema qui sia che stai cercando di "passare" una funzione sull'albero dell'istanza usando lo scoping dinamico (cioè inner e outer). Non ho letto le specifiche su questo particolare punto, ma non credo che funzionerà. Il motivo è che normalmente inner e outer sono usati in combinazione con cose che sono istanziate (variabili, modelli, ecc.).

Quindi la cosa da capire è che concettualmente entrambi constant variabili e function Le definizioni non sono istanziate. Essere in grado di trattare un function Come istanza (un valore di prima classe) ha diverse conseguenze utili, ma introduce anche alcune complicazioni semantiche. C'è stato un lavoro svolto nelle recenti versioni della lingua per cercare di trattare le funzioni come cittadini di prima classe. Il caso d'uso principale era passare le funzioni come argomenti ad altre funzioni. Ma penso che queste nuove semantiche si fermino a fare funzioni veramente valori di prima classe (come dimostrerebbe il tuo esempio). Tuttavia, questo potrebbe essere in discussione con OpenModelica. Non posso dire definitivamente.

Un modo in cui potresti gestire questo sarebbe usare sostituibili e redeclare. Quindi nel tuo Particle Modello, definire gravity come questo:

public
  replaceable function gravity = GravityField;

Quindi, istanzialo come segue:

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;

Nota, non ho testato questa soluzione. Ad esempio, il tuo Particle Il modello potrebbe richiedere il partial qualificatore (dal momento che dovresti sovrascrivere gravity a un nonpartial implementazione).

Spero che aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top