Sample Program:¶
Function to automatically create a representative horizontal vessel in the process industry given a volume.
[1]:
from fluids import TANK
def create_horizontal_vessel(volume, L_over_D_ratio=3, head_type='ASME F&D'):
"""
Create a representative horizontal vessel for a given volume, allowing
customization of the head type with predefined options.
Parameters
----------
volume : float
The desired total volume of the vessel in cubic meters.
L_over_D_ratio : float, optional
The desired length-to-diameter ratio of the vessel. Defaults to 3,
typical for the process industry.
head_type : str, optional
The type of head for both ends of the vessel. Allows for custom strings
corresponding to different torispherical options, alongside other allowed
types by the fluids TANK class. Defaults to 'ASME F&D'.
One of '2:1 semi-elliptical', 'ASME F&D', 'ASME 80/6', 'ASME 80/10 F&D',
'DIN 28011', 'DIN 28013', None, 'conical', 'ellipsoidal', 'guppy', 'spherical'
Returns
-------
fluids.geometry.TANK
An object representing the designed vessel, including its dimensions and
other relevant information.
Examples
--------
>>> designed_vessel = create_horizontal_vessel(100)
Notes
-----
The function uses the TANK class from the fluids library to calculate the
necessary dimensions for the given volume. The head type is customizable with
predefined strings for different standard torispherical options.
"""
# Mapping custom strings to torispherical head parameters
head_params = {
'2:1 semi-elliptical': {'f': 0.9, 'k': 0.17},
'ASME F&D': {'f': 1.0, 'k': 0.06},
'ASME 80/6': {'f': 0.8, 'k': 0.06},
'ASME 80/10 F&D': {'f': 0.8, 'k': 0.1},
'DIN 28011': {'f': 1.0, 'k': 0.1},
'DIN 28013': {'f': 0.8, 'k': 0.154}
}
head_a_ratios = {
'conical': 0.2,
'ellipsoidal': 0.2,
'guppy': 0.5,
'spherical': 0.5,
'None': 0
}
if head_type in head_params:
# Use custom torispherical head parameters
f = head_params[head_type]['f']
k = head_params[head_type]['k']
sideA_f, sideA_k, sideB_f, sideB_k = f, k, f, k
sideA, sideB = 'torispherical', 'torispherical'
sideA_a_ratio = sideB_a_ratio = None
else:
# Use the head type as specified (non-torispherical or default parameters)
sideA, sideB = head_type, head_type
sideA_f = sideA_k = sideB_f = sideB_k = None
sideA_a_ratio = sideB_a_ratio = head_a_ratios[head_type]
# Create a TANK object with the specified parameters
vessel = TANK(V=volume, L_over_D=L_over_D_ratio, horizontal=True,
sideA=sideA, sideB=sideB,
sideA_f=sideA_f, sideA_k=sideA_k,
sideB_f=sideB_f, sideB_k=sideB_k,
sideA_a_ratio=sideA_a_ratio, sideB_a_ratio=sideB_a_ratio)
return vessel
vessel = create_horizontal_vessel(100)
vessel = create_horizontal_vessel(100, L_over_D_ratio=5, head_type='spherical')
[2]:
def estimate_tank_weight_basic(tank, density=7850, thickness=0.005):
"""
Estimate the weight of a tank based on its volume and material properties.
Parameters
----------
tank : TANK
The TANK object representing the tank whose weight is to be estimated.
density : float, optional
The density of the material used for the tank, in kilograms per cubic meter.
Default is 7850 kg/m^3, typical of steel.
thickness : float, optional
The thickness of the tank's wall, in meters. Default is 0.005 m (5 mm).
Returns
-------
float
The estimated weight of the tank, in kilograms.
Notes
-----
The function calculates the difference in volume between the original tank
and an enlarged version of the tank created by adding the specified thickness
to its walls. This volume difference, representing the volume of material used,
is then multiplied by the material's density to estimate the tank's weight.
"""
# Create a new tank object with added thickness to represent the outer shell
outer_tank = tank.add_thickness(thickness)
# Calculate the volume of the material used for the shell
material_volume = outer_tank.V_total - tank.V_total
# Estimate the weight of the tank
weight = material_volume * density
return weight
estimate_tank_weight_basic(vessel)
[2]:
6397.683587435168
[3]:
def estimate_tank_weight(tank, density_body=7850, thickness_body=0.005, density_heads=7850,
thickness_heads=0.005, coating_density=0, coating_thickness=0):
"""
Estimate the weight of a tank with options for different materials and thicknesses
for the body and heads, and coatings.
Parameters
----------
tank : TANK
The TANK object representing the tank whose weight is to be estimated.
density_body : float, optional
The density of the material used for the tank's body, in kg/m^3. Default is 7850 kg/m^3 for steel.
thickness_body : float, optional
The thickness of the tank's body walls, in meters. Default is 0.005 m (5 mm).
density_heads : float, optional
The density of the material used for the tank's heads, in kg/m^3. Allows for different materials for the body and heads.
thickness_heads : float, optional
The thickness of the tank's heads, in meters. Allows for different thicknesses for the body and heads.
coating_density : float, optional
The density of any coating applied to the tank, in kg/m^3. Default is 0, assuming no coating.
coating_thickness : float, optional
The thickness of the coating, in meters. Default is 0, assuming no coating.
Returns
-------
float
The estimated total weight of the tank, in kilograms, including the body, heads, any internal structures, and coatings.
"""
# Create an outer tank to represent the body with added thickness
outer_tank_body = tank.add_thickness(thickness_body)
body_volume = outer_tank_body.V_lateral - tank.V_lateral
body_weight = body_volume * density_body
# Estimate heads weight by creating two new TANK objects with a length of 0 and added thickness for heads
head_tank_original = TANK(D=tank.D, L=0, horizontal=tank.horizontal,
sideA=tank.sideA, sideB=tank.sideB,
sideA_f=tank.sideA_f, sideA_k=tank.sideA_k,
sideB_f=tank.sideB_f, sideB_k=tank.sideB_k,)
head_tank_with_thickness = head_tank_original.add_thickness(thickness_heads)
heads_volume = head_tank_with_thickness.V_total - head_tank_original.V_total
heads_weight = heads_volume * density_heads
# Calculate the weight of the coating, if applicable
tank_minus_coating = tank.add_thickness(thickness_body, sideA_thickness=thickness_heads, sideB_thickness=thickness_heads)
coated_tank = tank_minus_coating.add_thickness(coating_thickness)
coating_volume = coated_tank.V_total - tank_minus_coating.V_total
coating_weight = coating_volume * coating_density
# Sum up the weights to get the total
total_weight = body_weight + heads_weight + coating_weight
return total_weight
# Assuming the create_horizontal_vessel function has been defined as per previous examples
tank = create_horizontal_vessel(volume=100, L_over_D_ratio=3, head_type='ASME F&D')
# Estimate the weight of the tank including the coating
tank_weight = estimate_tank_weight(tank=tank,
density_body=7850,
thickness_body=0.005,
density_heads=7850,
thickness_heads=0.005,
coating_density=1400,
coating_thickness=0.002)
print(f"Estimated weight of the coated tank: {tank_weight:.2f} kg")
Estimated weight of the coated tank: 6593.20 kg
[4]:
import pandas as pd
from numpy import linspace
def tank_strapping_chart(tank, intervals=100):
"""
Computes a pandas DataFrame of fill levels and volumes for a given tank object.
Parameters
----------
tank : TANK
The tank object from the fluids library for which fill levels and volumes are calculated.
intervals : int, optional
The number of intervals between empty (0%) and full (100%) to calculate volumes for. Default is 100.
Returns
-------
pd.DataFrame
A DataFrame with two columns: 'Fill Level (%)' and 'Volume (m^3)',
representing the fill level of the tank and the corresponding volume.
"""
# Generate fill levels from 0% to 100% at the specified intervals
fill_levels = linspace(0, 100, intervals)
# Calculate the corresponding volume for each fill level
volumes = [tank.V_from_h(tank.h_max * level/100) for level in fill_levels]
# Create a DataFrame
df = pd.DataFrame({
'Fill Level (%)': fill_levels,
'Volume (m^3)': volumes
})
return df
tank_strapping_chart(tank, 15)
[4]:
Fill Level (%) | Volume (m^3) | |
---|---|---|
0 | 0.000000 | 0.000000 |
1 | 7.142857 | 3.058448 |
2 | 14.285714 | 8.537083 |
3 | 21.428571 | 15.425298 |
4 | 28.571429 | 23.292010 |
5 | 35.714286 | 31.836766 |
6 | 42.857143 | 40.813114 |
7 | 50.000000 | 50.000000 |
8 | 57.142857 | 59.186886 |
9 | 64.285714 | 68.163234 |
10 | 71.428571 | 76.707990 |
11 | 78.571429 | 84.574702 |
12 | 85.714286 | 91.462917 |
13 | 92.857143 | 96.941552 |
14 | 100.000000 | 100.000000 |
[5]:
import pandas as pd
from numpy import linspace
def tank_strapping_chart_detailed(tank, dry_weight, liquid_density=1000, intervals=100):
"""
Computes a pandas DataFrame of fill levels, volumes, heights, weights, and surface areas for a given tank object,
including the total weight of the tank at each fill level and the surface areas of interest.
Parameters
----------
tank : TANK
The tank object from the fluids library for which fill levels, volumes, heights, weights, and surface areas are calculated.
dry_weight : float
The dry weight of the tank in kilograms.
liquid_density : float, optional
The density of the liquid in kg/m^3. Default is 1000 (density of water).
intervals : int, optional
The number of intervals between empty (0%) and full (100%) to calculate volumes for. Default is 100.
Returns
-------
pd.DataFrame
A DataFrame with columns: 'Fill Level (%)', 'Height (m)', 'Volume (m^3)', 'Liquid Weight (kg)',
'Total Weight (kg)', 'Wetted Surface Area (m^2)', 'Dry Surface Area (m^2)', 'Exposed Liquid Surface Area (m^2)',
representing the fill level of the tank, the corresponding height, volume, weight of the liquid,
total weight including the tank, and the surface areas of interest.
"""
# Pre-compute the dry (total) surface area of the tank
dry_surface_area = tank.A
# Generate fill levels from 0% to 100% at the specified intervals
fill_levels = linspace(0, 1, intervals)
# Initialize lists to store computed values
heights, volumes, liquid_weights, total_weights, wetted_areas, dry_areas, cross_sectional_areas = [], [], [], [], [], [], []
for level in fill_levels:
height = tank.h_max * level
volume = tank.V_from_h(height)
liquid_weight = volume * liquid_density
total_weight = dry_weight + liquid_weight
wetted_area = tank.SA_from_h(height)
dry_area = dry_surface_area - wetted_area
cross_sectional_area = tank.A_cross_sectional(height)
# Append computed values to lists
heights.append(height)
volumes.append(volume)
liquid_weights.append(liquid_weight)
total_weights.append(total_weight)
wetted_areas.append(wetted_area)
dry_areas.append(dry_area)
cross_sectional_areas.append(cross_sectional_area)
# Create a DataFrame
df = pd.DataFrame({
'Fill Level (%)': fill_levels,
'Height (m)': heights,
'Volume (m^3)': volumes,
'Liquid Weight (kg)': liquid_weights,
'Total Weight (kg)': total_weights,
'Wetted Surface Area (m^2)': wetted_areas,
'Dry Surface Area (m^2)': dry_areas,
'Exposed Liquid Surface Area (m^2)': cross_sectional_areas
})
return df
df = tank_strapping_chart_detailed(tank, intervals=10, dry_weight=5000) # for a dry weight of 5000 kg
df
[5]:
Fill Level (%) | Height (m) | Volume (m^3) | Liquid Weight (kg) | Total Weight (kg) | Wetted Surface Area (m^2) | Dry Surface Area (m^2) | Exposed Liquid Surface Area (m^2) | |
---|---|---|---|---|---|---|---|---|
0 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 5000.000000 | 0.000000 | 131.364674 | 0.000000 |
1 | 0.111111 | 0.379077 | 5.893393 | 5893.392635 | 10893.392635 | 25.421906 | 105.942768 | 22.991978 |
2 | 0.222222 | 0.758155 | 16.257248 | 16257.247829 | 21257.247829 | 38.260995 | 93.103679 | 30.940749 |
3 | 0.333333 | 1.137232 | 28.929098 | 28929.097826 | 33929.097826 | 49.590488 | 81.774186 | 35.466005 |
4 | 0.444444 | 1.516309 | 42.843948 | 42843.947653 | 47843.947653 | 60.368404 | 70.996270 | 37.582422 |
5 | 0.555556 | 1.895387 | 57.156052 | 57156.052347 | 62156.052347 | 70.996270 | 60.368404 | 37.582422 |
6 | 0.666667 | 2.274464 | 71.070902 | 71070.902174 | 76070.902174 | 81.774186 | 49.590488 | 35.466005 |
7 | 0.777778 | 2.653542 | 83.742752 | 83742.752171 | 88742.752171 | 93.103679 | 38.260995 | 30.940749 |
8 | 0.888889 | 3.032619 | 94.106607 | 94106.607365 | 99106.607365 | 105.942768 | 25.421906 | 22.991978 |
9 | 1.000000 | 3.411696 | 100.000000 | 100000.000000 | 105000.000000 | 131.364674 | 0.000000 | 0.000000 |