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. لا أستطيع أن أقول بشكل قاطع.

إحدى الطرق التي يمكنك من خلالها التعامل مع هذا هي استخدام قابلة للاستبدال و Redeclare. لذلك في الخاص بك 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