OpenModelica - J'essaie d'exécuter un exemple de livre mais d'avoir des problèmes intérieurs

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

  •  29-07-2022
  •  | 
  •  

Question

J'utilise OpenModelica et j'essaie d'exécuter un exemple de l'introduction à la modélisation physique avec Modelica. J'ai copié des exemples 9.1 - 9.4 dans un package. Le fichier ressemble maintenant à ceci:

    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;

Mais, si je vais à Omshell et que j'essaie de l'exécuter, j'obtiens ceci:

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

>> 

Donc, il y a clairement quelque chose lié à la portée que je n'obtiens pas correctement. Tout le code, à l'exception du package, est juste copié directement à partir du livre. Je crois que le package est nécessaire pour le mettre dans un seul fichier (même si j'ai essayé quelques autres façons de le faire sans succès). Toutes les suggestions sont appréciées.

Merci,

Était-ce utile?

La solution

Il s'agit d'un bug dans OpenModelica. Cela devrait bien fonctionner si c'est un composant intérieur ou une classe mais pas pour les fonctions.

J'ai ajouté un rapport de bogue à ce sujet et nous allons le corriger:https://trac.openmodelica.org/openmodelica/ticket/2467

Pour l'instant, vous pouvez utiliser un package intérieur / extérieur, ce qui devrait fonctionner correctement.

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;

Autres conseils

Ok, donc je pense que le problème ici est que vous essayez de "transmettre" une fonction dans l'arborescence d'instance en utilisant la portée dynamique (c'est-à-dire inner et outer). Je n'ai pas lu la spécification sur ce point particulier, mais je ne pense pas que cela fonctionnera. La raison en est que normalement inner et outer sont utilisés en conjonction avec des choses qui sont instanciées (variables, modèles, etc.).

La chose à comprendre est donc que les deux conceptuels constant variables et function Les définitions ne sont pas instanciées. Être capable de traiter un function Comme un exemple (une valeur de première classe) a plusieurs conséquences utiles, mais il introduit également certaines complications sémantiques. Il y a eu du travail dans des versions récentes du langage pour essayer de traiter les fonctions comme des citoyens de première classe. Le principal cas d'utilisation était de passer les fonctions comme des arguments à d'autres fonctions. Mais je pense que ces nouvelles sémantiques ne s'arrêtent pas à faire des fonctions vraiment des valeurs de première classe (comme votre exemple le montrerait). Cependant, cela peut être en cause avec OpenModelica. Je ne peux pas dire définitivement.

Une façon dont vous pourriez y faire face serait d'utiliser des remplaçables et de redéclater. Donc dans votre Particle modèle, définir gravity comme ça:

public
  replaceable function gravity = GravityField;

Ensuite, instanciez-le comme suit:

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;

Remarque, je n'ai pas testé cette solution. Par exemple, votre Particle le modèle peut nécessiter le partial qualificatif (puisque vous devrez remplacer gravity à un nonpartial la mise en oeuvre).

J'espère que cela aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top