Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor actuator travel time #1926

Open
mwetter opened this issue Aug 28, 2024 · 9 comments · May be fixed by #1933
Open

Refactor actuator travel time #1926

mwetter opened this issue Aug 28, 2024 · 9 comments · May be fixed by #1933
Assignees

Comments

@mwetter
Copy link
Contributor

mwetter commented Aug 28, 2024

The current implementation of the actuator model, using the 2nd order filter, causes always similar time to make a set point change, regardless of the size of the set point change. A more realistic implementation would use a slew rate limiter.

This issue is to test the performance of using a slew rate limiter and if the performance is good, change the actuator model that is used for pumps, valves and dampers.

The implementation is also done at lbl-srg/modelica-buildings#3965 to allow for benchmarking across a larger set of test cases.

The development branch is issue1926_actuatorTravel

@mwetter mwetter self-assigned this Aug 28, 2024
mwetter added a commit that referenced this issue Aug 28, 2024
This refactors the actuator models for #1926
@mwetter
Copy link
Contributor Author

mwetter commented Aug 28, 2024

Commit a1121d6 is an implementation that allows for the old functionality of using a 2nd order filter, but by default, the new model that linearly changes the actuator position is used. The model has now parameters for dampers and valves:

image

and for fans:

image

My suggestion is -- provided that numerical experiments are good which looks like to be the case based on ongoing tests -- to remove the 2nd order filter. Then the only option will be to have the linear travel time. The parameter use_linearDynamics can be removed, and we keep use_inputFilter.

Alternate names for discussion would be use_strokeTime (for dampers and valves) and use_riseTime (for fans and pumps) and provide a conversion script. Keeping use_inputFilter has the advantage that we use the same terms for actuators and movers, which is more intuitive as they both use the same implementation.

We could keep riseTime (but update the comment as the 99.6% no longer make sense), or we could change it with a conversion script to strokeTime for the valves and dampers. For the motor, I suggest to keep riseTime unless someone has a better term. Again, keeping riseTime may be more intuitive as actuators and movers use the same term for the same implementation.

@mwetter
Copy link
Contributor Author

mwetter commented Aug 28, 2024

Todo:

  • Discuss name and implementation.
  • Refactor FlowControlled_dp and FlowControlled_m_flow as the input to the slow rate limiter has now a unit and hence the scale is no longer 0...1. This requires proper scaling.
  • Update Actuators.UsersGuide.
  • Update Movers.UsersGuide.
  • Update reference results.

@justnielsen
Copy link

Hi Michael,

Thanks for looking into this issue. It could be relevant to include a closed-loop test at some point during the assessment. Below is a minimal example with two pressure controlling valves. One, valFil, uses the existing filter-only implementation and the other, valLin uses the proposed linear actuator dynamics. The actuator dynamics predominate the process dynamics (since there is no other dynamics) and the closed-loop simulation shows 'different' performance which indicates that models with controllers and actuator dynamic should be re-tuned. This could speak in favor of keeping the existing filter as the default option (?)

Replacing the filter with the slew rate limiter with riseTime set to the same value makes the process dynamics faster. With unchanged controller parameters, this tends to move the closed-loop dynamics further away from instability. This is positive from a stability point of view.

In processes where the dynamics are dominated by other components (thermal inertia etc.) and not by the actuator, the performance difference will be less pronounced.

The model

valveTravel_diagram

The results

valveTravel_plot

The code

model valveTravel
  extends Modelica.Icons.Example;
  package Medium = IBPSA.Media.Water "Medium";

  IBPSA.Controls.Continuous.LimPID pidFil(k=2e-3, Ti=15)
    annotation (Placement(transformation(extent={{-30,50},{-10,70}})));
  IBPSA.Controls.Continuous.LimPID pidLin(k=2e-3, Ti=15)
    annotation (Placement(transformation(extent={{-30,-30},{-10,-10}})));
  IBPSA.Fluid.Actuators.Valves.TwoWayLinear valFil(
    redeclare package Medium = Medium,
    use_linearDynamics=false,
    riseTime=30,
    y_start=0,
    l=0.0001,
    m_flow_nominal=2,
    dpValve_nominal=6000,
    from_dp=true) "Valve model with second-order filter enabled"
    annotation (Placement(transformation(extent={{-10,10},{10,30}})));
  IBPSA.Fluid.Actuators.Valves.TwoWayLinear valLin(
    redeclare package Medium = Medium,
    riseTime=30,
    y_start=0,
    l=0.0001,
    m_flow_nominal=2,
    dpValve_nominal=6000,
    from_dp=true) "Valve model with linear travel model"
    annotation (Placement(transformation(extent={{-10,-70},{10,-50}})));


  Modelica.Blocks.Sources.Step y(
    height=1000,
    offset=302000,
    startTime=60) "Control signal"
    annotation (Placement(transformation(extent={{-100,50},{-80,70}})));

  IBPSA.Fluid.Sensors.Pressure senPreFil(redeclare package Medium = Medium)
    annotation (Placement(transformation(
        extent={{-10,10},{10,-10}},
        rotation=180,
        origin={30,40})));
  IBPSA.Fluid.Sensors.Pressure senPreLin(redeclare package Medium = Medium)
    annotation (Placement(transformation(
        extent={{-10,10},{10,-10}},
        rotation=180,
        origin={30,-40})));
  IBPSA.Fluid.FixedResistances.PressureDrop resFil(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=4000)
    annotation (Placement(transformation(extent={{40,10},{60,30}})));
  IBPSA.Fluid.FixedResistances.PressureDrop resLin(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=4000)
    annotation (Placement(transformation(extent={{40,-70},{60,-50}})));
  IBPSA.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    nPorts=2,
    use_p_in=false,
    p(displayUnit="Pa") = 310000,
    T=293.15) "Boundary condition for flow source"
    annotation (Placement(transformation(extent={{-100,30},{-80,10}})));
  IBPSA.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    nPorts=2,
    p(displayUnit="Pa") = 3E5,
    T=293.15) "Boundary condition for flow sink"
    annotation (Placement(transformation(extent={{100,30},{80,10}})));
equation 
  connect(sou.ports[1], valFil.port_a)
    annotation (Line(points={{-80,21},{-80,20},{-10,20}}, color={0,127,255}));
  connect(valFil.port_b, resFil.port_a)
    annotation (Line(points={{10,20},{40,20}}, color={0,127,255}));
  connect(resFil.port_b, sin.ports[1])
    annotation (Line(points={{60,20},{80,20},{80,21}}, color={0,127,255}));
  connect(valFil.port_b, senPreFil.port)
    annotation (Line(points={{10,20},{30,20},{30,30}}, color={0,127,255}));
  connect(pidFil.y, valFil.y)
    annotation (Line(points={{-9,60},{0,60},{0,32}}, color={0,0,127}));
  connect(senPreFil.p, pidFil.u_m)
    annotation (Line(points={{19,40},{-20,40},{-20,48}}, color={0,0,127}));
  connect(y.y, pidFil.u_s)
    annotation (Line(points={{-79,60},{-32,60}}, color={0,0,127}));
  connect(valLin.port_b, resLin.port_a)
    annotation (Line(points={{10,-60},{40,-60}}, color={0,127,255}));
  connect(valLin.port_b, senPreLin.port)
    annotation (Line(points={{10,-60},{30,-60},{30,-50}}, color={0,127,255}));
  connect(pidLin.y, valLin.y)
    annotation (Line(points={{-9,-20},{0,-20},{0,-48}}, color={0,0,127}));
  connect(senPreLin.p, pidLin.u_m)
    annotation (Line(points={{19,-40},{-20,-40},{-20,-32}}, color={0,0,127}));
  connect(y.y, pidLin.u_s) annotation (Line(points={{-79,60},{-50,60},{-50,-20},
          {-32,-20}}, color={0,0,127}));
  connect(valLin.port_a, sou.ports[2]) annotation (Line(points={{-10,-60},{-68,-60},
          {-68,19},{-80,19}}, color={0,127,255}));
  connect(resLin.port_b, sin.ports[2]) annotation (Line(points={{60,-60},{70,-60},
          {70,19},{80,19}}, color={0,127,255}));
  annotation (
    experiment(
      StopTime=120,
      Tolerance=1e-06,
      __Dymola_Algorithm="Dassl"),
    uses(Modelica(version="4.0.0"), IBPSA(version="4.0.0")),
    Diagram(coordinateSystem(extent={{-100,-80},{100,80}})));
end valveTravel;

@mwetter
Copy link
Contributor Author

mwetter commented Aug 29, 2024

@justnielsen : Thanks for the example. We will watch out for control performance when doing the update. If we remove the option, we could move the old valves to the Obsolete package so people can switch back to the old behavior for a while if desired. (Note that in the maintenance branches of the libraries, such as Buildings 10.x, the old behavior will be retained, so retuning is only needed if models are update to the next major release.)

I agree that this generally moves away from the instability region.

@mwetter
Copy link
Contributor Author

mwetter commented Sep 5, 2024

Discussion:

  • IDEAS and LBL prefers to delete the 2nd order filter. To be checked with AixLib.
  • IDEAS and LBL prefer the following wording: use_strokeTime and strokeTime (for dampers and valves) and use_riseTime and riseTime (for fans and pumps).

@FWuellhorst and @nytschgeusen : Can you please add AixLibs and BuildingSystems preference so that we can close on this.

@Mathadon
Copy link
Member

Mathadon commented Sep 5, 2024

Sounds like a nice feature/update. I've used a slew rate filter in the past too and that worked without problems. I also check the MSL implementation and that looks ok.

I'm just confused about the statement that the slew rate filter makes process dynamics faster. I see the valve open at a slower pace instead of faster in the picture you sent. And that's indeed what I'd expect from the model equations. So this would result in more instability in closed loop control. (But less instability from the time integrator! Also, larger time steps, this would explain the speedups in the Buildings benchmark?)

I'd also propose to remove the old parameters and the proposed wording sounds good.

@mwetter
Copy link
Contributor Author

mwetter commented Sep 5, 2024

@Mathadon : Thanks for the feedback. For small adjustments, the slew rate limiter should be faster. E.g., if riseTime=60 seconds, and the input jumps by 10%, it takes 6 seconds to get to the new position, whereas with the 2nd order filter it still takes 60 seconds to get to the 99.6% change, regardless of how big the jump in input is.

@FWuellhorst
Copy link
Contributor

@mwetter Fine for AixLib, thanks for fixing this issue.

@nytschgeusen
Copy link
Contributor

@mwetter Also fine for BuildingSystems.

@mwetter mwetter linked a pull request Sep 15, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants