Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ model PartialEffectivenessNTU
final parameter Real NTU_nominal(min=0, fixed=false)
"Nominal number of transfer units";

Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime(fixed=false, start=flowRegime_nominal)
"Heat exchanger flow regime";

protected
final parameter Medium1.ThermodynamicState sta1_default = Medium1.setState_pTX(
T=Medium1.T_default,
Expand Down Expand Up @@ -85,8 +88,10 @@ protected
"Nominal temperature at port b2";
parameter Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime_nominal(fixed=false)
"Heat exchanger flow regime at nominal flow rates";
Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime(fixed=false, start=flowRegime_nominal)
"Heat exchanger flow regime";

parameter Real mPro_flow_nominal(unit="kg.kg/(s.s)") = m1_flow_nominal*m2_flow_nominal
"Product of nominal mass flow rates, used for scaling";

initial equation
assert(m1_flow_nominal > Modelica.Constants.eps,
"m1_flow_nominal must be positive, m1_flow_nominal = " + String(
Expand Down Expand Up @@ -156,25 +161,46 @@ initial equation
Z=Z_nominal,
flowRegime=Integer(flowRegime_nominal)) else 0;
UA_nominal = NTU_nominal*CMin_flow_nominal;
equation
// Assign the flow regime for the given heat exchanger configuration and capacity flow rates
if use_dynamicFlowRegime then
if (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) then
flowRegime = if (C1_flow*C2_flow >= 0) then Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow else Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) then
flowRegime = if (C1_flow*C2_flow >= 0) then Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow else Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowUnmixed) then
flowRegime = Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowUnmixed;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) then
flowRegime = if (C1_flow < C2_flow) then Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed
else Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed;
else
// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed)
flowRegime = if (C1_flow < C2_flow) then Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed
else Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed;
end if;
else
flowRegime = flowRegime_nominal;

flowRegime = flowRegime_nominal;

algorithm
// Assign the flow regime for the given heat exchanger configuration and
// mass flow rates

// ParallelFlow vs CounterFlow
when(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) and
flowRegime==flowRegime_nominal and (m1_flow*m2_flow/mPro_flow_nominal < -0.001)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) and
flowRegime==Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow and (m1_flow*m2_flow/mPro_flow_nominal > 0.001)) then
flowRegime := flowRegime_nominal;

// CounterFlow vs ParallelFlow
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) and
flowRegime == flowRegime_nominal and (m1_flow*m2_flow/mPro_flow_nominal < -0.001)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) and
flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow and (m1_flow*m2_flow/mPro_flow_nominal > 0.001)) then
flowRegime := flowRegime_nominal;

// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed)
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) and
flowRegime == flowRegime_nominal and (C1_flow < 0.95*C2_flow)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) and
(flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed and (C1_flow > 1.05*C2_flow))) then
flowRegime := flowRegime_nominal;
// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed)
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed) and
flowRegime == flowRegime_nominal and (C1_flow < 0.95*C2_flow)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed) and
(flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed and (C1_flow > 1.05*C2_flow))) then
flowRegime := flowRegime_nominal;
end when;

if not use_dynamicFlowRegime then
assert(noEvent(m1_flow > -0.1 * m1_flow_nominal)
and noEvent(m2_flow > -0.1 * m2_flow_nominal),
"*** Warning in " + getInstanceName() +
Expand All @@ -187,6 +213,7 @@ equation
level = AssertionLevel.warning);
end if;

equation
// Effectiveness
eps = Buildings.Fluid.HeatExchangers.BaseClasses.epsilon_C(
UA=UA,
Expand Down Expand Up @@ -251,6 +278,12 @@ for <code>UA</code>.
</html>", revisions="<html>
<ul>
<li>
March 7, 2026, by Michael Wetter:<br/>
Corrected implementation of switch of flow regime.<br/>
This is for
<a href=\"https://github.com/ibpsa/modelica-ibpsa/issues/2086\">IBPSA, #2086</a>.
</li>
<li>
February 7, 2025, by Jelger Jansen:<br/>
Removed <code>import</code> statement.
This is for
Expand Down
86 changes: 51 additions & 35 deletions Buildings/Fluid/HeatExchangers/WetCoilEffectivenessNTU.mo
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ model WetCoilEffectivenessNTU

parameter Buildings.Fluid.Types.HeatExchangerConfiguration configuration=
Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow
"Heat exchanger configuration";
"Heat exchanger configuration"
annotation(Evaluate=true);
parameter Real r_nominal=2/3
"Ratio between air-side and water-side convective heat transfer coefficient";

Expand Down Expand Up @@ -77,6 +78,9 @@ model WetCoilEffectivenessNTU
Real dryFra(final unit="1", min=0, max=1) = dryWetCalcs.dryFra
"Dry fraction, 0.3 means condensation occurs at 30% heat exchange length from air inlet";

Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime(fixed=false, start=flowRegime_nominal)
"Heat exchanger flow regime";

protected
final parameter Modelica.Units.SI.MassFraction X_w_a2_nominal=w_a2_nominal/(1
+ w_a2_nominal)
Expand Down Expand Up @@ -219,8 +223,6 @@ protected
"Index of water";
parameter Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime_nominal(fixed=false)
"Heat exchanger flow regime at nominal flow rates";
Buildings.Fluid.Types.HeatExchangerFlowRegime flowRegime(fixed=false, start=flowRegime_nominal)
"Heat exchanger flow regime";

Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
"Prescribed heat flow"
Expand Down Expand Up @@ -281,6 +283,9 @@ protected
p=Medium2.p_default,
X=Medium2.X_default[1:Medium2.nXi]) "Default state for medium 2";

parameter Real mPro_flow_nominal(unit="kg.kg/(s.s)") = m1_flow_nominal*m2_flow_nominal
"Product of nominal mass flow rates, used for scaling";

initial equation
assert(m1_flow_nominal > Modelica.Constants.eps,
"m1_flow_nominal must be positive, m1_flow_nominal = " + String(
Expand Down Expand Up @@ -318,41 +323,45 @@ initial equation
configuration <= Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed,
"Invalid heat exchanger configuration.");
end if;
flowRegime = flowRegime_nominal;

equation
algorithm
// Assign the flow regime for the given heat exchanger configuration and
// mass flow rates
if use_dynamicFlowRegime then
if (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) then
flowRegime = if (C1_flow*C2_flow >= 0)
then
Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow
else
Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) then
flowRegime = if (C1_flow*C2_flow >= 0)
then
Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow
else
Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowUnmixed) then
flowRegime = Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowUnmixed;
elseif (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) then
flowRegime = if (C1_flow < C2_flow)
then
Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed
else
Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed;
else
// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed)
flowRegime = if (C1_flow < C2_flow)
then
Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed
else
Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed;
end if;
else
flowRegime = flowRegime_nominal;

// ParallelFlow vs CounterFlow
when(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) and
flowRegime==flowRegime_nominal and (m1_flow*m2_flow/mPro_flow_nominal < -0.001)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow) and
flowRegime==Buildings.Fluid.Types.HeatExchangerFlowRegime.CounterFlow and (m1_flow*m2_flow/mPro_flow_nominal > 0.001)) then
flowRegime := flowRegime_nominal;

// CounterFlow vs ParallelFlow
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) and
flowRegime == flowRegime_nominal and (m1_flow*m2_flow/mPro_flow_nominal < -0.001)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow) and
flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.ParallelFlow and (m1_flow*m2_flow/mPro_flow_nominal > 0.001)) then
flowRegime := flowRegime_nominal;

// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed)
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) and
flowRegime == flowRegime_nominal and (C1_flow < 0.95*C2_flow)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1MixedStream2Unmixed) and
(flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinMixedCMaxUnmixed and (C1_flow > 1.05*C2_flow))) then
flowRegime := flowRegime_nominal;
// have ( configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed)
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed) and
flowRegime == flowRegime_nominal and (C1_flow < 0.95*C2_flow)) then
flowRegime := Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed;
elsewhen(use_dynamicFlowRegime and (configuration == Buildings.Fluid.Types.HeatExchangerConfiguration.CrossFlowStream1UnmixedStream2Mixed) and
(flowRegime == Buildings.Fluid.Types.HeatExchangerFlowRegime.CrossFlowCMinUnmixedCMaxMixed and (C1_flow > 1.05*C2_flow))) then
flowRegime := flowRegime_nominal;
end when;

if not use_dynamicFlowRegime then
assert(noEvent(m1_flow > -0.1 * m1_flow_nominal)
and noEvent(m2_flow > -0.1 * m2_flow_nominal),
"*** Warning in " + getInstanceName() +
Expand All @@ -365,6 +374,7 @@ equation
level = AssertionLevel.warning);
end if;

equation
connect(heaCoo.port_b, port_b1) annotation (Line(points={{80,60},{80,60},{100,60}},color={0,127,255},
thickness=1));
connect(heaCooHum_u.port_b, port_b2) annotation (Line(
Expand Down Expand Up @@ -650,6 +660,12 @@ Fuzzy identification of systems and its applications to modeling and control.
</html>", revisions="<html>
<ul>
<li>
March 7, 2026, by Michael Wetter:<br/>
Corrected implementation of switch of flow regime.<br/>
This is for
<a href=\"https://github.com/ibpsa/modelica-ibpsa/issues/2086\">IBPSA, #2086</a>.
</li>
<li>
February 7, 2025, by Jelger Jansen:<br/>
Removed <code>import</code> statement.
This is for
Expand Down