From c6c73a38e14da29f54748502a155d52b918e08c8 Mon Sep 17 00:00:00 2001 From: FWuellhorst Date: Wed, 6 Dec 2023 15:08:09 +0100 Subject: [PATCH] move fuzzy logic to separate model, make preOnOff name clear and hopefully fix optimica error. --- .../Safety/BaseClasses/OnOffFuzzyLogic.mo | 92 ++++++++++++++ .../BaseClasses/PartialOperationalEnvelope.mo | 2 +- .../Controls/Safety/BaseClasses/package.order | 1 + .../Controls/Safety/Data/Generic.mo | 3 +- .../Controls/Safety/Data/Wuellhorst2021.mo | 2 +- .../Controls/Safety/Examples/OnOff.mo | 6 +- .../Controls/Safety/OnOff.mo | 115 ++++++------------ .../Controls/Safety/Safety.mo | 2 +- 8 files changed, 140 insertions(+), 83 deletions(-) create mode 100644 IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/OnOffFuzzyLogic.mo diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/OnOffFuzzyLogic.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/OnOffFuzzyLogic.mo new file mode 100644 index 0000000000..3554048d04 --- /dev/null +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/OnOffFuzzyLogic.mo @@ -0,0 +1,92 @@ +within IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses; +model OnOffFuzzyLogic + "Fuzzy logic approach for on-off control" + parameter Real ySetRed + "Reduced relative compressor speed to allow longer on-time"; + Modelica.Blocks.Interfaces.BooleanInput turOn(start=false, fixed=true) + "Indicates if device should turn on" annotation (Placement(transformation( + extent={{-132,-76},{-100,-44}}))); + Modelica.Blocks.Interfaces.BooleanInput isAblToTurOn + "Indicates if the device can turn on" annotation (Placement(transformation( + extent={{-132,-106},{-100,-74}}))); + Modelica.Blocks.Interfaces.BooleanInput turOff(start=false, fixed=true) + "Indicates if the device should turn off" annotation (Placement( + transformation(extent={{-132,14},{-100,46}}))); + Modelica.Blocks.Interfaces.BooleanInput isAblToTurOff + "Indicates if the device can turn off" + annotation (Placement(transformation(extent={{-132,74},{-100,106}}))); + Modelica.Blocks.Interfaces.BooleanInput staOff + "Indicates if the device has to stay off" annotation (Placement( + transformation(extent={{-132,-46},{-100,-14}}))); + Modelica.Blocks.Interfaces.BooleanInput staOn + "Indicates if the device has to stay on" annotation (Placement(transformation( + extent={{-132,44},{-100,76}}))); + Modelica.Blocks.Interfaces.RealOutput yOut + "Output for relative compressor speed from 0 to 1" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Modelica.Blocks.Interfaces.RealInput ySet + "Input for relative compressor speed from 0 to 1" + annotation (Placement(transformation(extent={{-132,-16},{-100,16}}))); +protected + Integer devRunMin(start=0, fixed=true) + "Indicates if device needs to run at minimal limit"; + Integer devTurOff(start=0, fixed=true) + "Indicates if device needs to turn off"; + Integer devNorOpe(start=1, fixed=true) + "Indicates if device is at normal operation"; +equation + yOut = ySet * devNorOpe + 0 * devTurOff + ySetRed * devRunMin; + when edge(turOn) then + if isAblToTurOn then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + else + devTurOff = 1; + devRunMin = 0; + devNorOpe = 0; + end if; + elsewhen edge(turOff) then + if isAblToTurOff then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + else + devTurOff = 0; + devRunMin = 1; + devNorOpe = 0; + end if; + elsewhen isAblToTurOn and turOn then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + elsewhen isAblToTurOff and turOff then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + elsewhen staOff then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + elsewhen staOn then + devTurOff = 0; + devRunMin = 0; + devNorOpe = 1; + end when; + + annotation (Documentation(info=" +

+The model uses a fuzzy logic approach to avoid the need for a state-machine. +The device either has to turn off, run at the desired operating speed, or run +at the minimal speed. +

+", revisions=" +"), Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false))); +end OnOffFuzzyLogic; diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/PartialOperationalEnvelope.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/PartialOperationalEnvelope.mo index 415096a37c..d2a8987e0f 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/PartialOperationalEnvelope.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/PartialOperationalEnvelope.mo @@ -1,4 +1,4 @@ -within IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses; +within IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses; partial model PartialOperationalEnvelope "Indicates if the device operation is within a defined envelope" extends BaseClasses.PartialSafetyWithCounter; diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/package.order b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/package.order index 179873b31b..ebfa2baba7 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/package.order +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/BaseClasses/package.order @@ -4,3 +4,4 @@ OnPastThreshold PartialOperationalEnvelope PartialSafety PartialSafetyWithCounter +OnOffFuzzyLogic diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Generic.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Generic.mo index 5ff7a2a77e..e7a659809d 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Generic.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Generic.mo @@ -26,7 +26,8 @@ record Generic "Generic record definition for safety control blocks" annotation ( Dialog(group="On/Off Control", enable=use_minOnTime)); - parameter Boolean preYSet_start "Start value of pre(n) at initial time" + parameter Boolean onOffMea_start=true + "Start value for the on-off signal of the device, true for on" annotation ( Dialog(group="On/Off Control"), choices(checkBox=true)); diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Wuellhorst2021.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Wuellhorst2021.mo index 1290c3ae0c..290df53c20 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Wuellhorst2021.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Data/Wuellhorst2021.mo @@ -4,7 +4,7 @@ record Wuellhorst2021 extends Generic( tabLowCoo=[263.15,283.15; 333.15,283.15], dTHysAntFre=2, - preYSet_start=false, + onOffMea_start=false, ySetRed=0.3, r_mConMinPer_flow=0.1, r_mEvaMinPer_flow=0.1, diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Examples/OnOff.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Examples/OnOff.mo index ae15633b59..57495abcee 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Examples/OnOff.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Examples/OnOff.mo @@ -1,13 +1,13 @@ within IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.Examples; model OnOff "Example for on off controller" - extends BaseClasses.PartialSafety( hys(pre_y_start=true)); + extends BaseClasses.PartialSafety; extends Modelica.Icons.Example; IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.OnOff onOffCtr( maxCycRat=2, minOffTime(displayUnit="s") = 200, minOnTime(displayUnit="s") = 300, - preYSet_start=false, + onOffMea_start=false, use_minOffTime=true, use_minOnTime=true, use_maxCycRat=true, @@ -25,7 +25,7 @@ equation 11.6667},{42,-50},{22,-50}}, color={0,0,127})); connect(onOffCtr.sigBus, sigBus) annotation (Line( - points={{0.0833333,3.91667},{-50,3.91667},{-50,-52}}, + points={{0.0833333,3.91667},{-50,3.91667},{-50,-50}}, color={255,204,51}, thickness=0.5), Text( string="%second", diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/OnOff.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/OnOff.mo index 80782789f2..0ddb378168 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/OnOff.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/OnOff.mo @@ -19,14 +19,14 @@ model OnOff annotation(choices(checkBox=true)); parameter Integer maxCycRat "Maximum cycle rate" annotation (Dialog(enable=use_maxCycRat)); - parameter Boolean preYSet_start=true - "Start value of pre(ySet) at initial time"; + parameter Boolean onOffMea_start=true + "Start value for the on-off signal of the device, true for on"; parameter Real ySet_small "Threshold for relative speed for the device to be considered on"; parameter Real ySetRed=ySet_small "Reduced relative compressor speed to allow longer on-time"; Modelica.Blocks.Logical.Hysteresis ySetOn( - final pre_y_start=preYSet_start, + final pre_y_start=onOffMea_start, final uHigh=ySet_small, final uLow=ySet_small/2) "=true if device is set on" annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); @@ -34,17 +34,17 @@ model OnOff y(start=true, fixed=true)) "=true if the device is allowed to turn off, else false" annotation (Placement(transformation(extent={{40,80},{60,100}}))); - Modelica.Blocks.Logical.Pre preOnOff(final pre_u_start=preYSet_start) + Modelica.Blocks.Logical.Pre preOnOff(final pre_u_start=onOffMea_start) "On off signal of previous time step" annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses.CycleRateBoundary cycRatBou(final maxCycRat=maxCycRat, final delTim=3600) if use_maxCycRat "Check cycle rate violations" - annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses.OnPastThreshold locTimCtr( final minOnTime=minOffTime) if use_minOffTime "Check if device should be locked" - annotation (Placement(transformation(extent={{20,10},{40,30}}))); + annotation (Placement(transformation(extent={{0,10},{20,30}}))); Modelica.Blocks.Logical.Not notIsOn "=true if device is off" annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); IBPSA.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses.OnPastThreshold runTimCtr( @@ -53,26 +53,24 @@ model OnOff Modelica.Blocks.Logical.And andIsAblToTurOn( y(start=true, fixed=true)) "=false to lock the device off" - annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + annotation (Placement(transformation(extent={{50,-70},{70,-50}}))); Modelica.Blocks.Sources.BooleanConstant booConstCycRat(final k=true) if not use_maxCycRat "Constant value for disabled option" - annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + annotation (Placement(transformation(extent={{0,-100},{20,-80}}))); Modelica.Blocks.Sources.BooleanConstant booConstLocTim(final k=true) if not use_minOffTime "Constant value for disabled option" - annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + annotation (Placement(transformation(extent={{0,-20},{20,0}}))); Modelica.Blocks.Sources.BooleanConstant booConstRunTim(final k=true) if not use_minOnTime "Constant value for disabled option" annotation (Placement(transformation(extent={{0,60},{20,80}}))); Modelica.Blocks.Logical.Not notSetOn "Device is not set to turn on" annotation (Placement(transformation(extent={{-100,18},{-80,38}}))); - Modelica.Blocks.Logical.And andTurOff( - y(start=not preYSet_start, fixed=true)) + Modelica.Blocks.Logical.And andTurOff "Check if device is on and is set to be turned off" annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); - Modelica.Blocks.Logical.And andTurOn( - y(start=preYSet_start, fixed=true)) - "Check if device is Off and is set to be turned on" + Modelica.Blocks.Logical.And andTurOn + "Check if device is off and is set to be turned on" annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); Modelica.Blocks.Logical.And andStaOn @@ -87,71 +85,29 @@ model OnOff rotation=0, origin={-90,110}))); -protected - Integer devRunMin(start=0, fixed=true) - "Indicates if device needs to run at minimal limit"; - Integer devTurOff(start=0, fixed=true) - "Indicates if device needs to turn off"; - Integer devNorOpe(start=1, fixed=true) - "Indicates if device is at normal operation"; + BaseClasses.OnOffFuzzyLogic onOffFuzLog(ySetRed=ySetRed) + "Fuzzy logic to device for output" + annotation (Placement(transformation(extent={{74,0},{114,40}}))); equation - yOut = ySet * devNorOpe + 0 * devTurOff +ySetRed * devRunMin; - when edge(andTurOn.y) then - if andIsAblToTurOn.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - else - devTurOff = 1; - devRunMin = 0; - devNorOpe = 0; - end if; - elsewhen edge(andTurOff.y) then - if isAblToTurOff.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - else - devTurOff = 0; - devRunMin = 1; - devNorOpe = 0; - end if; - elsewhen andIsAblToTurOn.y and andTurOn.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - elsewhen isAblToTurOff.y and andTurOff.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - elsewhen andStaOff.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - elsewhen andStaOn.y then - devTurOff = 0; - devRunMin = 0; - devNorOpe = 1; - end when; connect(preOnOff.y, cycRatBou.u) annotation (Line(points={{-79,-90},{-66,-90},{-66, - -66},{-24,-66},{-24,-50},{18,-50}}, color={255,0,255})); + -50},{-2,-50}}, color={255,0,255})); connect(preOnOff.y, notIsOn.u) annotation (Line(points={{-79,-90},{-66,-90},{-66, -66},{-108,-66},{-108,-50},{-102,-50}}, color={255,0,255})); - connect(notIsOn.y, locTimCtr.u) annotation (Line(points={{-79,-50},{-52,-50},{ - -52,-10},{0,-10},{0,20},{18,20}}, + connect(notIsOn.y, locTimCtr.u) annotation (Line(points={{-79,-50},{-52,-50},{-52, + -30},{-48,-30},{-48,-4},{-8,-4},{-8,20},{-2,20}}, color={255,0,255})); connect(runTimCtr.u, preOnOff.y) annotation (Line(points={{-2,100},{-66,100},{ -66,-90},{-79,-90}}, color={255,0,255})); connect(locTimCtr.y, andIsAblToTurOn.u1) annotation (Line( - points={{41,20},{52,20},{52,-60},{58,-60}}, + points={{21,20},{26,20},{26,-10},{36,-10},{36,-60},{48,-60}}, color={255,0,255}, pattern=LinePattern.Dash)); connect(cycRatBou.y, andIsAblToTurOn.u2) annotation (Line( - points={{41,-50},{50,-50},{50,-68},{58,-68}}, + points={{21,-50},{30,-50},{30,-68},{48,-68}}, color={255,0,255}, pattern=LinePattern.Dash)); connect(booConstCycRat.y, andIsAblToTurOn.u2) annotation (Line( - points={{41,-90},{50,-90},{50,-68},{58,-68}}, + points={{21,-90},{32,-90},{32,-68},{48,-68}}, color={255,0,255}, pattern=LinePattern.Dash)); @@ -167,7 +123,7 @@ equation connect(notIsOn.y, andTurOn.u1) annotation (Line(points={{-79,-50},{-52,-50},{ -52,-90},{-42,-90}}, color={255,0,255})); connect(booConstLocTim.y, andIsAblToTurOn.u1) annotation (Line( - points={{41,-10},{52,-10},{52,-60},{58,-60}}, + points={{21,-10},{36,-10},{36,-60},{48,-60}}, color={255,0,255}, pattern=LinePattern.Dash)); @@ -195,6 +151,22 @@ equation {28,100},{21,100}}, color={255,0,255})); connect(booConstRunTim.y, isAblToTurOff.u) annotation (Line(points={{21,70},{28, 70},{28,90},{38,90}}, color={255,0,255})); + connect(onOffFuzLog.yOut, yOut) + annotation (Line(points={{116,20},{130,20}}, color={0,0,127})); + connect(onOffFuzLog.ySet, ySet) annotation (Line(points={{70.8,20},{56,20},{56,36}, + {-76,36},{-76,20},{-136,20}}, color={0,0,127})); + connect(onOffFuzLog.staOff, andStaOff.y) annotation (Line(points={{70.8,14},{36, + 14},{36,-30},{-19,-30}}, color={255,0,255})); + connect(onOffFuzLog.staOn, andStaOn.y) annotation (Line(points={{70.8,32},{42,32}, + {42,50},{-19,50}}, color={255,0,255})); + connect(onOffFuzLog.isAblToTurOff, isAblToTurOff.y) annotation (Line(points={{70.8, + 38},{64,38},{64,90},{61,90}}, color={255,0,255})); + connect(andIsAblToTurOn.y, onOffFuzLog.isAblToTurOn) annotation (Line(points={{71, + -60},{80,-60},{80,-40},{54,-40},{54,2},{70.8,2}}, color={255,0,255})); + connect(onOffFuzLog.turOff, andTurOff.y) annotation (Line(points={{70.8,26},{32, + 26},{32,40},{-12,40},{-12,10},{-19,10}}, color={255,0,255})); + connect(onOffFuzLog.turOn, andTurOn.y) annotation (Line(points={{70.8,8},{28,8}, + {28,-70},{-12,-70},{-12,-90},{-19,-90}}, color={255,0,255})); annotation (Documentation(info="

Checks if the ySet value is legal by checking if @@ -240,14 +212,5 @@ equation "), - Diagram(coordinateSystem(extent={{-120,-120},{120,120}}), graphics={ - Rectangle( - extent={{120,60},{60,-10}}, - lineColor={0,0,127}, - fillColor={255,255,255}, - fillPattern=FillPattern.Solid), Text( - extent={{60,60},{120,-6}}, - textColor={0,0,127}, - textString="See -equations")})); + Diagram(coordinateSystem(extent={{-120,-120},{120,120}}))); end OnOff; diff --git a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Safety.mo b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Safety.mo index 9defa9ac62..0b72a730e0 100644 --- a/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Safety.mo +++ b/IBPSA/Fluid/HeatPumps/ModularReversible/Controls/Safety/Safety.mo @@ -33,7 +33,7 @@ model Safety "Model including all safety levels" final use_minOffTime=safCtrPar.use_minOffTime, final use_maxCycRat=safCtrPar.use_maxCycRat, final maxCycRat=safCtrPar.maxCycRat, - final preYSet_start=safCtrPar.preYSet_start, + final onOffMea_start=safCtrPar.onOffMea_start, final ySet_small=ySet_small, final ySetRed=safCtrPar.ySetRed) if safCtrPar.use_minOnTime or safCtrPar.use_minOffTime or safCtrPar.use_maxCycRat "On off control block"