You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Modelica技术问询:如何传递基于record接口的记录至函数

在Modelica函数中接收基于partial record的派生记录实例

问题重现

你定义了如下的CrossSections包,其中CrossSection是partial record,派生出Circle和Rectangle两个具体记录:

package CrossSections  
  partial record CrossSection
    constant String name="Generic";
    parameter SI.Area area "cross sectional area";
  end CrossSection;

  record Circle
    extends CrossSection(name="Circle",    
      final area = (d/2)^2*Modelica.Constants.pi);
    parameter Modelica.Units.SI.Diameter d "Diameter of the cross section";  
  end Circle;
  
  record Rectangle
    parameter SI.Length a,b;
    extends CrossSection(name="Rectangle",
      final area = a*b);
  end Rectangle;
end CrossSections

尝试编写函数foo接收CrossSection类型输入并根据实例类型分支计算时,出现报错Component 'cs' has partial type 'CrossSection':

function foo
  input CrossSections.CrossSection cs;
  
  output Real o1;
  algorithm
    if Modelica.Utilities.Strings.isEqual("Circle", cs.name) then
      o1 := cs.area*3;
    elseif Modelica.Utilities.Strings.isEqual("Rectangle", cs.name) then
      o1 := cs.area*2;
    else
      o1 := cs.area*5;
    end if;
    return;
end foo;

解决方案

Modelica中不能直接将partial record作为函数输入类型,需要通过replaceable input配合constrainedby关键字实现多态记录的传递,以下是两种可行实现方式:

方式1:基于name字段分支(兼容所有Modelica工具)

修改函数输入定义,使用replaceable和constrainedby限定输入为CrossSection的派生具体记录:

function foo
  replaceable input CrossSections.CrossSection cs constrainedby CrossSections.CrossSection;
  
  output Real o1;
algorithm
  if Modelica.Utilities.Strings.isEqual("Circle", cs.name) then
    o1 := cs.area*3;
  elseif Modelica.Utilities.Strings.isEqual("Rectangle", cs.name) then
    o1 := cs.area*2;
  else
    o1 := cs.area*5;
  end if;
end foo;

方式2:基于类型判断(更安全,部分工具支持如Dymola)

使用Modelica.Utilities.Types.isInstanceOf函数直接判断实例类型,避免依赖name字段的硬编码:

function foo
  replaceable input CrossSections.CrossSection cs constrainedby CrossSections.CrossSection;
  
  output Real o1;
algorithm
  if Modelica.Utilities.Types.isInstanceOf(cs, CrossSections.Circle) then
    o1 := cs.area*3;
  elseif Modelica.Utilities.Types.isInstanceOf(cs, CrossSections.Rectangle) then
    o1 := cs.area*2;
  else
    o1 := cs.area*5;
  end if;
end foo;

调用示例

可以在模型中直接传入派生记录实例调用函数:

model TestFoo
  CrossSections.Circle circle(d=0.1);
  CrossSections.Rectangle rect(a=0.2, b=0.3);
  Real res1, res2;
equation
  res1 = foo(circle);
  res2 = foo(rect);
end TestFoo;

内容的提问来源于stack exchange,提问作者Fabian Bachl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 23:47:30