简体   繁体   中英

How to eliminate dead code in Dymola/Modelica

I am trying to slim down a very complex model to improve performance, and noticed big performance changes when I add or remove variables into the signal bus, especially multi-body frames.

I am wondering if there is any setting that can eliminate code that isn't involved in generating outputs from the model.

I tried setting the bus connector to "protected" to ensure it doesn't become an output but the code to calculate them is still being generated.

I also tried these flags but it doesn't eliminate the dead code:

Advanced.Embedded.OptimizeForOutputs=true;
Advanced.SubstituteVariablesUsedOnce=true;
Evaluate=true;
Advanced.EvaluateAlsoTop=true;
Advanced.SubstituteVariablesUsedOnce=true;

This is a simple model to replicate the scenario:

简单的modelica模型

model TestBusConnector
  extends Modelica.Icons.Example;
protected 
        Modelica.Blocks.Examples.BusUsage_Utilities.Interfaces.ControlBus controlBus
    annotation (Placement(transformation(extent={{-20,-20},{20,20}})));
public 
  Modelica.Blocks.Sources.Sine sine(freqHz=1)
    annotation (Placement(transformation(extent={{-40,-50},{-20,-30}})));
  Modelica.Blocks.Sources.Constant const(k=0)
    annotation (Placement(transformation(extent={{-10,50},{10,70}})));
  Modelica.Blocks.Interfaces.RealOutput y
    annotation (Placement(transformation(extent={{90,-10},{110,10}})));
equation 
  connect(y, const.y) annotation (Line(points={{100,0},{60,0},{60,60},{11,60}}, color={0,0,127}));
  connect(sine.y, controlBus.testBusVariable)
    annotation (Line(points={{-19,-40},{0,-40},{0,0}}, color={0,0,127}));
  annotation (experiment(__Dymola_fixedstepsize=0.001, __Dymola_Algorithm="Euler"),
      __Dymola_experimentFlags(Advanced(
        InlineMethod=0,
        InlineOrder=2,
        InlineFixedStep=0.001)),
    __Dymola_experimentSetupOutput(
      states=false,
      derivatives=false,
      inputs=false,
      outputs=false,
      auxiliaries=false,
      equidistant=false,
      events=false));
end TestBusConnector;

Code generated from Dymola 2019 FD01 is shown below:

include <dsblock6.c>

PreNonAliasNew(0)
StartNonAlias(0)
DeclareVariable("sine.amplitude", "Amplitude of sine wave", 1, 0.0,0.0,0.0,0,513)
DeclareVariable("sine.freqHz", "Frequency of sine wave [Hz]", 1, 0.0,0.0,0.0,0,513)
DeclareVariable("sine.phase", "Phase of sine wave [rad|deg]", 0, 0.0,0.0,0.0,0,513)
DeclareVariable("sine.offset", "Offset of output signal", 0, 0.0,0.0,0.0,0,513)
DeclareVariable("sine.startTime", "Output = offset for time < startTime [s]", 0,\
 0.0,0.0,0.0,0,513)
DeclareVariable("sine.y", "Connector of Real output signal", 0.0, 0.0,0.0,0.0,0,512)
DeclareVariable("const.k", "Constant output value", 0, 0.0,0.0,0.0,0,513)
DeclareVariable("const.y", "Connector of Real output signal", 0, 0.0,0.0,0.0,0,513)
DeclareOutput("y", "", 0, 0.0, 0.0,0.0,0.0,0,513)
DeclareAlias2("controlBus.testBusVariable", "Connector of Real output signal", \
"sine.y", 1, 5, 5, 1028)
EndNonAlias(0)

#define DymolaHaveUpdateInitVars 1
#include <dsblock5.c>

DYMOLA_STATIC void UpdateInitVars(double*time, double* X_, double* XD_, double* U_, double* DP_, int IP_[], Dymola_bool LP_[], double* F_, double* Y_, double* W_, double QZ_[], double duser_[], int iuser_[], void*cuser_[],struct DYNInstanceData*did_,int initialCall) {
}
StartDataBlock
EndDataBlock

The translated modelica code (dsmodel.mof) still has the calculation for the sine block.

// Translated Modelica model generated by Dymola from Modelica model 
//  TEMP.TEST.TestBusConnector


// -----------------------------------------------------------------------------

// Initial Section
  sine.amplitude := 1;
  sine.freqHz := 1;
  sine.phase := 0;
  sine.offset := 0;
  sine.startTime := 0;
  const.k := 0;
  const.y := 0;
  y := 0.0;




// -----------------------------------------------------------------------------

// Conditionally Accepted Section
  sine.y := (if time < 0 then 0 else sin(6.283185307179586*time));

// -----------------------------------------------------------------------------

// Eliminated alias variables
  // To have eliminated alias variables listed, set
  //   Advanced.OutputModelicaCodeWithAliasVariables = true
  // before translation. May give much output.

Ideally, I would like the model to translate to:

y := 0.0;

The reason the other answers don't work is that your model is not consistent with your question: "I am wondering if there is any setting that can eliminate code that isn't involved in generating outputs from the model."

By connecting the control-bus to sine.y you implicitly create an output, and thus sine.y is involved in generating outputs from the model.

That can be avoided in one of the following ways:

  • Remove the connection between sine.y and controlBus
  • Change controlBus to be protected
  • Change so that controlBus isn't at the top-level

It's not a direct answer to your question, but still it could help to improve performance. Part of the computational effort you are trying to avoid is generated by computing variables in the result file. This can be avoided by the settings below:

选择要存储在结果文件中的变量

This can be set as an annotation in the model itself using:

  annotation (__Dymola_experimentSetupOutput(
      states=false,
      derivatives=false,
      inputs=false,
      auxiliaries=false));

There is another flag which could help. It does not give the result you expected, but it might be still useful:

Advanced.Define.AutoRemoveAuxiliaries = true;

The Dymola User Manual 2 describes the flag as follows:

Removes code for auxiliary variables that neither influences the simulation state nor the outputs. This improves performance a bit.

From this description my expectation was that the code is generated like you asked for, but unfortunately it is not the case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM