"""
Constants and unit conversions.
"""
import numpy as np
import pandas as pd
from tabulate import tabulate
from requests.structures import CaseInsensitiveDict
### Unit conversions ###
[docs]
def T_in_K(
T: float,
) -> float:
"""Convert celcius to Kelvin.
Args:
T (float): Temperature in Celcius.
Returns:
float: Temperature in Kelvin.
"""
return T + STANDARD_TEMPERATURE_K
[docs]
def P_in_Pa(
P: float,
units: str,
) -> float:
"""Convert pressure to Pa.
Args:
P (float): Pressure.
units (float): Supported pressure units: Torr, bar, mbar, or
hPa.
Returns:
float: Pressure in Pa.
"""
return P * P_CF[units]
### Geometric Calculations ###
[docs]
def cross_sectional_area(
diameter: float,
) -> float:
"""Calculate cross sectional area.
Args:
diameter (float): Diameter.
Returns:
float: Cross sectional area.
"""
return np.pi * (diameter / 2) ** 2
[docs]
def partial_cylinder_area(
height: float,
width: float,
) -> tuple[float, float]:
"""
Calculate the cross-sectional area and perimeter of a partial
cylinder ("boat") given its height and width. Assumes the partial
cylinder is a segment of a circle with given width as chord length
and that the height is less than the diameter of the circle.
Calculations based on:
https://mathworld.wolfram.com/CircularSegment.html and
https://www.vcalc.com/wiki/KurtHeckman/Circle-area-of-an-arc-segment-h.
Args:
height (float): Height of the segment (cm).
width (float): Chord length of the segment (cm).
Returns:
float: Outer perimeter (cm).
float: Cross-sectional area (cm^2).
"""
# Ensure the proper geometry for the following calculation
if height > width / 2:
raise ValueError("Boat height cannot be greater than boat radius.")
# Calculate radius from height and chord length
r = (height / 2) + (width**2 / (8 * height))
# Central angle (theta) in radians
theta = 2 * np.arccos((r - height) / r)
# Arc length
arc_length = r * theta
# Wetted perimeter
perimeter = arc_length + width
# Area of the segment
area = (r**2 / 2) * (theta - np.sin(theta))
return perimeter, area
### Display Calculations ###
[docs]
def table(
title: str,
var_names: list[str],
var: list[float],
var_fmts: list[str],
units: list[str],
) -> None:
"""Print a formatted table of variables.
Args:
title (str): Title of the table.
var_names (list): List of variable names.
var (list): Variable values.
var_fmts (list): List of formats for each variable.
units (list): List of units for each variable.
Returns:
None
"""
data = pd.DataFrame(
[var_names, [format(v, "8" + fmt) for v, fmt in zip(var, var_fmts)], units]
).T
table = tabulate(
data, # pyright: ignore[reportArgumentType]
disable_numparse=True,
tablefmt="fancy_grid",
showindex=False,
)
# Center the title based on the table width
width = len(table.splitlines()[0])
print(f"\033[1m{title}\033[0m".center(width))
print(table)
### Constants ###
STANDARD_TEMPERATURE_K = 273.15 # K
STANDARD_PRESSURE_Pa = 101325 # Pa
UNIVERSAL_GAS_CONSTANT = 8.3145 # kg m2 s-2 K-1 mol-1
BOLTZMANN_CONSTANT = 1.380649e-23 # kg m2 s-2 K-1
AVOGADROS_NUMBER = 6.0221408e23 # mol-1
P_CF = CaseInsensitiveDict(
{
"Torr": 133.322,
"bar": 1e5,
"mbar": 100,
"hPa": 100,
"Pa": 1,
}
) # conversion factors to Pa