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

Issue3618 air filter #3676

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
4c1f2ae
first implementation
Dec 27, 2023
ca8b5fe
cleanup
Dec 28, 2023
5422c41
add OM scripts
Dec 28, 2023
f1557a8
update the plot script
Dec 28, 2023
526d305
reference data generation
Dec 28, 2023
5c410d4
improve model doc
Dec 29, 2023
4702143
model restruct
Jan 11, 2024
763d5d2
model doc update
Jan 14, 2024
b0477ad
update release note
Jan 14, 2024
7ddd341
Merge pull request #3620 from SenHuang19/issue3618_airFilter
JayHuLBL Mar 1, 2024
083dc1f
Merge branch 'master' into issue3618_airFilter
JayHuLBL Mar 1, 2024
27d9538
deleted invalid word [ci skip]
JayHuLBL Mar 1, 2024
8e2a608
refactored formatting
JayHuLBL Mar 1, 2024
d3f0636
fixed validation folder
JayHuLBL Mar 1, 2024
87e5370
improved graphic arrangement
JayHuLBL Mar 1, 2024
2602d9c
corrected release note
JayHuLBL Mar 4, 2024
033ac22
merged master
JayHuLBL Apr 10, 2024
0a6a806
changed connector name
JayHuLBL Apr 10, 2024
0be4dbb
improved text [ci skip]
JayHuLBL Apr 10, 2024
54cc4a6
merged master
JayHuLBL Apr 12, 2024
e37292a
add asserts
SenHuang19 Apr 15, 2024
1b6cbae
format update
SenHuang19 Apr 16, 2024
92fe476
Merge pull request #3807 from SenHuang19/issue3618_airFilter
JayHuLBL Apr 19, 2024
f7c67ee
improved text and documentation
JayHuLBL Apr 19, 2024
ed0bd65
added variable in reference results
JayHuLBL Apr 19, 2024
2a98e8a
refactoring and adding an example
SenHuang19 Aug 26, 2024
5d10a8e
script update
SenHuang19 Aug 26, 2024
6c49dab
example update
SenHuang19 Sep 2, 2024
63142ce
ref dataset update
SenHuang19 Sep 2, 2024
db1b8b0
model doc update and small issues fix
SenHuang19 Sep 2, 2024
021d6b7
model doc improve
SenHuang19 Sep 3, 2024
a11b196
typos fix
SenHuang19 Sep 4, 2024
7e1f587
minor fix
SenHuang19 Sep 4, 2024
07ad4e9
minor doc update
SenHuang19 Sep 25, 2024
f649536
model doc enhance and move the per to the top level class
Nov 8, 2024
d3a9dfe
model doc improve
Nov 11, 2024
5fd768e
eliminate unnecessary calculations
Nov 12, 2024
2f7c2f2
minor model doc update
Nov 13, 2024
b731d7a
update the file name
Nov 13, 2024
d53922b
fix typo
Nov 13, 2024
929e92b
Merge pull request #3986 from SenHuang19/issue3618_airFilter
JayHuLBL Nov 20, 2024
2a5e2c1
merged master
JayHuLBL Nov 20, 2024
18e0ad8
corrected package order
JayHuLBL Nov 20, 2024
c70d36a
updated reference
JayHuLBL Nov 20, 2024
53a0558
Deleted openmodelica script
JayHuLBL Nov 20, 2024
e746684
improved code
JayHuLBL Jan 2, 2025
2c71507
move all the paras to the dataset
Jan 10, 2025
01cdd28
model doc update and package restructure
Jan 15, 2025
5cc2922
refer result update
Jan 15, 2025
fc585cd
clean up
Jan 16, 2025
6cc13a9
fix typo
Jan 16, 2025
0d724ec
model doc update
Jan 16, 2025
0073880
Merge pull request #4095 from SenHuang19/issue3618_airFilter
JayHuLBL Jan 17, 2025
a59aa8f
corrected package order
JayHuLBL Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions Buildings/Fluid/AirFilters/BaseClasses/FiltrationEfficiency.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
within Buildings.Fluid.AirFilters.BaseClasses;
model FiltrationEfficiency
"Component that calculates the filtration efficiency"

parameter Real mCon_nominal(
final unit = "kg")
"Maximum mass of the contaminant that can be captured by the filter";
parameter String namCon[:]={"CO2"}
"Name of trace substance";
parameter
Buildings.Fluid.AirFilters.Data.Characteristics.FiltrationEfficiencyParameters
filEffPar
"Filtration efficiency versus relative mass of the contaminant";
Buildings.Controls.OBC.CDL.Interfaces.RealInput mCon(
final unit="kg")
"Mass of the contaminant captured by the filter"
annotation (Placement(transformation(extent={{-140,-20},{-100,20}})));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput y[nConSub](
each final unit="1",
each final min=0,
each final max=1)
"Filtration efficiency of each contaminant"
annotation (Placement(transformation(extent={{100,-80},{140,-40}})));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput rat(
final unit="1",
Copy link
Contributor Author

@JayHuLBL JayHuLBL Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this class, the rat is a scale variable, while in class Buildings.Fluid.AirFilters.BaseClasses.Characteristics.FiltrationEfficiencyParameters, the rat is a vector. Are they same or different?
Through commit e746684, I removed each declaration. Is it a correct change? As in Modelica, each should only be used by the vector variable declaration.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buildings.Fluid.AirFilters.BaseClasses.FilterationEfficiency defines rat while in Buildings.Fluid.AirFilters.BaseClasses.Characteristics.FiltrationEfficiencyParameters, we declare a list of rat and each rat corresponds to a specific type of containment. Should I rename the rat in Buildings.Fluid.AirFilters.BaseClasses.Characteristics.FiltrationEfficiencyParameters to avoid confusions?

final min=0,
final max=1)
"Relative mass of the contaminant captured by the filter"
annotation (Placement(transformation(extent={{100,40},{140,80}})));
protected
parameter Integer nConSub = size(namCon,1)
"Total types of contaminant substances";
equation
rat = Buildings.Utilities.Math.Functions.smoothMin(
x1=1,
x2= mCon/mCon_nominal,
deltaX=0.1)
"Calculate the relative mass of the contaminant captured by the filter";
for i in 1:nConSub loop
y[i] = Buildings.Utilities.Math.Functions.smoothInterpolation(
x=rat,
xSup=filEffPar.rat[i],
ySup=filEffPar.eps[i])
"Calculate the filtration efficiency";
end for;
annotation (Icon(coordinateSystem(preserveAspectRatio=false), graphics={
Rectangle(
extent={{-100,100},{100,-100}},
lineColor={28,108,200},
fillColor={255,255,255},
fillPattern=FillPattern.Solid),
Text(
extent={{-100,140},{100,100}},
textColor={0,0,255},
textString="%name")}),
Diagram(coordinateSystem(preserveAspectRatio=false)),
defaultComponentName="eps",
Documentation(info="<html>
<p>
This model calculates the filtration efficiency, <i>eps</i>, using cubic Hermite spline interpolation of
the filter dataset (see
<a href=\"modelica://Buildings.Fluid.AirFilters.Data.Characteristics.filtrationEfficiencyParameters\">
Buildings.Fluid.AirFilters.Data.Characteristics.filtrationEfficiencyParameters</a>)
with respect to <i>rat</i>.
</p>
<p>
The <i>rat</i> is the relative mass of the contaminant that is captured by the filter,
and is calculated by
</p>
<p align=\"center\" style=\"font-style:italic;\">
rat = mCon/mCon_nominal,
</p>
<p>
where <i>mCon</i> is the mass of the contaminant that is captured by the filter, and
<i>mCon_nominal</i> is the filter's maximum contaminant capacity.
</p>
<P>
<b>Note:</b>
The upper limit of <i>rat</i> is 1 and any value exceeding 1 will be capped at 1.
</p>
</html>", revisions="<html>
<ul>
<li>
December 22, 2023, by Sen Huang:<br/>
First implementation.
</li>
</ul>
</html>"));
end FiltrationEfficiency;
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
within Buildings.Fluid.AirFilters.BaseClasses;
model FlowCoefficientCorrection
"Component that calculates the flow coefficient correction factor"
parameter Real b=1.1
"Resistance coefficient";
Buildings.Controls.OBC.CDL.Interfaces.RealInput rat(
final unit="1",
final min=0,
final max=1)
"Relative mass of the contaminant captured by the filter"
annotation (Placement(transformation(extent={{-140,-20},{-100,20}})));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput y(
final unit="1",
final min=1)
"Flow coefficient correction"
annotation (Placement(transformation(extent={{100,-20},{140,20}})));
initial equation
assert(b-1.0>0.01,
"In " + getInstanceName() + ":The resistance coefficient must be larger
than 1",
level = AssertionLevel.error)
"Validate the resistance coefficient";
equation
y=b^rat;

annotation (defaultComponentName="coeCor",
Icon(coordinateSystem(preserveAspectRatio=false), graphics={
Rectangle(
extent={{-100,100},{100,-100}},
lineColor={28,108,200},
fillColor={255,255,255},
fillPattern=FillPattern.Solid),
Text(
extent={{-100,140},{100,100}},
textColor={0,0,255},
textString="%name")}),
Diagram(coordinateSystem(preserveAspectRatio=false)),
Documentation(info="<html>
<p>
This model calculates the flow coefficient of the filter by
</p>
<p align=\"center\" style=\"font-style:italic;\">
kCor = b<sup>rat</sup>,
</p>
<p>
where <code>b</code> is the resistance coefficient and it must be greater than 1,
<code>rat</code> is the relative mass of the contaminant that is captured by the filter
(see descriptions in
<a href=\"modelica://Buildings.Fluid.AirFilters.BaseClasses.FiltrationEfficiency\">
Buildings.Fluid.AirFilters.BaseClasses.FiltrationEfficiency</a>).
</p>
<h4>References</h4>
<p>
Qiang Li ta al., (2022). Experimental study on the synthetic dust loading characteristics of air filters.
Separation and Purification Technology 284 (2022), 120209.
</p>
</html>", revisions="<html>
<ul>
<li>
December 22, 2023, by Sen Huang:<br/>
First implementation.
</li>
</ul>
</html>"));
end FlowCoefficientCorrection;
87 changes: 87 additions & 0 deletions Buildings/Fluid/AirFilters/BaseClasses/MassAccumulation.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
within Buildings.Fluid.AirFilters.BaseClasses;
model MassAccumulation
"Component that mimics the accumulation of the contaminants"
parameter Integer nConSub(
final min=1)=1
"Total number of contaminant substance types";
parameter Real mCon_nominal(
final unit = "kg")
"Maximum mass of the contaminant that can be captured by the filter";
parameter Real mCon_reset(
final min = 0)
"Initial contaminant mass of the filter after replacement";
Buildings.Controls.OBC.CDL.Interfaces.RealInput mCon_flow[nConSub](
each final unit="kg/s")
"Contaminant mass flow rate"
annotation (Placement(transformation(extent={{-140,-20},{-100,20}})));
Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uRep
"Replacing the filter when trigger becomes true"
annotation (Placement(transformation(extent={{-140,-80},{-100,-40}})));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon(
final unit = "kg")
"Mass of the contaminant captured by the filter"
annotation (Placement(transformation(extent={{100,-20},{140,20}})));
Buildings.Controls.OBC.CDL.Reals.IntegratorWithReset intWitRes(
final k=1,
final y_start=mCon_reset)
"Calculate the mass of contaminant"
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
final k=mCon_reset)
"Constant"
annotation (Placement(transformation(extent={{-80,-30},{-60,-10}})));
Modelica.Blocks.Logical.Greater greater
"Check if the filter is full"
annotation (Placement(transformation(extent={{40,40},{60,60}})));
Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(
final k=mCon_nominal)
"Constant"
annotation (Placement(transformation(extent={{-20,40},{0,60}})));
Buildings.Controls.OBC.CDL.Utilities.Assert assMes(
final message="In " + getInstanceName() + ": The filter needs to be replaced.")
"Warning message when the filter is full"
annotation (Placement(transformation(extent={{72,40},{92,60}})));
Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum(
final nin=nConSub) "Summation of the inputs"
annotation (Placement(transformation(extent={{-52,-10},{-32,10}})));
equation
connect(intWitRes.y, mCon)
annotation (Line(points={{12,0},{120,0}}, color={0,0,127}));
connect(con.y, intWitRes.y_reset_in)
annotation (Line(points={{-58,-20},{-20,-20}, {-20,-8},{-12,-8}}, color={0,0,127}));
connect(intWitRes.trigger, uRep)
annotation (Line(points={{0,-12},{0,-60},{-120,-60}}, color={255,0,255}));
connect(assMes.u, greater.y)
annotation (Line(points={{70,50},{61,50}}, color={255,0,255}));
connect(greater.u2, intWitRes.y)
annotation (Line(points={{38,42},{20,42},{20,0},{12,0}}, color={0,0,127}));
connect(con1.y, greater.u1)
annotation (Line(points={{2,50},{38,50}}, color={0,0,127}));
connect(mulSum.y, intWitRes.u)
annotation (Line(points={{-30,0},{-12,0}}, color={0,0,127}));
connect(mulSum.u, mCon_flow)
annotation (Line(points={{-54,0},{-120,0}}, color={0,0,127}));
annotation (Placement(transformation(extent={{20,62},{40,82}})),
defaultComponentName="masAcc",
Icon(coordinateSystem(preserveAspectRatio=false), graphics={
Rectangle(extent={{-100,100},{100,-100}}, lineColor={28,108,200},
fillColor={255,255,255}, fillPattern=FillPattern.Solid),
Text(extent={{-100,140},{100,100}}, textColor={0,0,255}, textString="%name")}),
Diagram(coordinateSystem(preserveAspectRatio=false)),
Documentation(info="<html>
<p>
This model mimics the process for a filter to capture the contaminants.
The mass of the contaminants, <code>mCon</code>, increases by time.
However, when the input signal <code>uRep</code> changes from <code>false</code>
to <code>true</code>, <code>mCon</code> is reset to a constant, <code>mCon_reset</code>.
</p>
</html>", revisions="<html>
<ul>
<li>
December 22, 2023, by Sen Huang:<br/>
First implementation.
</li>
</ul>
</html>"));

end MassAccumulation;
97 changes: 97 additions & 0 deletions Buildings/Fluid/AirFilters/BaseClasses/MassTransfer.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
within Buildings.Fluid.AirFilters.BaseClasses;
model MassTransfer
"Component that sets the trace substance at port_b based on an input trace substance mass flow rate and an input mass transfer efficiency"
extends Buildings.Fluid.Interfaces.PartialTwoPortInterface;
parameter String namCon[:]={"CO2"}
"Name of trace substance";
Buildings.Controls.OBC.CDL.Interfaces.RealInput eps[nConSub](
each final unit = "1",
each final min = 0,
each final max= 1)
"Mass transfer coefficient"
annotation (Placement(transformation(extent={{-140,40},{-100,80}})));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon_flow[nConSub](
each final unit = "kg/s")
"Contaminant mass flow rate"
annotation (Placement(transformation(extent={{100,40},{140,80}})));

protected
parameter Integer nConSub=size(namCon,1)
"Total types of contaminant substances";
parameter Real s[:,:]={
{if (Modelica.Utilities.Strings.isEqual(string1=Medium.extraPropertiesNames[i],
string2=namCon[j],
caseSensitive=false))
then 1 else 0 for i in 1:nConSub}
for j in 1:Medium.nC}
"Vector to check if the trace substances in the medium are included in the performance dataset"
annotation(Evaluate=true);
initial equation
assert(abs(sum(s) - nConSub) < 0.1,
"In " + getInstanceName() + ":Some specified trace substances are
not present in medium '" + Medium.mediumName + "'.\n"
+ "Check filter parameter and medium model.",
level = AssertionLevel.warning)
"Check if all the specified substances are included in the medium";

equation
// Modify the substances individually.
for i in 1:Medium.nC loop
if max(s[i]) > 0.9 then
for j in 1:nConSub loop
if s[i,j]>0.9 then
port_b.C_outflow[i]=inStream(port_a.C_outflow[i])*(1 - eps[j] * s[i,j]);
port_a.C_outflow[i]=inStream(port_a.C_outflow[i]);
mCon_flow[j]=inStream(port_a.C_outflow[j])* eps[j];
end if;
end for;
else
port_b.C_outflow[i]=inStream(port_a.C_outflow[i]);
port_a.C_outflow[i]=inStream(port_b.C_outflow[i]);
end if;
end for;
// Mass balance (no storage).
port_a.Xi_outflow=inStream(port_b.Xi_outflow);
port_b.Xi_outflow=inStream(port_a.Xi_outflow);
port_a.m_flow =-port_b.m_flow;
// Pressure balance (no pressure drop).
port_a.p=port_b.p;
// Energy balance (no heat exchange).
port_a.h_outflow=inStream(port_b.h_outflow);
port_b.h_outflow=inStream(port_a.h_outflow);

if not allowFlowReversal then
assert(m_flow>-m_flow_small,
"In " + getInstanceName() + ": Reverting flow occurs even though allowFlowReversal is false.",
level=AssertionLevel.error);
end if;

annotation (defaultComponentName="masTra",
Icon(coordinateSystem(preserveAspectRatio=false), graphics={
Rectangle(extent={{-100,100},{100,-100}}, fillColor={255,255,255},
fillPattern=FillPattern.Solid, pattern=LinePattern.None)}),
Diagram(coordinateSystem(preserveAspectRatio=false)),
Documentation(info="<html>
<p>
This model sets the trace substance
of the medium that leaves <code>port_b</code> by
</p>
<pre>
port_b.C_outflow = inStream(port_a.C_outflow) - eps * C_inflow;
</pre>
<p>
where <code>eps</code> is an input mass transfer efficiency and
<code>C_inflow</code> is an input trace substance rate.
</p>
<p>
This model has no pressure drop.
</p>
</html>", revisions="<html>
<ul>
<li>
December 22, 2023, by Sen Huang:<br/>
First implementation.
</li>
</ul>
</html>"));
end MassTransfer;
Loading