Buildings.Fluid.BaseClasses

Package with base classes for Buildings.Fluid

Information

This package contains base classes that are used to construct the models in Buildings.Fluid.

Extends from Modelica.Icons.BasesPackage (Icon for packages containing base classes).

Package Content

Name Description
Buildings.Fluid.BaseClasses.ActuatorFilter ActuatorFilter Filter used for actuators of valves, dampers and movers
Buildings.Fluid.BaseClasses.IndexMassFraction IndexMassFraction Computes the index of a substance in the mass fraction vector Xi
Buildings.Fluid.BaseClasses.MassFlowRateMultiplier MassFlowRateMultiplier Model that multiplies the mass flow rate
Buildings.Fluid.BaseClasses.PartialResistance PartialResistance Partial model for a hydraulic resistance
Buildings.Fluid.BaseClasses.PartialThreeWayResistance PartialThreeWayResistance Flow splitter with partial resistance model at each port
Buildings.Fluid.BaseClasses.FlowModels FlowModels Flow models for pressure drop calculations
Buildings.Fluid.BaseClasses.Validation Validation Collection of validation models

Buildings.Fluid.BaseClasses.ActuatorFilter Buildings.Fluid.BaseClasses.ActuatorFilter

Filter used for actuators of valves, dampers and movers

Buildings.Fluid.BaseClasses.ActuatorFilter

Information

This block implements a filter that is used to approximate the actuators of valves, dampers and fans.

Implementation

The implementation is based on Modelica.Blocks.Continuous.CriticalDamping. It differs from that model in that the internal state of the filter s is transformed using x = u_nominal*s. It turns out that this transformation leads to smaller system of nonlinear equations if u_nominal ≠ 0, see IBPSA, #1498 for a discussion.

Extends from Modelica.Blocks.Interfaces.SISO (Single Input Single Output continuous control block).

Parameters

TypeNameDefaultDescription
Frequencyf Cut-off frequency [Hz]
Booleannormalizedtrue= true, if amplitude at f_cut is 3 dB, otherwise unmodified filter
Realu_nominal1Magnitude of input
Initialization
InitinitTypeModelica.Blocks.Types.Init.N...Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)
Realx_start[n]zeros(n)Initial or guess values of states
Realy_start0.0Initial value of output (remaining states are in steady state)

Connectors

TypeNameDescription
input RealInputuConnector of Real input signal
output RealOutputyConnector of Real output signal

Modelica definition

block ActuatorFilter "Filter used for actuators of valves, dampers and movers" import Modelica.Blocks.Types.Init; extends Modelica.Blocks.Interfaces.SISO; constant Integer n=2 "Order of filter"; parameter Modelica.Units.SI.Frequency f(start=1) "Cut-off frequency"; parameter Boolean normalized = true "= true, if amplitude at f_cut is 3 dB, otherwise unmodified filter"; parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.NoInit "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"; parameter Real x_start[n]=zeros(n) "Initial or guess values of states"; parameter Real y_start=0.0 "Initial value of output (remaining states are in steady state)"; parameter Real u_nominal = 1 "Magnitude of input"; Real x[n](each final stateSelect=StateSelect.never) = u_nom*s "Transformed filter states"; protected final parameter Real u_nom = if abs(u_nominal-1) < 1E-12 then 1-1E-12 else u_nominal "Magnitude of input (set to a value different from 1 to avoid elimination by symbolic processing)"; parameter Real alpha=if normalized then sqrt(2^(1/n) - 1) else 1.0 "Frequency correction factor for normalized filter"; parameter Real w_u=2*Modelica.Constants.pi*f/alpha/u_nom; Real s[n](start=x_start/u_nom) "Filter states"; initial equation if initType == Init.SteadyState then der(s) = zeros(n); elseif initType == Init.InitialState then s = x_start/u_nom; elseif initType == Init.InitialOutput then y = y_start; der(s[1:n - 1]) = zeros(n - 1); end if; equation der(s[1]) = (u - u_nom*s[1])*w_u; for i in 2:n loop der(s[i]) = (u_nom*s[i - 1] - u_nom*s[i])*w_u; end for; y =u_nom*s[n]; end ActuatorFilter;

Buildings.Fluid.BaseClasses.IndexMassFraction

Computes the index of a substance in the mass fraction vector Xi

Information

This block computes the index that the subtance with name substanceName has in the mass fraction vector X. If the medium model has no component called substanceName, then the block writes an error message and terminates the simulation.

This block is used for example to obtain the index of the subtance 'water' to obtain the water vapor concentration, or to measure any other mass fraction.

Parameters

TypeNameDefaultDescription
replaceable package MediumModelica.Media.Interfaces.Pa...Medium model
StringsubstanceName""Name of species substance

Connectors

TypeNameDescription
replaceable package MediumMedium model

Modelica definition

block IndexMassFraction "Computes the index of a substance in the mass fraction vector Xi" replaceable package Medium = Modelica.Media.Interfaces.PartialCondensingGases "Medium model"; parameter String substanceName="" "Name of species substance"; protected parameter Integer i_x = sum( if Modelica.Utilities.Strings.isEqual(string1=Medium.substanceNames[i], string2=substanceName, caseSensitive=false) then i else 0 for i in 1:Medium.nXi) "Index of substance"; initial equation assert(i_x > 0, "Substance '" + substanceName + "' is not present in medium '" + Medium.mediumName + "'.\n" + "Change medium model to one that has '" + substanceName + "' as a substance."); end IndexMassFraction;

Buildings.Fluid.BaseClasses.MassFlowRateMultiplier Buildings.Fluid.BaseClasses.MassFlowRateMultiplier

Model that multiplies the mass flow rate

Buildings.Fluid.BaseClasses.MassFlowRateMultiplier

Information

This model multiplies the mass flow rate so that 0 = port_b.m_flow + k * port_a.m_flow.

The specific enthalpy, the species concentration and the trace substance concentration remain unchanged. Therefore, this model does not conserve mass or energy. It is used in Buildings.Fluid.Geothermal.Borefields.BaseClasses.PartialBorefield and also in the Buildings library to avoid having to instantiate circuits in parallel, with each having the same mass flow rate and temperatures.

Extends from Buildings.Fluid.Interfaces.PartialTwoPort (Partial component with two ports).

Parameters

TypeNameDefaultDescription
replaceable package MediumPartialMediumMedium in the component
Realk Gain for mass flow rate
Assumptions
BooleanallowFlowReversaltrue= false to simplify equations, assuming, but not enforcing, no flow reversal

Connectors

TypeNameDescription
FluidPort_aport_aFluid connector a (positive design flow direction is from port_a to port_b)
FluidPort_bport_bFluid connector b (positive design flow direction is from port_a to port_b)

Modelica definition

model MassFlowRateMultiplier "Model that multiplies the mass flow rate" extends Buildings.Fluid.Interfaces.PartialTwoPort; parameter Real k "Gain for mass flow rate"; initial equation assert(k > Modelica.Constants.small or -k < -Modelica.Constants.small, "Gain must not be zero. Received k = " + String(k)); equation // Pressure drop in design flow direction port_a.p = port_b.p; // Mass balance (mass is not conserved by this model!) port_b.m_flow = -k*port_a.m_flow; // Specific enthalpy flow rate port_a.h_outflow = inStream(port_b.h_outflow); port_b.h_outflow = inStream(port_a.h_outflow); // Transport of substances port_a.Xi_outflow = inStream(port_b.Xi_outflow); port_b.Xi_outflow = inStream(port_a.Xi_outflow); port_a.C_outflow = inStream(port_b.C_outflow); port_b.C_outflow = inStream(port_a.C_outflow); end MassFlowRateMultiplier;

Buildings.Fluid.BaseClasses.PartialResistance Buildings.Fluid.BaseClasses.PartialResistance

Partial model for a hydraulic resistance

Buildings.Fluid.BaseClasses.PartialResistance

Information

Partial model for a flow resistance, possible with variable flow coefficient. Models that extend this class need to implement an equation that relates m_flow and dp, and they need to assign the parameter m_flow_turbulent.

See for example Buildings.Fluid.FixedResistances.PressureDrop for a model that extends this base class.

Extends from Buildings.Fluid.Interfaces.PartialTwoPortInterface (Partial model transporting fluid between two ports without storing mass or energy).

Parameters

TypeNameDefaultDescription
replaceable package MediumPartialMediumMedium in the component
MassFlowRatem_flow_turbulent Turbulent flow if |m_flow| >= m_flow_turbulent [kg/s]
Nominal condition
MassFlowRatem_flow_nominal Nominal mass flow rate [kg/s]
PressureDifferencedp_nominal Pressure drop at nominal mass flow rate [Pa]
Assumptions
BooleanallowFlowReversaltrue= false to simplify equations, assuming, but not enforcing, no flow reversal
Advanced
MassFlowRatem_flow_small1E-4*abs(m_flow_nominal)Small mass flow rate for regularization of zero flow [kg/s]
Booleanfrom_dpfalse= true, use m_flow = f(dp) else dp = f(m_flow)
Booleanlinearizedfalse= true, use linear relation between m_flow and dp for any flow rate
Diagnostics
Booleanshow_Tfalse= true, if actual temperature at port is computed

Connectors

TypeNameDescription
FluidPort_aport_aFluid connector a (positive design flow direction is from port_a to port_b)
FluidPort_bport_bFluid connector b (positive design flow direction is from port_a to port_b)

Modelica definition

partial model PartialResistance "Partial model for a hydraulic resistance" extends Buildings.Fluid.Interfaces.PartialTwoPortInterface( show_T=false, dp(nominal=if dp_nominal_pos > Modelica.Constants.eps then dp_nominal_pos else 1), m_flow( nominal=if m_flow_nominal_pos > Modelica.Constants.eps then m_flow_nominal_pos else 1), final m_flow_small = 1E-4*abs(m_flow_nominal)); constant Boolean homotopyInitialization = true "= true, use homotopy method"; parameter Boolean from_dp = false "= true, use m_flow = f(dp) else dp = f(m_flow)"; parameter Modelica.Units.SI.PressureDifference dp_nominal(displayUnit="Pa") "Pressure drop at nominal mass flow rate"; parameter Boolean linearized = false "= true, use linear relation between m_flow and dp for any flow rate"; parameter Modelica.Units.SI.MassFlowRate m_flow_turbulent(min=0) "Turbulent flow if |m_flow| >= m_flow_turbulent"; protected parameter Medium.ThermodynamicState sta_default= Medium.setState_pTX(T=Medium.T_default, p=Medium.p_default, X=Medium.X_default); parameter Modelica.Units.SI.DynamicViscosity eta_default= Medium.dynamicViscosity(sta_default) "Dynamic viscosity, used to compute transition to turbulent flow regime"; final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_pos=abs( m_flow_nominal) "Absolute value of nominal flow rate"; final parameter Modelica.Units.SI.PressureDifference dp_nominal_pos( displayUnit="Pa") = abs(dp_nominal) "Absolute value of nominal pressure difference"; 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 // Isenthalpic state transformation (no storage and no loss of energy) port_a.h_outflow = if allowFlowReversal then inStream(port_b.h_outflow) else Medium.h_default; port_b.h_outflow = inStream(port_a.h_outflow); // Mass balance (no storage) port_a.m_flow + port_b.m_flow = 0; // Transport of substances port_a.Xi_outflow = if allowFlowReversal then inStream(port_b.Xi_outflow) else Medium.X_default[1:Medium.nXi]; port_b.Xi_outflow = inStream(port_a.Xi_outflow); port_a.C_outflow = if allowFlowReversal then inStream(port_b.C_outflow) else zeros(Medium.nC); port_b.C_outflow = inStream(port_a.C_outflow); end PartialResistance;

Buildings.Fluid.BaseClasses.PartialThreeWayResistance Buildings.Fluid.BaseClasses.PartialThreeWayResistance

Flow splitter with partial resistance model at each port

Buildings.Fluid.BaseClasses.PartialThreeWayResistance

Information

Partial model for flow resistances with three ports such as a flow mixer/splitter or a three way valve.

If energyDynamics ≠ Modelica.Fluid.Types.Dynamics.SteadyState, then at the junction of the three flows, a mixing volume will be present. This will introduce a dynamic energy and momentum balance, which often breaks algebraic loops. The time constant of the mixing volume is determined by the parameter tau.

Extends from Buildings.Fluid.Interfaces.LumpedVolumeDeclarations (Declarations for lumped volumes).

Parameters

TypeNameDefaultDescription
replaceable package MediumPartialMediumMedium in the component
PartialTwoPortInterfaceres1redeclare Buildings.Fluid.In...Partial model, to be replaced with a fluid component
PartialTwoPortInterfaceres2redeclare Buildings.Fluid.In...Partial model, to be replaced with a fluid component
PartialTwoPortInterfaceres3redeclare Buildings.Fluid.In...Partial model, to be replaced with a fluid component
Dynamics
Conservation equations
DynamicsenergyDynamicsModelica.Fluid.Types.Dynamic...Type of energy balance: dynamic (3 initialization options) or steady state
MassFlowRatemDyn_flow_nominal Nominal mass flow rate for dynamic momentum and energy balance [kg/s]
RealmSenFac1Factor for scaling the sensible thermal mass of the volume
Nominal condition
Timetau10Time constant at nominal flow for dynamic energy and momentum balance [s]
Advanced
Dynamics
DynamicsmassDynamicsenergyDynamicsType of mass balance: dynamic (3 initialization options) or steady state, must be steady state if energyDynamics is steady state
Booleanfrom_dptrue= true, use m_flow = f(dp) else dp = f(m_flow)
PortFlowDirectionportFlowDirection_1Modelica.Fluid.Types.PortFlo...Flow direction for port_1
PortFlowDirectionportFlowDirection_2Modelica.Fluid.Types.PortFlo...Flow direction for port_2
PortFlowDirectionportFlowDirection_3Modelica.Fluid.Types.PortFlo...Flow direction for port_3
BooleanverifyFlowReversalfalse=true, to assert that the flow does not reverse when portFlowDirection_* does not equal Bidirectional
MassFlowRatem_flow_small Small mass flow rate for checking flow reversal [kg/s]
Initialization
AbsolutePressurep_startMedium.p_defaultStart value of pressure [Pa]
TemperatureT_startMedium.T_defaultStart value of temperature [K]
MassFractionX_start[Medium.nX]Medium.X_defaultStart value of mass fractions m_i/m [kg/kg]
ExtraPropertyC_start[Medium.nC]fill(0, Medium.nC)Start value of trace substances
ExtraPropertyC_nominal[Medium.nC]fill(1E-2, Medium.nC)Nominal value of trace substances. (Set to typical order of magnitude.)

Connectors

TypeNameDescription
FluidPort_aport_1First port, typically inlet
FluidPort_bport_2Second port, typically outlet
FluidPort_aport_3Third port, can be either inlet or outlet

Modelica definition

partial model PartialThreeWayResistance "Flow splitter with partial resistance model at each port" extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations( final massDynamics=energyDynamics, final mSenFac=1); Modelica.Fluid.Interfaces.FluidPort_a port_1( redeclare package Medium = Medium, h_outflow(start=Medium.h_default, nominal=Medium.h_default), m_flow(min=if (portFlowDirection_1 == Modelica.Fluid.Types.PortFlowDirection.Entering) then 0.0 else -Modelica.Constants.inf, max=if (portFlowDirection_1== Modelica.Fluid.Types.PortFlowDirection.Leaving) then 0.0 else Modelica.Constants.inf)) "First port, typically inlet"; Modelica.Fluid.Interfaces.FluidPort_b port_2( redeclare package Medium = Medium, h_outflow(start=Medium.h_default, nominal=Medium.h_default), m_flow(min=if (portFlowDirection_2 == Modelica.Fluid.Types.PortFlowDirection.Entering) then 0.0 else -Modelica.Constants.inf, max=if (portFlowDirection_2 == Modelica.Fluid.Types.PortFlowDirection.Leaving) then 0.0 else Modelica.Constants.inf)) "Second port, typically outlet"; Modelica.Fluid.Interfaces.FluidPort_a port_3( redeclare package Medium=Medium, h_outflow(start=Medium.h_default, nominal=Medium.h_default), m_flow(min=if (portFlowDirection_3==Modelica.Fluid.Types.PortFlowDirection.Entering) then 0.0 else -Modelica.Constants.inf, max=if (portFlowDirection_3==Modelica.Fluid.Types.PortFlowDirection.Leaving) then 0.0 else Modelica.Constants.inf)) "Third port, can be either inlet or outlet"; parameter Modelica.Units.SI.Time tau=10 "Time constant at nominal flow for dynamic energy and momentum balance"; parameter Modelica.Units.SI.MassFlowRate mDyn_flow_nominal "Nominal mass flow rate for dynamic momentum and energy balance"; parameter Boolean from_dp = true "= true, use m_flow = f(dp) else dp = f(m_flow)"; parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_1=Modelica.Fluid.Types.PortFlowDirection.Bidirectional "Flow direction for port_1"; parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_2=Modelica.Fluid.Types.PortFlowDirection.Bidirectional "Flow direction for port_2"; parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_3=Modelica.Fluid.Types.PortFlowDirection.Bidirectional "Flow direction for port_3"; parameter Boolean verifyFlowReversal = false "=true, to assert that the flow does not reverse when portFlowDirection_* does not equal Bidirectional"; parameter Modelica.Units.SI.MassFlowRate m_flow_small "Small mass flow rate for checking flow reversal"; replaceable Buildings.Fluid.Interfaces.PartialTwoPortInterface res1 constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface( redeclare final package Medium = Medium, allowFlowReversal=portFlowDirection_1 == Modelica.Fluid.Types.PortFlowDirection.Bidirectional) "Partial model, to be replaced with a fluid component"; replaceable Buildings.Fluid.Interfaces.PartialTwoPortInterface res2 constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface( redeclare final package Medium = Medium, allowFlowReversal=portFlowDirection_2 == Modelica.Fluid.Types.PortFlowDirection.Bidirectional) "Partial model, to be replaced with a fluid component"; replaceable Buildings.Fluid.Interfaces.PartialTwoPortInterface res3 constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface( redeclare final package Medium = Medium, allowFlowReversal=portFlowDirection_3 == Modelica.Fluid.Types.PortFlowDirection.Bidirectional) "Partial model, to be replaced with a fluid component"; Buildings.Fluid.Delays.DelayFirstOrder vol( redeclare final package Medium = Medium, final nPorts=3, final tau=tau, final m_flow_nominal=mDyn_flow_nominal, final energyDynamics=energyDynamics, final p_start=p_start, final T_start=T_start, final X_start=X_start, final C_start=C_start, final allowFlowReversal=true, final prescribedHeatFlowRate=false) if have_controlVolume "Fluid volume to break algebraic loop"; protected parameter Boolean have_controlVolume= energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState "Boolean flag used to remove conditional components"; Modelica.Fluid.Interfaces.FluidPort_a port_internal( redeclare package Medium = Medium) if not have_controlVolume "Internal dummy port for easier connection of conditional connections"; initial equation assert(portFlowDirection_1<>Modelica.Fluid.Types.PortFlowDirection.Leaving or portFlowDirection_2<>Modelica.Fluid.Types.PortFlowDirection.Leaving or portFlowDirection_3<>Modelica.Fluid.Types.PortFlowDirection.Leaving, "In " + getInstanceName() + ": All ports are configured to Modelica.Fluid.Types.PortFlowDirection.Leaving, which is non-physical."); assert(portFlowDirection_1<>Modelica.Fluid.Types.PortFlowDirection.Entering or portFlowDirection_2<>Modelica.Fluid.Types.PortFlowDirection.Entering or portFlowDirection_3<>Modelica.Fluid.Types.PortFlowDirection.Entering, "In " + getInstanceName() + ": All ports are configured to Modelica.Fluid.Types.PortFlowDirection.Entering, which is non-physical."); equation if verifyFlowReversal then if portFlowDirection_1==Modelica.Fluid.Types.PortFlowDirection.Entering then assert(port_1.m_flow> -m_flow_small, "In " + getInstanceName() + ": Flow is leaving port_1 despite portFlowDirection_1=PortFlowDirection.Entering, since m_flow=" + String(port_1.m_flow) + "<-"+String(m_flow_small)); end if; if portFlowDirection_1==Modelica.Fluid.Types.PortFlowDirection.Leaving then assert(port_1.m_flow< m_flow_small, "In " + getInstanceName() + ": Flow is entering port_1 despite portFlowDirection_1=PortFlowDirection.Leaving, since m_flow=" + String(port_1.m_flow) + ">"+String(m_flow_small)); end if; if portFlowDirection_2==Modelica.Fluid.Types.PortFlowDirection.Entering then assert(port_2.m_flow> -m_flow_small, "In " + getInstanceName() + ": Flow is leaving port_2 despite portFlowDirection_2=PortFlowDirection.Entering, since m_flow=" + String(port_2.m_flow) + "<-"+String(m_flow_small)); end if; if portFlowDirection_2==Modelica.Fluid.Types.PortFlowDirection.Leaving then assert(port_2.m_flow< m_flow_small, "In " + getInstanceName() + ": Flow is entering port_2 despite portFlowDirection_2=PortFlowDirection.Leaving, since m_flow=" + String(port_2.m_flow) + ">"+String(m_flow_small)); end if; if portFlowDirection_3==Modelica.Fluid.Types.PortFlowDirection.Entering then assert(port_3.m_flow> -m_flow_small, "In " + getInstanceName() + ": Flow is leaving port_3 despite portFlowDirection_3=PortFlowDirection.Entering, since m_flow=" + String(port_3.m_flow) + "<-"+String(m_flow_small)); end if; if portFlowDirection_3==Modelica.Fluid.Types.PortFlowDirection.Leaving then assert(port_3.m_flow< m_flow_small, "In " + getInstanceName() + ": Flow is entering port_3 despite portFlowDirection_3=PortFlowDirection.Leaving, since m_flow=" + String(port_3.m_flow) + ">"+String(m_flow_small)); end if; end if; if portFlowDirection_1==Modelica.Fluid.Types.PortFlowDirection.Leaving then if not have_controlVolume then connect(res1.port_a, port_internal); else connect(res1.port_a, vol.ports[1]); end if; connect(port_1, res1.port_b); else if not have_controlVolume then connect(res1.port_b, port_internal); else connect(res1.port_b, vol.ports[1]); end if; connect(port_1, res1.port_a); end if; if portFlowDirection_2==Modelica.Fluid.Types.PortFlowDirection.Leaving then if not have_controlVolume then connect(res2.port_a, port_internal); else connect(res2.port_a, vol.ports[2]); end if; connect(port_2, res2.port_b); else if not have_controlVolume then connect(res2.port_b, port_internal); else connect(res2.port_b, vol.ports[2]); end if; connect(port_2, res2.port_a); end if; if portFlowDirection_3==Modelica.Fluid.Types.PortFlowDirection.Leaving then if not have_controlVolume then connect(res3.port_a, port_internal); else connect(res3.port_a, vol.ports[3]); end if; connect(port_3, res3.port_b); else if not have_controlVolume then connect(res3.port_b, port_internal); else connect(res3.port_b, vol.ports[3]); end if; connect(port_3, res3.port_a); end if; end PartialThreeWayResistance;