Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
302 views
in Technique[技术] by (71.8m points)

modelica - How to find which component is using outer components in Dymola?

In Modelica models, we often use outer components, such as system settings and other common variables, but if I am reading a new model, is there any easy way to allow me to find which component is using outer components?
As an example, the following screenshot is Modelica.Fluid.Examples.HeatingSystem, how could I know which component is using the "system" as an outer component?
I could read the code line by line, but is there an easier way to do this? enter image description here

question from:https://stackoverflow.com/questions/65857118/how-to-find-which-component-is-using-outer-components-in-dymola

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Dymola does not provide such a feature in the gui. But with the ModelManagement library its possible to obtain such information. The library is available with the standard Dymola license and pre-installed.

Below you find the function SO.printComponents() which uses the ModelManagement library to obtain all components in a class which match the given criterias.

For your model the printed output is:

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
  ...

You see all components in Modelica.Fluid.Examples.HeatingSystem which contain an instance of Modelica.Fluid.System with the prefix outer.

If a component inherited the system instance from a base class via extends, the base class is given between angle brackets in the form <base-class>.

The first component in the output for example means, that the tank component is extending the PartialLumpedVessel class, which contains a component heatTransfer which extends the PartialHeatTransfer which contains the system instance we are looking for.

Note that for multilevel inheritance only the final base class is given, not the full path to it. This is e.g. relevant for the valve, which inherits the system instance from PartialTwoPort via PartialValve and PartialTwoPortTransport.

Background information

The ModelManagement library features some interesting functions in the package ModelManagement.Structure which allow to obtain information about Modelica classes.

The functions are divided into two different types:

  • ModelManagement.Structure.AST: For these functions, only Modelica code of the selected class is considered. Everything that is inherited is not considered.
  • ModelManagement.Structure.Instantiated: All functions in this package operate on the translated model

At the first glance ModelManagement.Structure.Instantiated.UsedModels seems a good starting point. But its documentation says:

Optionally disabled components, base-classes, and called functions are not included.

As the Fluid package makes heavy use of inheritance, we would easily miss a component when inheritance is not considered.

Fortunately the Testing library contains a function, which returns all inherited base classes Testing.Utilities.Class.getExtendedClasses. In addition ModelManagement.Structure.AST.ComponentsInClassAttributes allows us to retrieve all components of a given class (but not the inherited ones).

With those two functions, we can build a new function that:

  • Retrieves all components of a class, including the ones inherited from base classes
  • Checks if a component matches our search criteria (in your case it should be an outer instance of Modelica.Fluid.System)
  • Recursively check sub-components of all components, as the usage of system could happen further down in the hierarchy

Here is the code. Additionally a small print function is included, which prints the found components nicely to the terminal.

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...