在 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
。然后是特殊形状Board
和Cylinder
,结合关键字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 单位
有没有办法在 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
。然后是特殊形状Board
和Cylinder
,结合关键字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 单位