在 Modelica 中使用点符号和数组中的字符串加载记录

Load a record using dot notation and strings from an array in Modelica

有没有办法在 Modelica 中加载记录,并使用数组中的字符串操作记录目录的一部分?

我在下面包含了最小的工作示例,总而言之,我有两个不同的记录,其参数值分别为 Cylinder 和 Board,并且我有一个包含它们名称的数组。我想访问函数中的一组参数值,具体取决于用户输入 "ShapeNumber"。因此,当用户输入 1 时,从 Cylinder 记录中加载参数,当用户输入 2 时,从 Board 记录中加载参数。理想情况下,我想将字符串 "Cylinder" 或 "Board" 添加到点符号中以加载记录,如下面的代码所示。

package Test_things

  record General_parameters
    parameter Real Length "Length in m";
  end General_parameters;

  record Cylinder_parameters
    extends General_parameters;
    parameter Real Diameter "Diameter in m";
  end Cylinder_parameters;

  record Board_parameters
    extends General_parameters;
    parameter Real Width "Width in m";
    parameter Real Depth "Depth in m";
  end Board_parameters;

  record Parameter_values
    constant Test_things.Cylinder_parameters Cylinder(Length=10, Diameter=0.5);
    constant Test_things.Board_parameters Board(
      Length=20,
      Width=1,
      Depth=0.01);
    constant String[2] ShapesArray = {"Cylinder","Board"};
  end Parameter_values;

  function Length_tester
    input Integer   ShapeNumber; //Which shape from within the shape array is tested

    output Boolean LongEnough;

    Test_things.Parameter_values Values; //Gives Values.Cylinder, Values.Board, Values.ShapesArray

  protected
    String ShapeName;
    Real Length;
  algorithm
    //Load correct shape
    ShapeName := Values.ShapesArray[ShapeNumber];

    // This is what I would like: Length := Values.{ShapeName}.Length;
    // which results in one of the two lines of code below.
    // Length := Values.Cylinder.Length;
    // Length := Values.Board.Length;

    // This works for now, but has to be adjusted whenever a new shape is used
    if ShapeName == "Cylinder" then
      Length := Values.Cylinder.Length;
    elseif ShapeName == "Board" then
      Length := Values.Board.Length;
    end if;

    if Length > 15 then
      LongEnough := true;
    else
      LongEnough := false;
    end if;

  end Length_tester;

  model Main
    Boolean LongEnoughCylinder;
    Boolean LongEnoughBoard;
  equation
    // Test Cylinder
    LongEnoughCylinder = Length_tester(1);
    // Test Board
    LongEnoughBoard = Length_tester(2);
  end Main;
end Test_things;

我找到了 if 语句的解决方法,但是当我添加一条新记录时,我必须在我拥有的每个函数中更新该 if 语句,而不是只用记录的名称更新数组.

感谢您的帮助!

您尝试执行的操作目前无法实现,因为 Modelica 不支持 class 路径的动态创建。所有 class 路径都必须进行硬编码。

因此,您的 if/else 解决方法是一个合法的解决方案。为了保持较低的可维护性,您可以创建一个包含 if/else 逻辑的函数 getLength,您的所有其他函数都将使用这个逻辑。

您可以在下面找到我要使用的解决方案。一切都尽可能通用,因此您可以使用任意数量的任何类型的形状。为此,可以使用具有所有可能形状参数的通用形状类型 Shape。然后是特殊形状BoardCylinder,结合关键字final将不需要的参数设置为0,用户不能修改。这允许创建包含基本形状类型和特殊形状的形状数组。 testLength 函数将非常简单,接受一个形状数组。此解决方案的缺点是(对于作为开发人员的您),具有新参数的新形状需要更新基本形状类型和专用形状。

package Test_things

  record Shape "Generic shape with all possible parameters"
    import SI = Modelica.SIunits;

    // Common parameters
    parameter ShapeTypes shapeType "Kind of shape";
    parameter SI.Length length;

    // Board parameters
    parameter SI.Length width;
    parameter SI.Length depth;

    // Cylinder parameters
    parameter SI.Diameter diameter;
  end Shape;

  type ShapeTypes = enumeration(Cylinder, Board);

  record Cylinder "Cylinder shape with unneeded parameters set on final 0"
    extends Shape(final shapeType=ShapeTypes.Cylinder, final width=0, final depth=0);
  end Cylinder;

  record Board "Board shape with unneeded parameters set on final 0"
    extends Shape(final shapeType=ShapeTypes.Board, final diameter=0);
  end Board;

  function testLength "Check if length of a specific shape in an array of shapes is bigger than 15"
    input Integer shapeNumber "Shape of interest";
    input  Shape shapes[:] "Array of shapes";
    output Boolean longEnough;
  algorithm 
    longEnough := shapes[shapeNumber].length > 15;
  end testLength;

  model Main
    constant Shape shapes[:] = {
      Board(length=20, width=1, depth=0.01),
      Cylinder(length=1, diameter=2)}; 
   // note: this works in OpenModelica only with the prefix constant, parameter does not compile
   // in Dymola it works with both

    Boolean longEnoughCylinder;
    Boolean longEnoughBoard;
  equation 
    // Test Cylinder
    longEnoughCylinder = testLength(1, shapes);
    // Test Board
    longEnoughBoard = testLength(2, shapes);
  end Main;

end Test_things6;

关于样式的一些注意事项:

  • 除了function之外的所有classes都要大写
  • 所有的实例、参数等都要小写
  • 不要将单位写入注释,而是使用 SI 单位