Like all libraries, this was developed to scratch my own itches. Since its
public release it has been found useful by many others, from students across
the world to practicing engineers at some of the world’s largest companies.

The bulk of this library’s API is considered stable; enhancements to
functions and classes will still happen, and default methods when using a generic
correlation interface may change to newer and more accurate correlations as
they are published and reviewed.

To the extent possible, correlations are implemented depending on the highest
level parameters. The friction_factor correlation does not accept pipe diameter,
velocity, viscosity, density, and roughness - it accepts Reynolds number and
relative roughness. This makes the API cleaner and encourages modular design.

All functions are designed to accept inputs in base SI units. However, any
set of consistent units given to a function will return a consistent result;
for instance, a function calculating volume doesn’t care if given an input in
inches or meters; the output units will be the cube of those given to it.
The user is directed to unit conversion libraries such as
pint to perform unit conversions if they
prefer not to work in SI units.

The standard math library is used in all functions except where special
functions from numpy or scipy are necessary. SciPy is used for root finding,
interpolation, scientific constants, ode integration, and its many special
mathematical functions not present in the standard math library. No other
libraries will become required dependencies; anything else is optional.

To allow use of numpy arrays with fluids, a vectorized module is implemented,
which wraps all of the fluids functions with np.vectorize. Instead of importing
from fluids, the user can import from fluids.vectorized:

Where different parameters may be used with a dimensionless number, either
a separate function is created for each or both sets of parameters are can
be specified. For example, instead of specifying viscosity and density for the
Reynolds number calculation, kinematic viscosity could have been used instead:

>>> Reynolds(D=0.01,V=1.5,nu=1E-6)15000.0

In the case of groups like the Fourier number, used in both heat and mass
transfer, two separate functions are available, Fourier_heat and
Fourier_mass. The heat transfer version supports specifying either the
density, heat capacity, and thermal conductivity - or just the thermal
diffusivity. There is no equivalent set of three parameters for the mass
transfer version; it always requires mass diffusivity.

Converters between loss coefficient, L/D equivalent, length of pipe, and
pressure drop are available.
It is recommended to convert length/diameter equivalents and lengths of pipe
at specified friction factors to loss coefficients. They can all be summed
easily afterwards.

The transition to laminar flow is implemented abruptly at Re=2040,
one of the latest experimental results which is accurate to +- 10.
If the Reynolds number is in the laminar regime, the transition happens
automatically and the well-known solution fd = 64/Re is given.

>>> fluids.friction.friction_factor(Re=150)0.4266666666666667

Friction factor in curved pipes in available as friction_factor_curved.
The curved friction factor is applicable for helices and coils, and to a
lesser extent curved bends.

The critical Reynolds number for curved pipes
is increased compared to straight pipe flow, and is a function of the
curvature of the pipe. The preferred method to calculate the transition
(used by default for the automatic regime transition)
is the method of Schmidt (1967).

>>> helical_transition_Re_Schmidt(Di=.01,Dc=2.5)3948.7442097768603

Although roughness is a hard value to know without measuring it for a pipe,
several hundred pipe conditions have had their roughness values measured in the
literature, and they can be searched through using fuzzy matching fluids.

>>> nearest_material_roughness('Used water piping',clean=False)'Seamless steel tubes, Used water piping'>>> material_roughness('Seamless steel tubes, Used water piping')0.0015

The material_roughness function can also be used directly, but in that case
there is no feedback about the material which was found.

There is one more way of obtaining the roughness of a clean pipe, developed by
Farshad and Rieke (2006). It has been established that in commercial pipe,
the larger the diameter, the larger the roughness.

The construction of mechanical systems often uses the “gauge” sytems, a variety
of old imperial conversions between plate or wire thickness and a dimensionless
number. Conversion from and to the gauge system is done by the gauge_from_t and
t_from_gauge functions.

Looking up the gauge from a wire of known diameter approximately 1.2 mm:

Sizing of vessels and storage tanks is implemented in an object-oriented way
as TANK in fluids.geometry. All results use the exact equations; all are
documented in the many functions in <fluids.geometry>

>>> T1=TANK(D=1.2,L=4,horizontal=False)>>> T1.V_total,T1.A# Total volume of the tank and its surface area4.523893421169302, 17.34159144781566

By default, tanks are cylinders without heads. Tank heads can be specified
to be conical, ellipsoidal, torispherical, guppy, or spherical. The heads can
be specified independently. The diameter and length are not required;
the total volume desired can be specified along with the length to
diameter ratio.

Conical, ellipsoidal, guppy and spherical heads are all governed only
by one parameter, a, the distance the head extends out from the main
tank body. Torispherical heads are governed by two parameters k and f.
If these parameters are not provided, the distance the head extends out
will be 25% of the size of the tank’s diameter. For torispherical heads, the
distance is similar but more complicated.

Partial volume lookups are also useful. This is useful when the height of fluid
in the tank is known, but not the volume. The reverse calculation is also
implemented, and useful when doing dynamic simulation and to calculate the new
height after a specified volume of liquid is removed.

Four main classes are available to model the atmosphere. They are the
US Standard Atmosphere 1976 (ATMOSPHERE_1976), a basic
but very quick model; the NRLMSISE 00 model, substantially more powerful and
accurate and still the standard to this day (ATMOSPHERE_NRLMSISE00); and two
models for wind speed only, Horizontal Wind Model 1993 (hwm93) and
Horizontal Wind Model 2014 (hwm14). The two horizontal wind models are actually
fortran codes, and are not compilled automatically on installation.

ATMOSPHERE_1976 is the simplest model, and very suitable for basic engineering
purposes. It supports atmospheric temperature, density, and pressure as a
function of elevation. Optionally, a local temperature difference from earth’s
average can be specified to correct the model to local conditions but this is
only a crude approximation.

ATMOSPHERE_NRLMSISE00 is the recommended model, and calculates atmospheric density,
temperature, and pressure as a function of height, latitude/longitude, day of year,
and seconds since start of day. The model can also take into account solar and
geomagnetic disturbances which effect the atmosphere at very high elevations
if more parameters are provided. It is valid up to 1000 km. This model
is somewhat slow; it is a Python port of the fortran version, created by Joshua
Milas. It does not support gravity profiles or transport properties, but does
calculate the composition of the atmosphere (He, O, N2, O2, Ar, H2, N2 as
constituents).

The horizontal wind models have almost the same API, and calculate wind speed
and direction as a function of elevation, latitude, longitude, day of year and
time of day. hwm93 can also take as an argument local geomagnetic conditions
and solar activity, but this effect was found to be so negligible it was removed
from future versions of the model such as hwm14.

Both isothermal and isentropic/polytropic compression models are implemented in
fluids.compressible. Isothermal compression calculates the work required to compress a gas from
one pressure to another at a specified temperature. This is the best possible case
for compression; all actual compresssors require more work to do the compression.
By making the compression take a large number of stages and cooling the gas
between stages, this can be approached reasonable closely. Integrally
geared compressors are often used for this purpose.

>>> isothermal_work_compression(P1=1E5,P2=1E6,T=300)5743.425357533477

Work is calculated on a J/mol basis. If the second pressure is lower than the
first, a negative work will result and you are modeling an expander instead
of a compressor. Gas compressibility factor can also be specified. The lower
the gas’s compressibility factor, the less power required to compress it.

There is only one function implemented to model both isentropic and polytropic
compressors, as the only difference is that a polytropic exponent n is used
instead of the gas’s isentropic exponent Cp/Cv k and the type of efficiency
is changed. The model requires initial temperature, inlet and outlet pressure,
isentropic exponent or polytropic exponent, and optionally an efficiency.

Compressing air from 1 bar to 10 bar, with inlet temperature of 300 K and
efficiency of 78%:

The work is the same as calculated with the original inputs. Note that the
conversion is specific to three inputs: Inlet pressure; outlet pressure;
and isentropic exponent k. If any of those change, then the calculated
polytropic exponent and efficiency will be different as well.

To go in the reverse direction, we take the case of isentropic exponent
k =Cp/Cv=1.4, eta_p=0.83 The power is calculated to be:

We first need to calculate the polytropic exponent from the polytropic
efficiency:

Not all specified mass flow rates are possible. At a certain downstream
pressure, chocked flow will develop - that downstream pressure is that
at which the mass flow rate reaches a maximum. An exception will be
raised if such an input is specified:

>>> isothermal_gas(rho=11.3,fd=0.00185,P1=1E6,L=1000,D=0.5,m=260)Exception: The desired mass flow rate cannot be achieved with the specified upstream pressure; the maximum flowrate is 257.216733 at an downstream pressure of 389699.731765>>> isothermal_gas(rho=11.3,fd=0.00185,P1=1E6,P2=3E5,L=1000,D=0.5)Exception: Given outlet pressure is not physically possible due to the formation of choked flow at P2=389699.731765, specified outlet pressure was 300000.000000

The downstream pressure at which chocked flow occurs can be calculated directly
as well:

In the above example, the friction factor was calculated using the density
and velocity of the gas when it enters the stream. However, the average values,
at the middle pressure, and more representative. We can iterate to observe
the effect of using the average values:

In addition to the actual model, many common simplifications used in industry
are implemented as well. These are equally capable of solving for any of the
following inputs:

Mass flow rate

Upstream pressure

Downstream pressure

Diameter of pipe

Length of pipe

None of these models include an acceleration term. In addition to reducing
their accuracy, it allows all solutions for the above variables to be analytical.
These models cannot predict the occurrence of chocked flow, and model only
turbulent, not laminar, flow. Most of these models do not depend on the gas’s
viscosity.

Rather than using mass flow rate, they use specific gravity and volumetric
flow rate. The volumetric flow rate is specified with respect to a reference
temperature and pressure. The defaults are 288.7 K and 101325 Pa, dating to
the old imperial standard of 60° F. The specific gravity is with respect to
air at the reference conditions. As the ideal gas law is used in each of
these models, in addition to pressure and specific gravity the average
temperature in the pipeline is required. Average compressibility factor is
an accepted input to all models and corrects the ideal gas law’s ideality.

The full list of approximate models is as follows:

Panhandle_A

Panhandle_B

Weymouth

Oliphant

Fritzsche

Muller

IGT

Spitzglass_high

Spitzglass_low

As an example, calculating flow for a pipe with diameter 0.34 m, upstream
pressure 90 bar and downstream pressure 20 bar, 160 km long, 0.693 specific
gravity and with an average temperature in the pipeline of 277.15 K:

Each model also includes a pipeline efficiency term, ranging from 0 to 1. These
are just empirical correction factors, Some of the models were developed with
theory and a correction factor applied always; others are more empirical, and
have a default correction factor. 0.92 is the default for the Panhandle A/B,
Weymouth, and Oliphant models; the rest default to a correction of 1 i.e. no
correction at all.

The Muller and IGT models are the most accurate and recent approximations.
They both depend on viscosity.

These empirical models are included because they are mandated in many industrial
applications regardless of their accuracy, and correction factors have already
been determined.

A great deal of effort was spent converting these models to base SI units
and checking the coefficients used in each model with multiple sources.
In many cases multiple sets of coefficients are available for a model;
the most authoritative or common ones were used in those cases.

In the simplest case, consider a spherical particle of diameter D=1 mm,
density=3400 kg/m^3, traveling at 30 m/s in air with viscosity mu=1E-5 Pa*s
and density 1.2 kg/m^3.

We calculate the particle Reynolds number:

>>> Re=Reynolds(V=30,rho=1.2,mu=1E-5,D=1E-3)>>> Re3599.9999999999995

The drag coefficient Cd can be calculated with no other parameters:

>>> drag_sphere(Re)0.3914804681941151

The terminal velocity of the particle is easily calculated with the
v_terminal function.

>>> v_terminal(D=1E-3,rhop=3400,rho=1.2,mu=1E-5)8.971223953182939

Very often, we are not interested in just what the velocity of the particle will
be at terminal conditions, but on the distance it will travel and the particle will
never have time to reach terminal conditions. An integrating function is available
to do that. Consider that same particle being shot directly down from a helicopter
100 m high.

The integrating function, integrate_drag_sphere, performs the integral with respect
to time. At one second, we can see the (velocity, distance travelled):

Twelve different packed bed pressure drop correlations are available. A meta
function which allows any of them to be selected and automatically selects
the most accurate correlation for the given parameters.

Pressure drop through a packed bed depends on the density, viscosity and
velocity of the fluid, as well as the diameter of the particles, the amount
of free space in the bed (voidage), and to a lesser amount the ratio of
particle to tube diameter and the shape of the particles.

Consider 0.8 mm pebbles with 40% empty space with water flowing through a 2 m
column creeping flow at a superficial velocity of 1 mm/s. We can calculate the
pressure drop as follows:

Not all particles are spherical. There have been correlations published for
specific shapes, but what is often performed is simply an adjustment of particle
diameter by its sphericity in the correlation, with the effective dp used
as the product of the actual dp and the sphericity of the particle. The less
spherical the particles, the higher the pressure drop. This is supported in
all of the correlations.

While it is easy to measure the volume of particles added to a given column
and determine the voidage experimentally, this does not help in the design process.
Several authors have methodically filled columns with particles of different sizes and
created correlations in terms of sphericity and particle to tube diameter ratios.
Three such correlations are implemented in fluids, one generally using sphericity,
one for spheres, and one for cylinders.

If the diameter of the piping varies, not all of the loss coefficients will be
with respect to the same diameter. Each loss coefficient must be converted to
one standard diameter before the total pressure drop can be calculated. The
following example is solved with the optional pint unit compatibility module.

The now internationally-standardized methods (IEC 60534) for sizing liquid and
gas valves have been implemented. Conversion factors among the different types
of valve coefficients are implemented as well.

There are two forms of loss coefficient used for vales, an imperial and a metric
variable called “valve flow coefficient”. Both can be converted to the standard
dimensionless loss coefficient.

If one knows the actual loss coefficient of a valve, the valve flow coefficient
can be calculated in either metric or imperial forms as follows. The flow
coefficients are specific to the diameter of the valve.

For a valve with a specified Kv and pressure drop, the flow rate can be calculated
easily for the case of non-choked non-compressible flow (neglecting other friction
losses), as illustrated in the example below for a 5 cm valve with a pressure drop
370 kPa and density of 870 kg/m^3:

The approach documented above is not an adequate procedure for sizing valves
however because chocked flow, compressible flow, the effect of inlet and outlet
reducers, the effect of viscosity and the effect of laminar/turbulent flow all
have large influences on the performance of control valves.

Historically, valve manufacturers had their own standards for sizing valves,
but these have been standardized today into the IEC 60534 methods.

To rigorously size a control valve for liquid flow, the inlet pressure,
allowable pressure drop, and desired flow rate must first be known.
These need to be determined taking into account the entire pipe network
and the various operating conditions it needs to support; sizing the valves
can be performed afterward and only if no valve with the desired performance
is available does the network need to be redesigned.

To illustrate sizing a valve, we borrow an example from Emerson’s
Control Valve Handbook, 4th edition (2005). It involves a flow of 800 gpm of
liquid propane. The inlet and outlet pipe size is 8 inches, but the size of the
valve itself is unknown. The desired pressure drop is 25 psi.

Converting this problem to SI units and using the thermo library to calculate
the necessary properties of the fluid, we calculate the necessary Kv of the
valve based on an assumed valve size of 3 inches:

FL, Liquid pressure recovery factor of a control valve without attached fittings

Fd, Valve style modifier

Both of these are factors between 0 and 1. In the Emerson handbook, they are
not considered in the sizing procedure and set to 1. These factors are also
a function of the diameter of the valve and are normally tabulated next to the
values of Cv or Kv for a valve.

The example in the book calculated Cv = 125.7, but doesn’t actually use the
full calculation method. Either way, the valve will not carry the desired flow
rate; we need to try a larger valve size. The 4 inch size is tried next in the
example, which has a known Cv of 203.

The calculated Cv is well under the valve’s maximum Cv; we can select it.

This model requires a vapor pressure and a critical pressure of the fluid as
inputs. There is no clarification in the standard about how to handle mixtures,
which do not have these values. It is reasonable
to calculate vapor pressure as the bubble pressure, and the mixture’s critical
pressure through a mole-weighted average.

For actual values of Cv, Fl, Fd, and available diameters, an excellent resource
is the Fisher Catalog 12.

To rigorously size a control valve for gas flow, the inlet pressure,
allowable pressure drop, and desired flow rate must first be known.
These need to be determined taking into account the entire pipe network
and the various operating conditions it needs to support; sizing the valves
can be performed afterward and only if no valve with the desired performance
is available does the network need to be redesigned.

To illustrate sizing a valve, we borrow an example from Emerson’s
Control Valve Handbook, 4th edition (2005). It involves a flow of 6 million ft^3/hour
of natural gas. The inlet and outlet pipe size is 8 inches, but the size of the
valve itself is unknown. The desired pressure drop is 150 psi.

Converting this problem to SI units and using the thermo library to calculate
the necessary properties of the fluid, we calculate the necessary Kv of the
valve based on an assumed valve size of 8 inches.

FL, Liquid pressure recovery factor of a control valve without attached fittings

Fd, Valve style modifier

xT, Pressure difference ratio factor of a valve without fittings at choked flow

All three of these are factors between 0 and 1. In the Emerson handbook, FL and Fd are
not considered in the sizing procedure and set to 1. xT is specified as 0.137
at full opening. These factors are also a function of the diameter of the
valve and are normally tabulated next to the values of Cv or Kv for a valve.
Performing the calculation:

The 8-inch valve is rated with Cv = 2190. The valve is adequate to provide
the desired flow because the rated Cv is higher. The calculated value in their
example is 1515, differing slightly due to the properties used.

The example next goes on to determine the actual opening position the valve
should be set at to provide the required flow. Their conclusion is approximately
75% open; we can do better using a numerical solver. The values of opening at
different positions are obtained in this example from the valve’s
datasheet.

Loading the data and creating interpolation functions so FL, Fd, and xT
are all smooth functions:

Motors are available in standard sizes, mostly as designated by the
National Electrical Manufacturers Association (NEMA). To easily determine what
the power of a motor will actually be once purchased, motor_round_size implements
rounding up of a motor power to the nearest size. NEMA standard motors are
specified in terms of horsepower.

Motors are designed to generate a certain amount of power, but they themselves are
not 100% efficient at doing this and require more power due to efficiency losses.
Many minimum values for motor efficiency are standardized. The Canadian standard
for this is implemented in fluids as CSA_motor_efficiency.

>>> CSA_motor_efficiency(P=5*hp)0.855

Most motors are not enclosed (the default assumption), but those that are closed
are more efficient.

>>> CSA_motor_efficiency(P=5*hp,closed=True)0.875

The number of poles in a motor also affects its efficiency:

>>> CSA_motor_efficiency(P=5*hp,poles=6)0.875

There is also a schedule of higher efficiency values standardized as well,
normally available at somewhat higher cost:

A motor will spin at more or less its design frequency, depending on its type.
However, if it does not meet sufficient resistance, it will not be using its
design power. This is good and bad - less power is used, but as a motor
drops under 50% of its design power, its efficiency becomes terrible. A function
has been written based on generic performance curves to estimate the underloaded
efficiency of a motor. Just how bad efficiency drops off depends on the design
power of a motor - higher power motors do better operating at low loads than
small motors.

Many motors have Variable Frequency Drives (VFDs) which allow them to vary the
speed of their rotation. The VFD is another source of inefficiency, but by allowing
the pump or other piece of equipment to vary its speed, a system may be designed to
be less energy intensive. For example, rather than running a pump at a certain
high frequency and controlling the flow with a large control valve, the flow
rate can be controlled with the VFD directly.

The efficiency of a VFD depends on the maximum power it needs to be able to
generate, and the power it is actually generating at an instant (load).
A table of typical modern VFD efficiencies is implemented in fluids as
VFD_efficiency.