diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
new file mode 100644
index 0000000000..a881df6575
--- /dev/null
+++ b/.github/workflows/github-actions.yml
@@ -0,0 +1,85 @@
+name: CI of IDEAS using GitHub Actions
+on: [push, pull_request]
+jobs:
+ build:
+ runs-on: self-hosted
+ steps:
+ - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
+ - run: echo "🐧 This job is now running on a ${{ runner.os }} server called tony-de-rekenpony hosted by The Sysis team at KU Leuven"
+ - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
+ - name: Check out repository code
+ uses: actions/checkout@v3
+ with:
+ clean: true
+ - name: Change permissions of repository folder
+ run: chmod -R 777 /home/actions-runner/_work
+ - name: List of files in the repository
+ run: |
+ ls ${{ github.workspace }}
+ test:
+ runs-on: self-hosted
+ needs: build
+ defaults:
+ run:
+ working-directory: IDEAS/Resources/Scripts/tests
+ steps:
+ - name: Test IDEAS.Buildings.Components
+ run: make test-dymola PACKAGE=\"IDEAS.Buildings.Components\" INTERACTIVE=false
+ - name: Test IDEAS.Buildings.Examples
+ run: make test-dymola PACKAGE=\"IDEAS.Buildings.Examples\" INTERACTIVE=false
+ - name: Test IDEAS.Buildings.Validation
+ run: make test-dymola PACKAGE=\"IDEAS.Buildings.Validation\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Actuators
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Actuators\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.BaseClasses
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.BaseClasses\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Chillers
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Chillers\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Delays
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Delays\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Examples
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Examples\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.FixedResistances
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.FixedResistances\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Geothermal
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Geothermal\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.HeatExchangers
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.HeatExchangers\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.HeatPumps
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.HeatPumps\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Interfaces
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Interfaces\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.MassExchangers
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.MassExchangers\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.MixingVolumes
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.MixingVolumes\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Movers
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Movers\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Sensors
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Sensors\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Sources
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Sources\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Storage
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Storage\" INTERACTIVE=false
+ - name: Test IDEAS.Fluid.Taps
+ run: make test-dymola PACKAGE=\"IDEAS.Fluid.Taps\" INTERACTIVE=false
+ - name: Test IDEAS.ThermalZones
+ run: make test-dymola PACKAGE=\"IDEAS.ThermalZones\" INTERACTIVE=false
+ - name: Test IDEAS.BoundaryConditions
+ run: make test-dymola PACKAGE=\"IDEAS.BoundaryConditions\" INTERACTIVE=false
+ - name: Test IDEAS.Controls
+ run: make test-dymola PACKAGE=\"IDEAS.Controls\" INTERACTIVE=false
+ - name: Test IDEAS.Media
+ run: make test-dymola PACKAGE=\"IDEAS.Media\" INTERACTIVE=false
+ - name: Test IDEAS.Utilities
+ run: make test-dymola PACKAGE=\"IDEAS.Utilities\" INTERACTIVE=false
+ - name: Test IDEAS.Templates
+ run: make test-dymola PACKAGE=\"IDEAS.Templates\" INTERACTIVE=false
+ - name: Test IDEAS.Examples.PPD12
+ run: make test-dymola PACKAGE=\"IDEAS.Examples.PPD12\" INTERACTIVE=false
+ - name: Test IDEAS.Examples.IBPSA
+ run: make test-dymola PACKAGE=\"IDEAS.Examples.IBPSA\" INTERACTIVE=false
+ - name: Test IDEAS.Examples.Tutorial
+ run: make test-dymola PACKAGE=\"IDEAS.Examples.Tutorial\" INTERACTIVE=false
+ - name: Test IDEAS.Examples.TwinHouses
+ run: make test-dymola PACKAGE=\"IDEAS.Examples.TwinHouses\" INTERACTIVE=false
\ No newline at end of file
diff --git a/IDEAS/Airflow/Multizone/BaseClasses/ReversibleDensityColumn.mo b/IDEAS/Airflow/Multizone/BaseClasses/ReversibleDensityColumn.mo
deleted file mode 100644
index f831d0982c..0000000000
--- a/IDEAS/Airflow/Multizone/BaseClasses/ReversibleDensityColumn.mo
+++ /dev/null
@@ -1,145 +0,0 @@
-within IDEAS.Airflow.Multizone.BaseClasses;
-model ReversibleDensityColumn
- "Vertical shaft with no friction and no storage of heat and mass, reversible because it can handle negative column heights"
- replaceable package Medium = IDEAS.Media.Air
- "Medium in the component"
- annotation (choices(
- choice(redeclare package Medium = IDEAS.Media.Air "Moist air")));
- parameter Modelica.Units.SI.Length h = 3 "Height of shaft";
-
- Modelica.Fluid.Interfaces.FluidPort_a port_a(
- redeclare package Medium = Medium,
- p(start=Medium.p_default))
- "Fluid connector a (positive design flow direction is from port_a to port_b)"
-annotation (Placement(transformation(extent={{-10,90},{10,110}}),
- iconTransformation(extent={{-10,90},{10,110}})));
- Modelica.Fluid.Interfaces.FluidPort_b port_b(
- redeclare package Medium = Medium,
- p(start=Medium.p_default))
- "Fluid connector b (positive design flow direction is from port_a to port_b)"
-annotation (Placement(transformation(extent={{10,-110},{-10,-90}}), iconTransformation(extent={{10,-110},{-10,-90}})));
-
- Modelica.Units.SI.VolumeFlowRate V_flow = m_flow/Medium.density(sta_b)
- "Volume flow rate at inflowing port (positive when flow from port_a to port_b)";
- Modelica.Units.SI.MassFlowRate m_flow = port_a.m_flow
- "Mass flow rate from port_a to port_b (m_flow > 0 is design flow direction)";
- Modelica.Units.SI.PressureDifference dp(displayUnit="Pa") = port_a.p - port_b.p
- "Pressure difference between port_a and port_b";
- Modelica.Units.SI.Density rho = IDEAS.Utilities.Psychrometrics.Functions.density_pTX(
- p=Medium.p_default,
- T=Medium.temperature(Medium.setState_phX(
- port_b.p,
- inStream(port_b.h_outflow),
- Xi)),
- X_w=if Medium.nXi == 0 then 0 else Xi[1])
- "Density in medium column";
-
-protected
- Medium.ThermodynamicState sta_b=Medium.setState_phX(
- port_b.p,
- actualStream(port_b.h_outflow),
- actualStream(port_b.Xi_outflow))
- "Medium properties in port_a";
- Medium.MassFraction Xi[Medium.nXi] = inStream(port_b.Xi_outflow)
- "Mass fraction used to compute density";
-
-equation
- // Pressure difference between ports
- // Xi is computed first as it is used in two expression, and in one
- // of them only one component is used.
- // We test for Medium.nXi == 0 as Modelica.Media.Air.SimpleAir has no
- // moisture and hence Xi[1] is an illegal statement.
- // We first compute temperature and then invoke a density function that
- // takes temperature as an argument. Simply calling a density function
- // of a medium that takes enthalpy as an argument would be dangerous
- // as different media can have different datum for the enthalpy.
-
- dp=-h*rho*Modelica.Constants.g_n;
-
- // Isenthalpic state transformation (no storage and no loss of energy)
- port_a.h_outflow = inStream(port_b.h_outflow);
- port_b.h_outflow = inStream(port_a.h_outflow);
-
- // Mass balance (no storage)
- port_a.m_flow + port_b.m_flow = 0;
-
- // Transport of substances
- port_a.Xi_outflow = inStream(port_b.Xi_outflow);
- port_b.Xi_outflow = inStream(port_a.Xi_outflow);
-
- port_a.C_outflow = inStream(port_b.C_outflow);
- port_b.C_outflow = inStream(port_a.C_outflow);
-
- annotation (
-Icon(graphics={
- Line(
- points={{0,100},{0,-100},{0,-98}}),
- Text(
- extent={{24,-78},{106,-100}},
- lineColor={0,0,127},
- textString="Zone/Amb"),
- Text(
- extent={{32,104},{98,70}},
- lineColor={0,0,127},
- textString="FlowElem"),
- Text(
- extent={{36,26},{88,-10}},
- lineColor={0,0,127},
- fillColor={255,0,0},
- fillPattern=FillPattern.Solid,
- textString="h=%h"),
- Rectangle(
- extent={{-16,80},{16,-80}},
- fillColor={255,0,0},
- fillPattern=FillPattern.Solid,
- pattern=LinePattern.None),
- Rectangle(
- visible=densitySelection == IDEAS.Airflow.Multizone.Types.densitySelection.fromTop,
- extent={{-16,80},{16,0}},
- fillColor={85,170,255},
- fillPattern=FillPattern.Solid,
- pattern=LinePattern.None,
- lineColor={0,0,0}),
- Rectangle(
- visible=densitySelection == IDEAS.Airflow.Multizone.Types.densitySelection.actual,
- extent={{-16,80},{16,54}},
- fillColor={85,170,255},
- fillPattern=FillPattern.Solid,
- pattern=LinePattern.None,
- lineColor={0,0,0}),
- Rectangle(
- visible=densitySelection == IDEAS.Airflow.Multizone.Types.densitySelection.fromBottom,
- extent={{-16,0},{16,-82}},
- fillColor={85,170,255},
- fillPattern=FillPattern.Solid,
- pattern=LinePattern.None,
- lineColor={0,0,0}),
- Rectangle(
- visible=densitySelection == IDEAS.Airflow.Multizone.Types.densitySelection.actual,
- extent={{-16,-55},{16,-80}},
- fillColor={85,170,255},
- fillPattern=FillPattern.Solid,
- pattern=LinePattern.None,
- lineColor={0,0,0})}),
- defaultComponentName="col",
- Documentation(info="
-
-This model describes the pressure difference of a vertical medium
-column. It can be used to model the pressure difference caused by
-stack effect.
-
-It is a variation on IDEAS.Airflow.Multizone.MediumColumn.
-
-
-",
- revisions="
-
--
-January 19, 2022, by Klaas De Jonge:
-Adapted IDEAS.Airflow.Multizone.MediumColumn to obtain the current model where input of h can be negative and cleaned out the model as the density should always be set by port_b.
-This makes port_a not nececarilly always the top port.
-
-
-
-"));
-end ReversibleDensityColumn;
diff --git a/IDEAS/Airflow/Multizone/BaseClasses/package.order b/IDEAS/Airflow/Multizone/BaseClasses/package.order
index b7c99a59a1..698bba52a4 100644
--- a/IDEAS/Airflow/Multizone/BaseClasses/package.order
+++ b/IDEAS/Airflow/Multizone/BaseClasses/package.order
@@ -3,7 +3,6 @@ DoorDiscretized
ErrorControl
PartialOneWayFlowElement
PowerLawResistanceParameters
-ReversibleDensityColumn
TwoWayFlowElement
TwoWayFlowElementBuoyancy
ZonalFlow
diff --git a/IDEAS/Airflow/Multizone/CrackOrOperableDoor.mo b/IDEAS/Airflow/Multizone/CrackOrOperableDoor.mo
new file mode 100644
index 0000000000..2614c925e7
--- /dev/null
+++ b/IDEAS/Airflow/Multizone/CrackOrOperableDoor.mo
@@ -0,0 +1,176 @@
+within IDEAS.Airflow.Multizone;
+
+model CrackOrOperableDoor
+ "Door model using discretization along height coordinate"
+ extends IDEAS.Fluid.Interfaces.PartialFourPortInterface(
+ redeclare final package Medium1 = Medium,
+ redeclare final package Medium2 = Medium,
+ final allowFlowReversal1=true,
+ final allowFlowReversal2=true,
+ final m1_flow_nominal=10/3600*1.2,
+ final m2_flow_nominal=m1_flow_nominal,
+ final m1_flow_small=1E-4*abs(m1_flow_nominal),
+ final m2_flow_small=1E-4*abs(m2_flow_nominal));
+ extends IDEAS.Airflow.Multizone.BaseClasses.ErrorControl;
+
+ replaceable package Medium =
+ Modelica.Media.Interfaces.PartialMedium "Medium in the component"
+ annotation (choices(
+ choice(redeclare package Medium = IDEAS.Media.Air "Moist air")));
+
+ parameter Modelica.Units.SI.Velocity vZer=0.001
+ "Minimum velocity to prevent zero flow. Recommended: 0.001";
+ parameter Modelica.Units.SI.Length wOpe=0.9 "Width of opening"
+ annotation (Dialog(group="Geometry"));
+ parameter Modelica.Units.SI.Length hOpe=2.1 "Height of opening"
+ annotation (Dialog(group="Geometry"));
+
+ parameter BoundaryConditions.Types.InterZonalAirFlow interZonalAirFlowType
+ "Interzonal air flow type";
+ parameter Modelica.Units.SI.PressureDifference dpCloRat(
+ min=0,
+ displayUnit="Pa") = 50 "Pressure drop at rating condition of closed door"
+ annotation (Dialog(group="Rating conditions"));
+
+ parameter Modelica.Units.SI.Length h_b1;
+ parameter Modelica.Units.SI.Length h_b2 = 0;
+ parameter Modelica.Units.SI.Length h_a1 = 0;
+ parameter Modelica.Units.SI.Length h_a2;
+
+ parameter Real CDCloRat(min=0, max=1)=1
+ "Discharge coefficient at rating conditions of closed door"
+ annotation (Dialog(group="Rating conditions"));
+ parameter Modelica.Units.SI.Area A_q50 "Surface area for leakage computation (closed door)";
+ parameter Real q50(unit="m3/(h.m2)") "Surface air tightness";
+
+ parameter Modelica.Units.SI.Area LClo(min=0) = q50*A_q50*1.2/3600 *(1.2/2/dpCloRat)^mClo/CDClo
+ "Effective leakage area of closed door"
+ annotation (Dialog(group="Closed door"));
+
+ parameter Real CDOpe=0.65 "Discharge coefficient of open door"
+ annotation (Dialog(group="Open door"));
+ parameter Real CDClo=0.65 "Discharge coefficient of closed door"
+ annotation (Dialog(group="Closed door"));
+
+ parameter Real mOpe = 0.5 "Flow exponent for door of open door"
+ annotation (Dialog(group="Open door"));
+ parameter Real mClo= 0.65 "Flow exponent for crack of closed door"
+ annotation (Dialog(group="Closed door"));
+
+ parameter Integer nCom=10 "Number of compartments for the discretization";
+
+ parameter Boolean useDoor = false "=true, to use operable door instead of a crack";
+ parameter Boolean use_y = true "=true, to use control input";
+
+ parameter Modelica.Units.SI.PressureDifference dp_turbulent(
+ min=0,
+ displayUnit="Pa") = 0.01
+ "Pressure difference where laminar and turbulent flow relation coincide. Recommended: 0.01";
+
+ Modelica.Blocks.Interfaces.RealInput y(min=0, max=1, unit="1") if useDoor and use_y
+ "Opening signal, 0=closed, 1=open"
+ annotation (Placement(transformation(extent={{-120,-10},{-100,10}}), iconTransformation(extent={{-120,-10},{-100,10}})));
+ IDEAS.Airflow.Multizone.Point_m_flow point_m_flow1(
+ redeclare package Medium = Medium,
+ dpMea_nominal = dpCloRat,
+ forceErrorControlOnFlow = false,
+ mMea_flow_nominal = (if interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts then LClo/2 else LClo)*CDClo*(2*dpCloRat/1.2)^mClo,
+ m = mClo,
+ useDefaultProperties = false) if not useDoor "Pressure drop equation" annotation(
+ Placement(visible = true, transformation(origin = {0, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.ReversibleDensityColumn col_b1(redeclare package Medium = Medium, h=h_b1) if interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts "Column for port b1" annotation(
+ Placement(visible = true, transformation(origin = {0, 70}, extent = {{50, -10}, {70, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.ReversibleDensityColumn col_a1(redeclare package Medium = Medium, h=h_a1) if interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts "Column for port a1" annotation(
+ Placement(visible = true, transformation(origin = {0, 70}, extent = {{-70, -10}, {-50, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.ReversibleDensityColumn col_b2(redeclare package Medium = Medium, h=h_b2) if interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts "Column for port b2" annotation(
+ Placement(visible = true, transformation(origin = {0, -50}, extent = {{-70, -10}, {-50, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.ReversibleDensityColumn col_a2(redeclare package Medium = Medium, h=h_a2) if interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts "Column for port a2" annotation(
+ Placement(visible = true, transformation(origin = {0, -50}, extent = {{50, -10}, {70, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.Point_m_flow point_m_flow2(
+ redeclare package Medium = Medium,
+ dpMea_nominal = dpCloRat,
+ forceErrorControlOnFlow = false,
+ m = mClo,
+ mMea_flow_nominal = LClo/2*CDClo*(2*dpCloRat/1.2)^mClo,
+ useDefaultProperties = false) if not useDoor and interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts "Pressure drop equation" annotation(
+ Placement(visible = true, transformation(origin = {0, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
+ IDEAS.Airflow.Multizone.DoorDiscretizedOperable doo(
+ redeclare package Medium = Medium,
+ final hA = 0,
+ final hB = 0,
+ final forceErrorControlOnFlow=false,
+ dp_turbulent=dp_turbulent,
+ nCom=nCom,
+ CDOpe=CDOpe,
+ CDClo=CDClo,
+ mOpe=mOpe,
+ mClo=mClo,
+ CDCloRat=CDCloRat,
+ wOpe=wOpe,
+ hOpe=hOpe,
+ dpCloRat=dpCloRat,
+ LClo=LClo,
+ vZer=vZer) if useDoor and interZonalAirFlowType == IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts annotation(
+ Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
+ IDEAS.Fluid.Sources.Boundary_pT bou(
+ redeclare package Medium = Medium,
+ nPorts = 2)
+ if interZonalAirFlowType <> IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts
+ "Sets absolute pressure when the ports are not connected externally" annotation(
+ Placement(visible = true, transformation(origin = {0, -90}, extent = {{-10, 10}, {10, -10}}, rotation = 90)));
+ Modelica.Blocks.Sources.Constant constOne(final k=1)
+ if not use_y
+ "Door constantly opened" annotation(
+ Placement(visible = true, transformation(origin = {-54, -14}, extent = {{-6, -6}, {6, 6}}, rotation = 0)));
+initial equation
+ assert( not (interZonalAirFlowType <> IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts and useDoor),
+ "In " +getInstanceName() + ": Cannot use a controllable door unless interZonalAirFlowType == TwoPorts.");
+
+equation
+ connect(col_a1.port_a, point_m_flow1.port_a) annotation(
+ Line(points = {{-60, 80}, {-60, 84}, {-20, 84}, {-20, 60}, {-10, 60}}, color = {0, 127, 255}));
+ connect(col_b1.port_a, point_m_flow1.port_b) annotation(
+ Line(points = {{60, 80}, {60, 84}, {20, 84}, {20, 60}, {10, 60}}, color = {0, 127, 255}));
+ connect(col_b2.port_a, point_m_flow2.port_a) annotation(
+ Line(points = {{-60, -40}, {-60, -36}, {-20, -36}, {-20, -60}, {-10, -60}}, color = {0, 127, 255}));
+ connect(col_a2.port_a, point_m_flow2.port_b) annotation(
+ Line(points = {{60, -40}, {60, -36}, {20, -36}, {20, -60}, {10, -60}}, color = {0, 127, 255}));
+ connect(col_b2.port_b, port_b2) annotation(
+ Line(points = {{-60, -60}, {-100, -60}}, color = {0, 127, 255}));
+ connect(col_a2.port_b, port_a2) annotation(
+ Line(points = {{60, -60}, {100, -60}}, color = {0, 127, 255}));
+ connect(col_b1.port_b, port_b1) annotation(
+ Line(points = {{60, 60}, {100, 60}}, color = {0, 127, 255}));
+ connect(col_a1.port_b, port_a1) annotation(
+ Line(points = {{-60, 60}, {-100, 60}}, color = {0, 127, 255}));
+ connect(y, doo.y) annotation(
+ Line(points = {{-110, 0}, {-10, 0}}, color = {0, 0, 127}));
+ connect(doo.port_a1, col_a1.port_a) annotation(
+ Line(points = {{-10, 6}, {-20, 6}, {-20, 84}, {-60, 84}, {-60, 80}}, color = {0, 127, 255}));
+ connect(doo.port_b1, col_b1.port_a) annotation(
+ Line(points = {{10, 6}, {20, 6}, {20, 84}, {60, 84}, {60, 80}}, color = {0, 127, 255}));
+ connect(doo.port_b2, col_b2.port_a) annotation(
+ Line(points = {{-10, -6}, {-20, -6}, {-20, -36}, {-60, -36}, {-60, -40}}, color = {0, 127, 255}));
+ connect(doo.port_a2, col_a2.port_a) annotation(
+ Line(points = {{10, -6}, {20, -6}, {20, -36}, {60, -36}, {60, -40}}, color = {0, 127, 255}));
+ connect(bou.ports[1], port_a2) annotation(
+ Line(points = {{0, -80}, {100, -80}, {100, -60}}, color = {0, 127, 255}));
+ if interZonalAirFlowType <> IDEAS.BoundaryConditions.Types.InterZonalAirFlow.TwoPorts then
+ connect(point_m_flow1.port_a, port_a1) annotation(
+ Line(points = {{-10, 60}, {-100, 60}}, color = {0, 127, 255}));
+ connect(point_m_flow1.port_b, port_b1) annotation(
+ Line(points = {{10, 60}, {100, 60}}, color = {0, 127, 255}));
+ connect(doo.port_b1, port_b1) annotation(
+ Line(points = {{10, 6}, {20, 6}, {20, 60}, {100, 60}}, color = {0, 127, 255}));
+ connect(doo.port_a1, port_a1) annotation(
+ Line(points = {{-10, 6}, {-20, 6}, {-20, 60}, {-100, 60}}, color = {0, 127, 255}));
+ end if;
+ connect(constOne.y, doo.y) annotation(
+ Line(points = {{-48, -14}, {-32, -14}, {-32, 0}, {-10, 0}}, color = {0, 0, 127}));
+ connect(bou.ports[2], port_b2) annotation(
+ Line(points = {{0, -80}, {-100, -80}, {-100, -60}}, color = {0, 127, 255}));
+
+annotation(
+ Diagram,
+ Icon(graphics = {Polygon(lineColor = {0, 0, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-30, -10}, {-16, -8}, {-16, -14}, {-30, -16}, {-30, -10}}), Line(points = {{-54, 48}, {-36, 48}}), Line(points = {{-54, 20}, {-36, 20}}), Rectangle(fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-100, 100}, {100, -100}}), Line(points = {{-54, -58}, {-36, -58}}), Rectangle(lineColor = {0, 0, 255}, fillColor = {255, 128, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-46, -16}, {-20, -20}}), Rectangle(lineColor = {0, 0, 255}, fillColor = {85, 75, 55}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-60, 80}, {60, -84}}), Rectangle(fillColor = {215, 215, 215}, fillPattern = FillPattern.Solid, extent = {{-54, 72}, {56, -84}}), Polygon(fillColor = {95, 95, 95}, fillPattern = FillPattern.Solid, points = {{56, 72}, {-36, 66}, {-36, -90}, {56, -84}, {56, 72}}), Rectangle(lineColor = {0, 0, 255}, fillColor = {255, 128, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-100, 2}, {-46, -2}}), Polygon(visible = false, origin = {75, 50}, rotation = 360, lineColor = {0, 128, 255}, fillColor = {0, 128, 255}, fillPattern = FillPattern.Solid, points = {{-5, 10}, {25, 10}, {-5, -10}, {-5, 10}}), Text(textColor = {0, 0, 127}, extent = {{-118, 34}, {-98, 16}}, textString = "y"), Line(points = {{-54, -6}, {-36, -6}}), Line(points = {{-54, -32}, {-36, -32}}), Polygon(visible = false, origin = {-79, -50}, rotation = 360, lineColor = {0, 128, 255}, fillColor = {0, 128, 255}, fillPattern = FillPattern.Solid, points = {{10, 10}, {-20, -10}, {10, -10}, {10, 10}}), Rectangle(lineColor = {0, 0, 255}, fillColor = {255, 128, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-46, 2}, {-40, -16}})}, coordinateSystem(extent = {{-100, -100}, {100, 100}})));
+end CrackOrOperableDoor;
\ No newline at end of file
diff --git a/IDEAS/Airflow/Multizone/Examples/TrickleVentIDEAS.mo b/IDEAS/Airflow/Multizone/Examples/TrickleVentIDEAS.mo
new file mode 100644
index 0000000000..b7b4982b02
--- /dev/null
+++ b/IDEAS/Airflow/Multizone/Examples/TrickleVentIDEAS.mo
@@ -0,0 +1,53 @@
+within IDEAS.Airflow.Multizone.Examples;
+model TrickleVentIDEAS
+ "Model with a trickle vent modelled using the models with flow based on tabulated data"
+ extends IDEAS.Airflow.Multizone.Examples.TrickleVent(west(nPorts=2), east(nPorts=2));
+
+ IDEAS.Airflow.Multizone.TrickleVent vent(
+ redeclare package Medium = Medium,
+ dp_nominal = 10,
+ m_flow_nominal = 0.02614,
+ use_y = true)
+ "Analytic trickle vent implementation" annotation(
+ Placement(visible = true, transformation(origin = {20, -70}, extent = {{-10, 10}, {10, -10}}, rotation = 0)));
+ Modelica.Blocks.Sources.Ramp ramp(
+ duration = 1e6,
+ height = -1,
+ offset = 1,
+ startTime = 1592000)
+ "Step control signal" annotation(
+ Placement(visible = true, transformation(origin = {-90, -88}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
+equation
+ connect(vent.port_a, east.ports[2]) annotation(
+ Line(points = {{10, -70}, {-25, -70}, {-25, -30}, {-30, -30}}, color = {0, 127, 255}));
+ connect(vent.port_b, west.ports[2]) annotation(
+ Line(points = {{30, -70}, {65, -70}, {65, -30}, {70, -30}}, color = {0, 127, 255}));
+ connect(ramp.y, vent.y) annotation(
+ Line(points = {{-79, -88}, {20.5, -88}, {20.5, -82}, {20, -82}}, color = {0, 0, 127}));
+ annotation (__Dymola_Commands(file="modelica://IDEAS/Resources/Scripts/Dymola/Airflow/Multizone/Examples/TrickleVentIDEAS.mos"
+ "Simulate and plot"),
+ experiment(
+ StopTime=2592000,
+ Interval=600,
+ Tolerance=1e-06),
+ Documentation(info="
+
+This model illustrates the use of the models
+
+IDEAS.Airflow.Multizone.Table_V_flow,
+which is an analytic alternative to the table implementation of
+
+IDEAS.Airflow.Multizone.Table_m_flow for
+
+modelling self regulating inlet vents.
+
+", revisions="
+
+-
+July 9, 2023 by Filip Jorissen:
+First implementation.
+
+
+"),
+ Diagram);
+end TrickleVentIDEAS;
\ No newline at end of file
diff --git a/IDEAS/Airflow/Multizone/Examples/package.order b/IDEAS/Airflow/Multizone/Examples/package.order
index 162a3ed47f..9940a37007 100644
--- a/IDEAS/Airflow/Multizone/Examples/package.order
+++ b/IDEAS/Airflow/Multizone/Examples/package.order
@@ -12,4 +12,5 @@ PressurizationData
ReverseBuoyancy
ReverseBuoyancy3Zones
TrickleVent
+TrickleVentIDEAS
ZonalFlow
diff --git a/IDEAS/Airflow/Multizone/ReversibleDensityColumn.mo b/IDEAS/Airflow/Multizone/ReversibleDensityColumn.mo
new file mode 100644
index 0000000000..1a9f81f9e8
--- /dev/null
+++ b/IDEAS/Airflow/Multizone/ReversibleDensityColumn.mo
@@ -0,0 +1,44 @@
+within IDEAS.Airflow.Multizone;
+model ReversibleDensityColumn
+ "Vertical shaft with no friction and no storage of heat and mass, reversible because it can handle negative column heights"
+
+ extends IDEAS.Airflow.Multizone.MediumColumn(
+ h(min=-Modelica.Constants.inf),
+ final densitySelection = IDEAS.Airflow.Multizone.Types.densitySelection.fromBottom);
+ // by convention, port_b must be connected to a zone instead of a flow element
+ // h is allowed to be negative to accomodate for this convention
+
+ annotation (
+Icon(graphics={
+ Line(
+ points={{0,100},{0,-100},{0,-98}}),
+ Text(origin = {-126, 2},lineColor = {0, 0, 127}, extent = {{24, -78}, {106, -100}}, textString = "Zone/Amb"),
+ Text(origin = {-130, 4}, lineColor = {0, 0, 127}, extent = {{32, 104}, {98, 70}}, textString = "FlowElem"),
+ Text(lineColor = {0, 0, 127}, extent = {{36, 26}, {88, -10}}, textString = "h=%h"),
+ Rectangle(fillColor = {255, 0, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-16, 80}, {16, -80}}),
+ Rectangle(visible = false, fillColor = {85, 170, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-16, 80}, {16, 0}}),
+ Rectangle(visible = false, fillColor = {85, 170, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-16, 80}, {16, 54}}),
+ Rectangle(fillColor = {85, 170, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-16, 0}, {16, -82}}),
+ Rectangle(visible = false, fillColor = {85, 170, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-16, -55}, {16, -80}})}),
+ defaultComponentName="col",
+ Documentation(info="
+
+This model describes the pressure difference of a vertical medium
+column. It can be used to model the pressure difference caused by
+stack effect.
+
+It is a variation on IDEAS.Airflow.Multizone.MediumColumn.
+
+
+",
+ revisions="
+
+-
+January 19, 2022, by Klaas De Jonge:
+Adapted IDEAS.Airflow.Multizone.MediumColumn to obtain the current model where input of h can be negative and cleaned out the model as the density should always be set by port_b.
+This makes port_a not nececarilly always the top port.
+
+
+
+"));
+end ReversibleDensityColumn;
\ No newline at end of file
diff --git a/IDEAS/Airflow/Multizone/TrickleVent.mo b/IDEAS/Airflow/Multizone/TrickleVent.mo
index 0a7ba4b9eb..74bcaa31e8 100644
--- a/IDEAS/Airflow/Multizone/TrickleVent.mo
+++ b/IDEAS/Airflow/Multizone/TrickleVent.mo
@@ -5,15 +5,21 @@ model TrickleVent "Self regulating trickle vent"
final from_dp=true,
final homotopyInitialization=true);
+ parameter Real l(min=1e-10, max=1) = 0.0001
+ "Valve leakage, l=Kv(y=0)/Kv(y=1)";
parameter Real deltaM(min=1E-6) = 0.3
"Fraction of nominal mass flow rate where transition to turbulent occurs"
annotation(Evaluate=true,
Dialog(group = "Transition to laminar",
enable = not linearized));
-
+ parameter Boolean use_y = false
+ "=true, to enable control input"
+ annotation(Evaluate=true, Dialog(group="Control"));
final parameter Real k = if computeFlowResistance then
m_flow_nominal_pos / sqrt(dp_nominal_pos) else 0
"Flow coefficient, k=m_flow/sqrt(dp), with unit=(kg.m)^(1/2)";
+ Modelica.Blocks.Interfaces.RealInput y(min=0,max=1) if use_y "Control input for trickle vent Kv value" annotation(
+ Placement(visible = true, transformation(origin = {0, 120}, extent = {{-20, -20}, {20, 20}}, rotation = -90), iconTransformation(origin = {0, 120}, extent = {{-20, -20}, {20, 20}}, rotation = -90)));
protected
final parameter Boolean computeFlowResistance=(dp_nominal_pos > Modelica.Constants.eps)
"Flag to enable/disable computation of flow resistance"
@@ -23,6 +29,7 @@ protected
then if from_dp then k^2/m_flow_nominal_pos else m_flow_nominal_pos/k^2
else 0
"Precomputed coefficient to avoid division by parameter";
+ Modelica.Blocks.Interfaces.RealInput y_internal "Internal variable for conditional variables";
initial equation
if computeFlowResistance then
assert(m_flow_turbulent > 0, "m_flow_turbulent must be bigger than zero.");
@@ -30,6 +37,10 @@ initial equation
assert(m_flow_nominal_pos > 0, "m_flow_nominal_pos must be non-zero. Check parameters.");
equation
+ connect(y, y_internal);
+ if not use_y then
+ y_internal = 1;
+ end if;
// Pressure drop calculation
if computeFlowResistance then
if linearized then
@@ -40,7 +51,7 @@ equation
m_flow_nominal,
IDEAS.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp(
dp=dp,
- k=k,
+ k=k*(l + (1-l)*y_internal),
m_flow_turbulent=m_flow_turbulent),
m_flow_nominal/10);
end if; // linearized
@@ -56,12 +67,20 @@ The positive mass flow rate is limited to m_flow_nominal
at a pressure difference of dp_nominal.
For negative pressure differences the mass flow rate is not limited.
+
+An optional control input can be enabled, which reduces the flow rate for the same
+pressure difference, but which does not affect the maximum flow rate.
+