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 |  | Number of data points for pressure curve | 
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;
  
constant Boolean homotopyInitialization = true ;
  
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) ;
 
  
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);
  
assert(homotopyInitialization, "In " +
 getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);
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] | 
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;
  
constant 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
    ;
initial equation 
  assert(homotopyInitialization, "In " +
 getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);
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