Package with base classes for Buildings.Fluid.Movers
Information
This package contains base classes that are used to construct the models in
Buildings.Fluid.Movers.
Extends from Modelica.Icons.BasesPackage (Icon for packages containing base classes).
Package Content
Name |
Description |
FlowMachineInterface
|
Partial model with performance curves for fans or pumps |
IdealSource
|
Base class for pressure and mass flow source with optional power input |
PartialFlowMachine
|
Partial model to interface fan or pump models with the medium |
PowerInterface
|
Partial model to compute power draw and heat dissipation of fans and pumps |
Characteristics
|
Functions for fan or pump characteristics |
Types
|
Package with type definitions |
Validation
|
Collection of validation models |
Partial model with performance curves for fans or pumps
Information
This is an interface that implements the functions to compute the head, power draw
and efficiency of fans and pumps.
The nominal hydraulic characteristic (volume flow rate versus total pressure)
is given by a set of data points
using the data record per
, which is an instance of
Buildings.Fluid.Movers.Data.Generic.
A cubic hermite spline with linear extrapolation is used to compute
the performance at other operating points.
The fan or pump energy balance can be specified in two alternative ways:
-
If
per.use_powerCharacteristic = false
, then the data points for
normalized volume flow rate versus efficiency is used to determine the efficiency,
and then the power consumption. The default is a constant efficiency of 0.7.
-
If
per.use_powerCharacteristic = true
, then the data points for
normalized volume flow rate versus power consumption
is used to determine the power consumption, and then the efficiency
is computed based on the actual power consumption and the flow work.
For exceptions to this general rule, check the
User's Guide for more information.
Implementation
For numerical reasons, the user-provided data points for volume flow rate
versus pressure rise are modified to add a fan internal flow resistance.
Because this flow resistance is subtracted during the simulation when
computing the fan pressure rise, the model reproduces the exact points
that were provided by the user.
Also for numerical reasons, the pressure rise at zero flow rate and
the flow rate at zero pressure rise is added to the user-provided data,
unless the user already provides these data points.
Since Modelica 3.2 does not allow dynamic memory allocation, this
implementation required the use of three different arrays for the
situation where no additional point is added, where one additional
point is added and where two additional points are added.
The parameter curve
causes the correct data record
to be used during the simulation.
Extends from Modelica.Blocks.Icons.Block (Basic graphical layout of input/output block).
Parameters
Type | Name | Default | Description |
Generic | per | | Record with performance data |
PrescribedVariable | preVar | Buildings.Fluid.Movers.BaseC... | Type of prescribed variable |
Boolean | computePowerUsingSimilarityLaws | | = true, compute power exactly, using similarity laws. Otherwise approximate. |
Density | rho_default | | Fluid density at medium default state [kg/m3] |
Boolean | haveVMax | | Flag, true if user specified data that contain V_flow_max |
VolumeFlowRate | V_flow_max | | Maximum volume flow rate, used for smoothing [m3/s] |
Integer | nOri | nOri( ... | Number of data points for pressure curve |
Advanced |
Boolean | homotopyInitialization | true | = true, use homotopy method |
Connectors
Type | Name | Description |
input RealInput | y_in | Prescribed mover speed [1] |
output RealOutput | y_out | Mover speed (prescribed or computed) [1] |
input RealInput | m_flow | Mass flow rate [kg/s] |
input RealInput | rho | Medium density [kg/m3] |
output RealOutput | V_flow | Volume flow rate [m3/s] |
input RealInput | dp_in | Prescribed pressure increase [Pa] |
output RealOutput | dp | Pressure increase (computed or prescribed) [Pa] |
output RealOutput | WFlo | Flow work [W] |
output RealOutput | PEle | Electrical power consumed [W] |
output RealOutput | eta | Overall efficiency [1] |
output RealOutput | etaHyd | Hydraulic efficiency [1] |
output RealOutput | etaMot | Motor efficiency [1] |
output RealOutput | r_N | Ratio N_actual/N_nominal [1] |
Modelica definition
model FlowMachineInterface
extends Modelica.Blocks.Icons.Block;
import cha =
Buildings.Fluid.Movers.BaseClasses.Characteristics;
parameter Buildings.Fluid.Movers.Data.Generic per
;
parameter Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable preVar=
Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed ;
parameter Boolean computePowerUsingSimilarityLaws
;
final parameter Modelica.SIunits.VolumeFlowRate V_flow_nominal=
per.pressure.V_flow[nOri] ;
parameter Modelica.SIunits.Density rho_default
;
parameter Boolean haveVMax
;
parameter Modelica.SIunits.VolumeFlowRate V_flow_max
;
parameter Integer nOri(min=1) ;
parameter Boolean homotopyInitialization = true ;
Modelica.Blocks.Interfaces.RealInput y_in(
final unit="1")
if preSpe
;
Modelica.Blocks.Interfaces.RealOutput y_out(
final unit="1") ;
Modelica.Blocks.Interfaces.RealInput m_flow(
final quantity="MassFlowRate",
final unit="kg/s") ;
Modelica.Blocks.Interfaces.RealInput rho(
final quantity="Density",
final unit="kg/m3",
min=0.0) ;
Modelica.Blocks.Interfaces.RealOutput V_flow(
quantity="VolumeFlowRate",
final unit="m3/s") ;
Modelica.Blocks.Interfaces.RealInput dp_in(
quantity="PressureDifference",
final unit="Pa")
if prePre ;
Modelica.Blocks.Interfaces.RealOutput dp(
quantity="Pressure",
final unit="Pa")
if not prePre ;
Modelica.Blocks.Interfaces.RealOutput WFlo(
quantity="Power",
final unit="W") ;
Modelica.Blocks.Interfaces.RealOutput PEle(
quantity="Power",
final unit="W") ;
Modelica.Blocks.Interfaces.RealOutput eta(
final quantity="Efficiency",
final unit="1") ;
Modelica.Blocks.Interfaces.RealOutput etaHyd(
final quantity="Efficiency",
final unit="1") ;
Modelica.Blocks.Interfaces.RealOutput etaMot(
final quantity="Efficiency",
final unit="1") ;
Modelica.Blocks.Interfaces.RealOutput r_N(unit="1")
;
Real r_V(start=1, unit="1") ;
protected
final parameter Boolean preSpe=
preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed
;
final parameter Boolean prePre=
preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.PressureDifference
or
preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.FlowRate
;
final parameter Real motDer[
size(per.motorEfficiency.V_flow, 1)](
each fixed=false)
;
final parameter Real hydDer[
size(per.hydraulicEfficiency.V_flow,1)](
each fixed=false)
;
parameter Modelica.SIunits.PressureDifference dpMax(displayUnit="Pa")=
if haveDPMax
then
per.pressure.dp[1]
else
per.pressure.dp[1] - ((per.pressure.dp[2] - per.pressure.dp[1])/(
per.pressure.V_flow[2] - per.pressure.V_flow[1]))*per.pressure.V_flow[1]
;
parameter Real delta = 0.05
;
parameter Real kRes(min=0, unit="kg/(s.m4)") = dpMax/V_flow_max*delta^2/10
;
parameter Integer curve=
if (haveVMax
and haveDPMax)
or (nOri == 2)
then 1
elseif haveVMax
or haveDPMax
then 2
else 3
;
final parameter Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParametersInternal
pCur1(
final n = nOri,
final V_flow =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
{per.pressure.V_flow[i]
for i
in 1:nOri}
else
zeros(nOri),
final dp =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
{(per.pressure.dp[i] + per.pressure.V_flow[i] * kRes)
for i
in 1:nOri}
else
zeros(nOri))
;
parameter Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParametersInternal
pCur2(
final n = nOri + 1,
V_flow =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
zeros(nOri + 1)
elseif haveVMax
then
cat(1, {0}, {per.pressure.V_flow[i]
for i
in 1:nOri})
elseif haveDPMax
then
cat(1, { per.pressure.V_flow[i]
for i
in 1:nOri}, {V_flow_max})
else
zeros(nOri + 1),
dp =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
zeros(nOri + 1)
elseif haveVMax
then
cat(1, {dpMax}, {per.pressure.dp[i] + per.pressure.V_flow[i] * kRes
for i
in 1:nOri})
elseif haveDPMax
then
cat(1, {per.pressure.dp[i] + per.pressure.V_flow[i] * kRes
for i
in 1:nOri}, {0})
else
zeros(nOri+1))
;
parameter Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParametersInternal
pCur3(
final n = nOri + 2,
V_flow =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
zeros(nOri + 2)
elseif haveVMax
or haveDPMax
then
zeros(nOri + 2)
else
cat(1, {0}, {per.pressure.V_flow[i]
for i
in 1:nOri}, {V_flow_max}),
dp =
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
zeros(nOri + 2)
elseif haveVMax
or haveDPMax
then
zeros(nOri + 2)
else
cat(1, {dpMax}, {per.pressure.dp[i] + per.pressure.V_flow[i] * kRes
for i
in 1:nOri}, {0}))
;
parameter Real preDer1[nOri](
each fixed=false)
;
parameter Real preDer2[nOri+1](
each fixed=false)
;
parameter Real preDer3[nOri+2](
each fixed=false)
;
parameter Real powDer[
size(per.power.V_flow,1)]=
if per.use_powerCharacteristic
then
Buildings.Utilities.Math.Functions.splineDerivatives(
x=per.power.V_flow,
y=per.power.P,
ensureMonotonicity=
Buildings.Utilities.Math.Functions.isMonotonic(x=per.power.P,
strict=false))
else
zeros(
size(per.power.V_flow,1))
;
parameter Boolean haveMinimumDecrease=
Modelica.Math.BooleanVectors.allTrue({(per.pressure.dp[i + 1] -
per.pressure.dp[i])/(per.pressure.V_flow[i + 1] - per.pressure.V_flow[
i]) < -kRes
for i
in 1:nOri - 1}) ;
parameter Boolean haveDPMax = (
abs(per.pressure.V_flow[1]) < Modelica.Constants.eps)
;
Modelica.Blocks.Interfaces.RealOutput dp_internal
;
function getPerformanceDataAsString
input Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters pressure
;
input Real derivative[:](unit="kg/(s.m4)") ;
input Integer minimumLength = 6 ;
input Integer significantDigits = 6 ;
output String str ;
algorithm
str :="";
for i
in 1:
size(derivative, 1)
loop
str :=str + " V_flow[" +
String(i) + "]=" +
String(
pressure.V_flow[i],
minimumLength=minimumLength,
significantDigits=significantDigits) + "\t" + "dp[" +
String(i) + "]=" +
String(
pressure.dp[i],
minimumLength=minimumLength,
significantDigits=significantDigits) + "\tResulting derivative dp/dV_flow = "
+
String(
derivative[i],
minimumLength=minimumLength,
significantDigits=significantDigits) + "\n";
end for;
end getPerformanceDataAsString;
function getArrayAsString
input Real array[:] ;
input String varName ;
input Integer minimumLength = 6 ;
input Integer significantDigits = 6 ;
output String str ;
algorithm
str :="";
for i
in 1:
size(array, 1)
loop
str :=str + " " + varName + "[" +
String(i) + "]=" +
String(
array[i],
minimumLength=minimumLength,
significantDigits=significantDigits) + "\n";
end for;
end getArrayAsString;
initial equation
assert(nOri > 1, "Must have at least two data points for pressure.V_flow.");
assert(
Buildings.Utilities.Math.Functions.isMonotonic(x=per.pressure.V_flow, strict=true)
and
per.pressure.V_flow[1] > -Modelica.Constants.eps,
"The fan pressure rise must be a strictly decreasing sequence with respect to the volume flow rate,
with the first element for the fan pressure raise being non-zero.
The following performance data have been entered:
" +
getArrayAsString(per.pressure.V_flow, "pressure.V_flow"));
if not haveVMax
then
assert((per.pressure.V_flow[nOri]-per.pressure.V_flow[nOri-1])
/((per.pressure.dp[nOri]-per.pressure.dp[nOri-1]))<0,
"The last two pressure points for the fan or pump performance curve must be decreasing.
You need to set more reasonable parameters.
Received
" +
getArrayAsString(per.pressure.dp, "dp"));
end if;
if (
not haveMinimumDecrease)
then
Modelica.Utilities.Streams.print("
Warning:
========
It is recommended that the volume flow rate versus pressure relation
of the fan or pump satisfies the minimum decrease condition
(per.pressure.dp[i+1]-per.pressure.dp[i])
d[i] = ------------------------------------------------- < " +
String(-kRes) + "
(per.pressure.V_flow[i+1]-per.pressure.V_flow[i])
is
" +
getArrayAsString({(per.pressure.dp[i+1]-per.pressure.dp[i])
/(per.pressure.V_flow[i+1]-per.pressure.V_flow[i])
for i
in 1:nOri-1}, "d") + "
Otherwise, a solution to the equations may not exist if the fan or pump speed is reduced.
In this situation, the solver will fail due to non-convergence and
the simulation stops.");
end if;
if (haveVMax
and haveDPMax)
or (nOri == 2)
then
preDer1=
Buildings.Utilities.Math.Functions.splineDerivatives(x=pCur1.V_flow,
y=pCur1.dp);
preDer2=
zeros(nOri + 1);
preDer3=
zeros(nOri + 2);
elseif haveVMax
or haveDPMax
then
preDer1=
zeros(nOri);
preDer2=
Buildings.Utilities.Math.Functions.splineDerivatives(x=pCur2.V_flow,
y=pCur2.dp);
preDer3=
zeros(nOri + 2);
else
preDer1=
zeros(nOri);
preDer2=
zeros(nOri + 1);
preDer3=
Buildings.Utilities.Math.Functions.splineDerivatives(x=pCur3.V_flow,
y=pCur3.dp);
end if;
motDer =
if per.use_powerCharacteristic
then zeros(
size(per.motorEfficiency.V_flow,
1))
elseif (
size(per.motorEfficiency.V_flow, 1) == 1)
then {0}
else
Buildings.Utilities.Math.Functions.splineDerivatives(
x=per.motorEfficiency.V_flow,
y=per.motorEfficiency.eta,
ensureMonotonicity=
Buildings.Utilities.Math.Functions.isMonotonic(x=per.motorEfficiency.eta,
strict=false));
hydDer =
if per.use_powerCharacteristic
then zeros(
size(per.hydraulicEfficiency.V_flow,
1))
elseif (
size(per.hydraulicEfficiency.V_flow, 1) == 1)
then {0}
else Buildings.Utilities.Math.Functions.splineDerivatives(x=per.hydraulicEfficiency.V_flow,
y=per.hydraulicEfficiency.eta);
equation
connect(dp_internal,dp);
connect(dp_internal,dp_in);
connect(r_N, y_in);
y_out=r_N;
V_flow = m_flow/rho;
r_V = V_flow/V_flow_max;
if (computePowerUsingSimilarityLaws == false)
and preVar <> Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed
then
r_N=1;
else
if (curve == 1)
then
if homotopyInitialization
then
V_flow*kRes + dp_internal =
homotopy(actual=
cha.pressure(
V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer1,
per=pCur1),
simplified=r_N * (
cha.pressure(
V_flow=V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer1,
per=pCur1)
+(V_flow-V_flow_nominal) * (
cha.pressure(
V_flow=(1+delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer1,
per=pCur1)
-
cha.pressure(V_flow=(1-delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer1,
per=pCur1))
/(2*delta*V_flow_nominal)));
else
V_flow*kRes + dp_internal=
cha.pressure(V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer1,
per=pCur1);
end if;
elseif (curve == 2)
then
if homotopyInitialization
then
V_flow*kRes + dp_internal =
homotopy(actual=
cha.pressure(
V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer2,
per=pCur2),
simplified=r_N * (
cha.pressure(
V_flow=V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer2,
per=pCur2)
+(V_flow-V_flow_nominal) * (
cha.pressure(
V_flow=(1+delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer2,
per=pCur2)
-
cha.pressure(V_flow=(1-delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer2,
per=pCur2))
/(2*delta*V_flow_nominal)));
else
V_flow*kRes + dp_internal=
cha.pressure(V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer2,
per=pCur2);
end if;
else
if homotopyInitialization
then
V_flow*kRes + dp_internal =
homotopy(actual=
cha.pressure(
V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer3,
per=pCur3),
simplified=r_N * (
cha.pressure(
V_flow=V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer3,
per=pCur3)
+(V_flow-V_flow_nominal)*
(
cha.pressure(V_flow=(1+delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer3,
per=pCur3)
-
cha.pressure(V_flow=(1-delta)*V_flow_nominal,
r_N=1,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer3,
per=pCur3))
/(2*delta*V_flow_nominal)));
else
V_flow*kRes + dp_internal=
cha.pressure(V_flow=V_flow,
r_N=r_N,
dpMax=dpMax,
V_flow_max=V_flow_max,
d=preDer3,
per=pCur3);
end if;
end if;
end if;
WFlo = dp_internal*V_flow;
if per.use_powerCharacteristic
then
if homotopyInitialization
then
PEle =
homotopy(actual=
cha.power(per=per.power, V_flow=V_flow, r_N=r_N, d=powDer, delta=delta),
simplified=V_flow/V_flow_nominal*
cha.power(per=per.power, V_flow=V_flow_nominal, r_N=1, d=powDer, delta=delta));
else
PEle = (rho/rho_default)*
cha.power(per=per.power, V_flow=V_flow, r_N=r_N, d=powDer, delta=delta);
end if;
eta = WFlo /
Buildings.Utilities.Math.Functions.smoothMax(x1=PEle, x2=1E-5, deltaX=1E-6);
etaHyd = 1;
etaMot = eta;
else
if homotopyInitialization
then
etaHyd =
homotopy(actual=
cha.efficiency(per=per.hydraulicEfficiency, V_flow=V_flow, d=hydDer, r_N=r_N, delta=delta),
simplified=
cha.efficiency(per=per.hydraulicEfficiency, V_flow=V_flow_max, d=hydDer, r_N=r_N, delta=delta));
etaMot =
homotopy(actual=
cha.efficiency(per=per.motorEfficiency, V_flow=V_flow, d=motDer, r_N=r_N, delta=delta),
simplified=
cha.efficiency(per=per.motorEfficiency, V_flow=V_flow_max, d=motDer, r_N=r_N, delta=delta));
else
etaHyd =
cha.efficiency(per=per.hydraulicEfficiency, V_flow=V_flow, d=hydDer, r_N=r_N, delta=delta);
etaMot =
cha.efficiency(per=per.motorEfficiency, V_flow=V_flow, d=motDer, r_N=r_N, delta=delta);
end if;
PEle = WFlo /
Buildings.Utilities.Math.Functions.smoothMax(x1=eta, x2=1E-5, deltaX=1E-6);
eta = etaHyd * etaMot;
end if;
end FlowMachineInterface;
Base class for pressure and mass flow source with optional power input
Information
Model of a fictitious pipe that is used as a base class
for a pressure source or to prescribe a mass flow rate.
Note that for fans and pumps with dynamic balance,
both the heat and the flow work are added to the volume of
air or water. This simplifies the equations compared to
adding heat to the volume, and flow work to this model.
Typically either control_m_flow
or
control_dp
should be true
to avoid a
singular system.
If control_m_flow = true
, then the mass flow rate
is set to the value of the input connector m_flow_in
.
Otherwise, this model does not specify the mass flow rate.
Similarly, if control_dp = true
, the head is equal to the
value of the input connector dp_in
.
Otherwise, this model does not specify the head.
Extends from Buildings.Fluid.Interfaces.PartialTwoPortTransport (Partial element transporting fluid between two ports without storage of mass or energy).
Parameters
Type | Name | Default | Description |
replaceable package Medium | PartialMedium | Medium in the component |
Boolean | control_m_flow | | if true, then the mass flow rate is equal to the value of m_flow_in |
Boolean | control_dp | not control_m_flow | if true, then the head is equal to the value of dp_in |
Assumptions |
Boolean | allowFlowReversal | true | = false to simplify equations, assuming, but not enforcing, no flow reversal |
Advanced |
PressureDifference | dp_start | 0 | Guess value of dp = port_a.p - port_b.p [Pa] |
MassFlowRate | m_flow_start | 0 | Guess value of m_flow = port_a.m_flow [kg/s] |
MassFlowRate | m_flow_small | | Small mass flow rate for regularization of zero flow [kg/s] |
Diagnostics |
Boolean | show_T | false | = true, if temperatures at port_a and port_b are computed |
Boolean | show_V_flow | true | = true, if volume flow rate at inflowing port is computed |
Connectors
Type | Name | Description |
FluidPort_a | port_a | Fluid connector a (positive design flow direction is from port_a to port_b) |
FluidPort_b | port_b | Fluid connector b (positive design flow direction is from port_a to port_b) |
input RealInput | m_flow_in | Prescribed mass flow rate [kg/s] |
input RealInput | dp_in | Prescribed pressure difference port_a.p-port_b.p [Pa] |
Modelica definition
Partial model to interface fan or pump models with the medium
Information
This is the base model for fans and pumps.
It provides an interface
between the equations that compute head and power consumption,
and the implementation of the energy and pressure balance
of the fluid.
Optionally, the fluid volume
is computed using a dynamic balance or a steady-state balance.
The parameter addPowerToMedium
determines whether
any power is added to the fluid. The default is addPowerToMedium=true
,
and hence the outlet enthalpy is higher than the inlet enthalpy if the
flow device is operating.
The setting addPowerToMedium=false
is physically incorrect
(since the flow work, the flow friction and the fan heat do not increase
the enthalpy of the medium), but this setting does in some cases lead to simpler equations
and more robust simulation, in particular if the mass flow is equal to zero.
Extends from Buildings.Fluid.Interfaces.LumpedVolumeDeclarations (Declarations for lumped volumes), Buildings.Fluid.Interfaces.PartialTwoPortInterface (Partial model transporting fluid between two ports without storing mass or energy).
Parameters
Type | Name | Default | Description |
replaceable package Medium | PartialMedium | Medium in the component |
Generic | per | redeclare parameter Building... | Record with performance data |
Boolean | computePowerUsingSimilarityLaws | | = true, compute power exactly, using similarity laws. Otherwise approximate. |
Boolean | addPowerToMedium | true | Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations) |
Boolean | nominalValuesDefineDefaultPressureCurve | false | Set to true to avoid warning if m_flow_nominal and dp_nominal are used to construct the default pressure curve |
Control |
InputType | inputType | Buildings.Fluid.Types.InputT... | Control input type |
Real | constInput | 0 | Constant input set point |
Real | stageInputs[:] | | Vector of input set points corresponding to stages |
Dynamics |
Equations |
Dynamics | energyDynamics | Modelica.Fluid.Types.Dynamic... | Type of energy balance: dynamic (3 initialization options) or steady state |
Dynamics | massDynamics | energyDynamics | Type of mass balance: dynamic (3 initialization options) or steady state |
Real | mSenFac | 1 | Factor for scaling the sensible thermal mass of the volume |
Nominal condition |
Time | tau | 1 | Time constant of fluid volume for nominal flow, used if energy or mass balance is dynamic [s] |
Filtered speed |
Boolean | use_inputFilter | true | = true, if speed is filtered with a 2nd order CriticalDamping filter |
Time | riseTime | 30 | Rise time of the filter (time to reach 99.6 % of the speed) [s] |
Init | init | Modelica.Blocks.Types.Init.I... | Type of initialization (no init/steady state/initial state/initial output) |
Real | y_start | 0 | Initial value of speed [1] |
Initialization |
AbsolutePressure | p_start | Medium.p_default | Start value of pressure [Pa] |
Temperature | T_start | Medium.T_default | Start value of temperature [K] |
MassFraction | X_start[Medium.nX] | Medium.X_default | Start value of mass fractions m_i/m [kg/kg] |
ExtraProperty | C_start[Medium.nC] | fill(0, Medium.nC) | Start value of trace substances |
ExtraProperty | C_nominal[Medium.nC] | fill(1E-2, Medium.nC) | Nominal value of trace substances. (Set to typical order of magnitude.) |
Assumptions |
Boolean | allowFlowReversal | true | = false to simplify equations, assuming, but not enforcing, no flow reversal |
Advanced |
MassFlowRate | m_flow_small | 1E-4*abs(m_flow_nominal) | Small mass flow rate for regularization of zero flow [kg/s] |
Diagnostics |
Boolean | show_T | false | = true, if actual temperature at port is computed |
Connectors
Type | Name | Description |
input IntegerInput | stage | Stage input signal for the pressure head |
output RealOutput | y_actual | Actual normalised pump speed that is used for computations [1] |
output RealOutput | P | Electrical power consumed [W] |
HeatPort_a | heatPort | Heat dissipation to environment |
Modelica definition
partial model PartialFlowMachine
extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations(
final mSenFac=1);
extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
m_flow_nominal(
final min=Modelica.Constants.small),
show_T=false,
port_a(
h_outflow(start=h_outflow_start)),
port_b(
h_outflow(start=h_outflow_start),
p(start=p_start),
final m_flow(max =
if allowFlowReversal
then +Modelica.Constants.inf
else 0)));
replaceable parameter Buildings.Fluid.Movers.Data.Generic per
constrainedby Buildings.Fluid.Movers.Data.Generic
;
parameter Buildings.Fluid.Types.InputType inputType = Buildings.Fluid.Types.InputType.Continuous
;
parameter Real constInput = 0 ;
parameter Real stageInputs[:]
;
parameter Boolean computePowerUsingSimilarityLaws
;
parameter Boolean addPowerToMedium=true
;
parameter Boolean nominalValuesDefineDefaultPressureCurve = false
;
parameter Modelica.SIunits.Time tau=1
;
parameter Boolean use_inputFilter=true
;
parameter Modelica.SIunits.Time riseTime=30
;
parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
;
parameter Real y_start(min=0, max=1, unit="1")=0 ;
Modelica.Blocks.Interfaces.IntegerInput stage
if
inputType == Buildings.Fluid.Types.InputType.Stages
;
Modelica.Blocks.Interfaces.RealOutput y_actual(
final unit="1")
;
Modelica.Blocks.Interfaces.RealOutput P(
quantity="Power",
final unit="W") ;
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
;
Modelica.SIunits.VolumeFlowRate VMachine_flow(start=_VMachine_flow) = eff.V_flow ;
Modelica.SIunits.PressureDifference dpMachine(displayUnit="Pa")=
-preSou.dp ;
Real eta(unit="1",
final quantity="Efficiency") = eff.eta ;
Real etaHyd(unit="1",
final quantity="Efficiency") = eff.etaHyd ;
Real etaMot(unit="1",
final quantity="Efficiency") = eff.etaMot ;
protected
final parameter Modelica.SIunits.VolumeFlowRate _VMachine_flow = 0
;
parameter Types.PrescribedVariable preVar ;
final parameter Boolean speedIsInput=
(preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed)
;
final parameter Integer nOri =
size(per.pressure.V_flow, 1)
;
final parameter Boolean haveVMax = (
abs(per.pressure.dp[nOri]) < Modelica.Constants.eps)
;
final parameter Modelica.SIunits.VolumeFlowRate V_flow_max=
if per.havePressureCurve
then
(
if haveVMax
then
per.pressure.V_flow[nOri]
else
per.pressure.V_flow[nOri] - (per.pressure.V_flow[nOri] - per.pressure.V_flow[
nOri - 1])/((per.pressure.dp[nOri] - per.pressure.dp[nOri - 1]))*per.pressure.dp[nOri])
else
m_flow_nominal/rho_default ;
final parameter Modelica.SIunits.Density rho_default=
Medium.density_pTX(
p=Medium.p_default,
T=Medium.T_default,
X=Medium.X_default) ;
final parameter Medium.ThermodynamicState sta_start=
Medium.setState_pTX(
T=T_start,
p=p_start,
X=X_start) ;
final parameter Modelica.SIunits.SpecificEnthalpy h_outflow_start =
Medium.specificEnthalpy(sta_start)
;
Modelica.Blocks.Sources.Constant[
size(stageInputs, 1)] stageValues(
final k=stageInputs)
if
inputType == Buildings.Fluid.Types.InputType.Stages ;
Modelica.Blocks.Sources.Constant setConst(
final k=constInput)
if
inputType == Buildings.Fluid.Types.InputType.Constant
;
Extractor extractor(
final nin=
size(stageInputs,1))
if
inputType == Buildings.Fluid.Types.InputType.Stages ;
Modelica.Blocks.Routing.RealPassThrough inputSwitch
;
Buildings.Fluid.Delays.DelayFirstOrder vol(
redeclare final package Medium =
Medium,
final tau=tau,
final energyDynamics=energyDynamics,
final massDynamics=massDynamics,
final T_start=T_start,
final X_start=X_start,
final C_start=C_start,
final m_flow_nominal=m_flow_nominal,
final m_flow_small=m_flow_small,
final p_start=p_start,
final prescribedHeatFlowRate=true,
final allowFlowReversal=allowFlowReversal,
nPorts=2) ;
Modelica.Blocks.Continuous.Filter filter(
order=2,
f_cut=5/(2*Modelica.Constants.pi*riseTime),
final init=init,
x(
each stateSelect=StateSelect.always),
final analogFilter=Modelica.Blocks.Types.AnalogFilter.CriticalDamping,
final filterType=Modelica.Blocks.Types.FilterType.LowPass)
if
use_inputFilter
;
Modelica.Blocks.Math.Gain gaiSpe(y(
final unit="1"))
if
inputType == Buildings.Fluid.Types.InputType.Continuous
and
speedIsInput
;
Buildings.Fluid.Movers.BaseClasses.IdealSource preSou(
redeclare final package Medium =
Medium,
final m_flow_small=m_flow_small,
final allowFlowReversal=allowFlowReversal,
final control_m_flow= (preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.FlowRate))
;
Buildings.Fluid.Movers.BaseClasses.PowerInterface heaDis(
final motorCooledByFluid=per.motorCooledByFluid,
final delta_V_flow=1E-3*V_flow_max)
if
addPowerToMedium ;
Modelica.Blocks.Math.Add PToMed(
final k1=1,
final k2=1)
if
addPowerToMedium ;
Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow prePow(
final alpha=0)
if
addPowerToMedium
;
Modelica.Blocks.Sources.RealExpression rho_inlet(y=
Medium.density(
Medium.setState_phX(port_a.p,
inStream(port_a.h_outflow),
inStream(port_a.Xi_outflow))))
;
Buildings.Fluid.Sensors.MassFlowRate senMasFlo(
redeclare final package Medium =
Medium) ;
Sensors.RelativePressure senRelPre(
redeclare final package Medium =
Medium) ;
FlowMachineInterface eff(
per(
final hydraulicEfficiency = per.hydraulicEfficiency,
final motorEfficiency = per.motorEfficiency,
final motorCooledByFluid = per.motorCooledByFluid,
final speed_nominal = 0,
final constantSpeed = 0,
final speeds = {0},
final power = per.power),
final nOri = nOri,
final rho_default=rho_default,
final computePowerUsingSimilarityLaws=computePowerUsingSimilarityLaws,
final haveVMax=haveVMax,
final V_flow_max=V_flow_max,
r_N(start=y_start),
r_V(start=m_flow_nominal/rho_default),
final preVar=preVar) ;
protected
block Extractor
extends Modelica.Blocks.Interfaces.MISO;
Modelica.Blocks.Interfaces.IntegerInput index ;
equation
y =
sum({
if index == i
then u[i]
else 0
for i
in 1:nin});
end Extractor;
initial equation
assert(m_flow_nominal >= Modelica.Constants.small, "In "+
getInstanceName()+
": The value of parameter m_flow_nominal should be greater or equal than " +
String(Modelica.Constants.small) + " but it equals " +
String(m_flow_nominal));
assert(nominalValuesDefineDefaultPressureCurve
or
per.havePressureCurve
or
(preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed),
"*** Warning: You are using a flow or pressure controlled mover with the
default pressure curve.
This leads to approximate calculations of the electrical power
consumption. Add the correct pressure curve in the record per
to obtain an accurate computation.
Setting nominalValuesDefineDefaultPressureCurve=true will suppress this warning.",
level=AssertionLevel.warning);
assert(nominalValuesDefineDefaultPressureCurve
or
(per.havePressureCurve
or
(preVar == Buildings.Fluid.Movers.BaseClasses.Types.PrescribedVariable.Speed))
or
per.use_powerCharacteristic == false,
"*** Warning: You are using a flow or pressure controlled mover with the
default pressure curve and you set use_powerCharacteristic = true.
Since this can cause wrong power consumption, the model will overwrite
this setting and use instead use_powerCharacteristic = false." +
"Since this causes the efficiency curve to be used,
make sure that the efficiency curves in the performance record per
are correct or add the pressure curve of the mover.
Setting nominalValuesDefineDefaultPressureCurve=true will suppress this warning.",
level=AssertionLevel.warning);
equation
connect(prePow.port, vol.heatPort);
connect(vol.heatPort, heatPort);
connect(preSou.port_b, port_b);
connect(stageValues.y, extractor.u);
connect(extractor.y, inputSwitch.u);
connect(setConst.y, inputSwitch.u);
connect(extractor.index, stage);
connect(PToMed.y, prePow.Q_flow);
connect(PToMed.u1, heaDis.Q_flow);
connect(senRelPre.port_b, preSou.port_a);
connect(senRelPre.port_a, preSou.port_b);
connect(heaDis.etaHyd,eff. etaHyd);
connect(heaDis.V_flow,eff. V_flow);
connect(eff.PEle, heaDis.PEle);
connect(eff.WFlo, heaDis.WFlo);
connect(rho_inlet.y,eff. rho);
connect(eff.m_flow, senMasFlo.m_flow);
connect(eff.PEle, P);
connect(eff.WFlo, PToMed.u2);
connect(inputSwitch.y, filter.u);
connect(senRelPre.p_rel, eff.dp_in);
connect(eff.y_out, y_actual);
connect(port_a, vol.ports[1]);
connect(vol.ports[2], senMasFlo.port_a);
connect(senMasFlo.port_b, preSou.port_a);
end PartialFlowMachine;
Partial model to compute power draw and heat dissipation of fans and pumps
Information
Block that implements the functions to compute the
heat dissipation of fans and pumps. It is used by the model
Buildings.Fluid.Movers.BaseClasses.PartialFlowMachine.
Extends from Modelica.Blocks.Icons.Block (Basic graphical layout of input/output block).
Parameters
Type | Name | Default | Description |
Boolean | motorCooledByFluid | | Flag, true if the motor is cooled by the fluid stream |
VolumeFlowRate | delta_V_flow | | Factor used for setting heat input into medium to zero at very small flows [m3/s] |
Advanced |
Boolean | homotopyInitialization | true | = true, use homotopy method |
Connectors
Type | Name | Description |
input RealInput | etaHyd | Hydraulic efficiency [1] |
input RealInput | V_flow | Volume flow rate [m3/s] |
input RealInput | WFlo | Flow work [W] |
input RealInput | PEle | Electrical power consumed [W] |
output RealOutput | Q_flow | Heat input from fan or pump to medium [W] |
Modelica definition
model PowerInterface
extends Modelica.Blocks.Icons.Block;
parameter Boolean homotopyInitialization = true ;
parameter Boolean motorCooledByFluid
;
parameter Modelica.SIunits.VolumeFlowRate delta_V_flow
;
Modelica.Blocks.Interfaces.RealInput etaHyd(
final quantity="Efficiency",
final unit="1") ;
Modelica.Blocks.Interfaces.RealInput V_flow(
final quantity="VolumeFlowRate",
final unit="m3/s") ;
Modelica.Blocks.Interfaces.RealInput WFlo(
final quantity="Power",
final unit="W") ;
Modelica.Blocks.Interfaces.RealInput PEle(
final quantity="Power",
final unit="W") ;
Modelica.Blocks.Interfaces.RealOutput Q_flow(
quantity="Power",
final unit="W") ;
Modelica.SIunits.Power WHyd
;
protected
Modelica.SIunits.HeatFlowRate QThe_flow
;
equation
etaHyd * WHyd = WFlo;
QThe_flow + WFlo =
if motorCooledByFluid
then PEle
else WHyd;
Q_flow =
if homotopyInitialization
then
homotopy(actual=
Buildings.Utilities.Math.Functions.regStep(
y1=QThe_flow,
y2=0,
x=
noEvent(
abs(V_flow))-2*delta_V_flow,
x_small=delta_V_flow),
simplified=0)
else
Buildings.Utilities.Math.Functions.regStep(
y1=QThe_flow,
y2=0,
x=
noEvent(
abs(V_flow))-2*delta_V_flow,
x_small=delta_V_flow);
end PowerInterface;
Extract scalar signal out of signal vector dependent on IntegerRealInput index
Information
Extends from Modelica.Blocks.Interfaces.MISO (Multiple Input Single Output continuous control block).
Parameters
Type | Name | Default | Description |
Integer | nin | 1 | Number of inputs |
Connectors
Type | Name | Description |
input RealInput | u[nin] | Connector of Real input signals |
output RealOutput | y | Connector of Real output signal |
input IntegerInput | index | Integer input for control input |
Modelica definition