如何在 Dymola 中找到哪个组件正在使用外部组件?
How to find which component is using outer components in Dymola?
在Modelica模型中,我们经常使用外部组件,比如系统设置和其他公共变量,但是如果我正在阅读一个新模型,有没有什么简单的方法可以让我找到哪个组件正在使用外部组件?
例如,下面的屏幕截图是 Modelica.Fluid.Examples.HeatingSystem,我怎么知道哪个组件正在使用“系统”作为外部组件?
我可以逐行阅读代码,但是有更简单的方法吗?
Dymola 在图形用户界面中不提供此类功能。但是使用 ModelManagement
库可以获得这样的信息。该库可通过标准 Dymola 许可证获得并已预安装。
下面是函数 SO.printComponents()
,它使用 ModelManagement 库获取 class 中符合给定条件的所有组件。
对于您的模型,打印输出为:
Components in Modelica.Fluid.Examples.HeatingSystem using Modelica.Fluid.System as outer:
tank<Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel>.heatTransfer<Modelica.Fluid.Interfaces.PartialHeatTransfer>.system
tank<Modelica.Fluid.Interfaces.PartialLumpedVolume>.system
pump<Modelica.Fluid.Machines.BaseClasses.PartialPump>.heatTransfer<Modelica.Fluid.Interfaces.PartialHeatTransfer>.system
...
valve<Modelica.Fluid.Interfaces.PartialTwoPort>.system
...
您会看到 Modelica.Fluid.Examples.HeatingSystem
中的所有组件,其中包含 Modelica.Fluid.System
的实例,前缀为 outer。
如果组件通过 extends
从基础 class 继承了系统实例,则基础 class 以 <base-class>
.[= 形式在尖括号之间给出。 31=]
例如,输出中的第一个组件意味着,tank
组件正在扩展 PartialLumpedVessel
class,其中包含一个组件 heatTransfer
,它扩展了 PartialHeatTransfer
其中包含我们要查找的系统实例。
请注意,对于多级继承,只给出了最终基 class,而不是它的完整路径。这是例如与阀门相关,它通过 PartialValve
和 PartialTwoPortTransport
.
从 PartialTwoPort
继承系统实例
背景资料
ModelManagement 库在包 ModelManagement.Structure
中提供了一些有趣的函数,这些函数允许获取有关 Modelica classes 的信息。
函数分为两种不同的类型:
- ModelManagement.Structure.AST:对于这些函数,只考虑所选 class 的 Modelica 代码。继承的一切都不考虑。
- ModelManagement.Structure.Instantiated: 这个包中的所有函数都在翻译后的模型上运行
乍一看,ModelManagement.Structure.Instantiated.UsedModels
似乎是个不错的起点。但它的文档说:
Optionally disabled components, base-classes, and called functions are not included.
由于 Fluid 包大量使用了继承,如果不考虑继承,我们很容易错过一个组件。
幸运的是,测试库包含一个函数,returns 所有继承的基础 classes Testing.Utilities.Class.getExtendedClasses
。此外 ModelManagement.Structure.AST.ComponentsInClassAttributes
允许我们检索给定 class 的所有组件(但不是继承的组件)。
利用这两个函数,我们可以构建一个新函数:
- 检索 class 的所有组件,包括从基础 classes
继承的组件
- 检查组件是否符合我们的搜索条件(在您的情况下它应该是
Modelica.Fluid.System
的外部实例)
- 递归检查所有组件的子组件,因为系统的使用可能发生在层次结构的更下方
这是代码。此外还包括一个小打印功能,可以将找到的组件很好地打印到终端。
package SO
function getComponentsUsingClass "Get all components in class c1 which use class c2 as local component"
import ModelManagement.Structure.AST;
import Testing.Utilities.Class.getExtendedClasses;
import Testing.Utilities.Vectors.catStrings;
input String c1 "Full path of class of which components are retrieved";
input String c2 "Full path of class which must be used in the components";
input Boolean isOuter=false "Return only components where c2 is used as an outer instance";
output String cmp[:] "All components in c1 using c2";
protected
String sub[:] "Sub-components";
Boolean baseClass "True if current class is a baseClass of c1 (c1 extends it)";
String prefix "Used to give base classe";
algorithm
cmp :=fill("", 0);
// loop over class c1 and all its base classes
for c in cat(1,{c1}, getExtendedClasses(c1)) loop
baseClass :=c <> c1;
prefix :=if baseClass then "<" + c + ">." else ".";
// loop over all components in the current class
for cmpa in AST.ComponentsInClassAttributes(c) loop
if cmpa.fullTypeName==c2 and cmpa.isOuter==isOuter then
cmp :=cat(1, cmp, {prefix+cmpa.name});
end if;
// if the current component is a Modelica class, obtain all sub-components using c2
// (Mon-Modelica classes would e.g. be the attributes min, max, stateSelect etc. of built in classes)
if cmpa.fullTypeName<>"" then
sub := getComponentsUsingClass(cmpa.fullTypeName, c2, isOuter);
sub :=catStrings(fill(prefix+cmpa.name, size(sub, 1)), sub);
cmp :=cat(1, cmp, sub);
end if;
end for;
end for;
end getComponentsUsingClass;
function printComponents
import Modelica.Utilities.Streams.print;
import DymolaModels.Utilities.Strings.stripLeft;
input String c1="Modelica.Fluid.Examples.HeatingSystem" "Full path of class of which components are retrieved";
input String c2="Modelica.Fluid.System" "Full path of class which must be used in the components";
input Boolean isOuter=true "Return only components where c2 is used as an outer instance";
algorithm
print("Components in " + c1 + " using " + c2 + (if isOuter then " as outer" else "") + ":");
for c in getComponentsUsingClass(c1, c2,isOuter) loop
print(" " + stripLeft(c, "."));
end for;
end printComponents;
annotation (uses(
Modelica(version="4.0.0"),
Testing(version="1.3.1"),
ModelManagement(version="1.2.0"),
DymolaModels(version="1.2")));
end SO;
在Modelica模型中,我们经常使用外部组件,比如系统设置和其他公共变量,但是如果我正在阅读一个新模型,有没有什么简单的方法可以让我找到哪个组件正在使用外部组件?
例如,下面的屏幕截图是 Modelica.Fluid.Examples.HeatingSystem,我怎么知道哪个组件正在使用“系统”作为外部组件?
我可以逐行阅读代码,但是有更简单的方法吗?
Dymola 在图形用户界面中不提供此类功能。但是使用 ModelManagement
库可以获得这样的信息。该库可通过标准 Dymola 许可证获得并已预安装。
下面是函数 SO.printComponents()
,它使用 ModelManagement 库获取 class 中符合给定条件的所有组件。
对于您的模型,打印输出为:
Components in Modelica.Fluid.Examples.HeatingSystem using Modelica.Fluid.System as outer:
tank<Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel>.heatTransfer<Modelica.Fluid.Interfaces.PartialHeatTransfer>.system
tank<Modelica.Fluid.Interfaces.PartialLumpedVolume>.system
pump<Modelica.Fluid.Machines.BaseClasses.PartialPump>.heatTransfer<Modelica.Fluid.Interfaces.PartialHeatTransfer>.system
...
valve<Modelica.Fluid.Interfaces.PartialTwoPort>.system
...
您会看到 Modelica.Fluid.Examples.HeatingSystem
中的所有组件,其中包含 Modelica.Fluid.System
的实例,前缀为 outer。
如果组件通过 extends
从基础 class 继承了系统实例,则基础 class 以 <base-class>
.[= 形式在尖括号之间给出。 31=]
例如,输出中的第一个组件意味着,tank
组件正在扩展 PartialLumpedVessel
class,其中包含一个组件 heatTransfer
,它扩展了 PartialHeatTransfer
其中包含我们要查找的系统实例。
请注意,对于多级继承,只给出了最终基 class,而不是它的完整路径。这是例如与阀门相关,它通过 PartialValve
和 PartialTwoPortTransport
.
PartialTwoPort
继承系统实例
背景资料
ModelManagement 库在包 ModelManagement.Structure
中提供了一些有趣的函数,这些函数允许获取有关 Modelica classes 的信息。
函数分为两种不同的类型:
- ModelManagement.Structure.AST:对于这些函数,只考虑所选 class 的 Modelica 代码。继承的一切都不考虑。
- ModelManagement.Structure.Instantiated: 这个包中的所有函数都在翻译后的模型上运行
乍一看,ModelManagement.Structure.Instantiated.UsedModels
似乎是个不错的起点。但它的文档说:
Optionally disabled components, base-classes, and called functions are not included.
由于 Fluid 包大量使用了继承,如果不考虑继承,我们很容易错过一个组件。
幸运的是,测试库包含一个函数,returns 所有继承的基础 classes Testing.Utilities.Class.getExtendedClasses
。此外 ModelManagement.Structure.AST.ComponentsInClassAttributes
允许我们检索给定 class 的所有组件(但不是继承的组件)。
利用这两个函数,我们可以构建一个新函数:
- 检索 class 的所有组件,包括从基础 classes 继承的组件
- 检查组件是否符合我们的搜索条件(在您的情况下它应该是
Modelica.Fluid.System
的外部实例) - 递归检查所有组件的子组件,因为系统的使用可能发生在层次结构的更下方
这是代码。此外还包括一个小打印功能,可以将找到的组件很好地打印到终端。
package SO
function getComponentsUsingClass "Get all components in class c1 which use class c2 as local component"
import ModelManagement.Structure.AST;
import Testing.Utilities.Class.getExtendedClasses;
import Testing.Utilities.Vectors.catStrings;
input String c1 "Full path of class of which components are retrieved";
input String c2 "Full path of class which must be used in the components";
input Boolean isOuter=false "Return only components where c2 is used as an outer instance";
output String cmp[:] "All components in c1 using c2";
protected
String sub[:] "Sub-components";
Boolean baseClass "True if current class is a baseClass of c1 (c1 extends it)";
String prefix "Used to give base classe";
algorithm
cmp :=fill("", 0);
// loop over class c1 and all its base classes
for c in cat(1,{c1}, getExtendedClasses(c1)) loop
baseClass :=c <> c1;
prefix :=if baseClass then "<" + c + ">." else ".";
// loop over all components in the current class
for cmpa in AST.ComponentsInClassAttributes(c) loop
if cmpa.fullTypeName==c2 and cmpa.isOuter==isOuter then
cmp :=cat(1, cmp, {prefix+cmpa.name});
end if;
// if the current component is a Modelica class, obtain all sub-components using c2
// (Mon-Modelica classes would e.g. be the attributes min, max, stateSelect etc. of built in classes)
if cmpa.fullTypeName<>"" then
sub := getComponentsUsingClass(cmpa.fullTypeName, c2, isOuter);
sub :=catStrings(fill(prefix+cmpa.name, size(sub, 1)), sub);
cmp :=cat(1, cmp, sub);
end if;
end for;
end for;
end getComponentsUsingClass;
function printComponents
import Modelica.Utilities.Streams.print;
import DymolaModels.Utilities.Strings.stripLeft;
input String c1="Modelica.Fluid.Examples.HeatingSystem" "Full path of class of which components are retrieved";
input String c2="Modelica.Fluid.System" "Full path of class which must be used in the components";
input Boolean isOuter=true "Return only components where c2 is used as an outer instance";
algorithm
print("Components in " + c1 + " using " + c2 + (if isOuter then " as outer" else "") + ":");
for c in getComponentsUsingClass(c1, c2,isOuter) loop
print(" " + stripLeft(c, "."));
end for;
end printComponents;
annotation (uses(
Modelica(version="4.0.0"),
Testing(version="1.3.1"),
ModelManagement(version="1.2.0"),
DymolaModels(version="1.2")));
end SO;