Chemical Engineering¶
This walkthrough demonstrates dimensional analysis for chemical engineering calculations---a domain where stoichiometry chains, molar conversions, and logarithmic measures like pH demand rigorous unit tracking.
Each example shows two approaches:
- Python API --- Direct use of ucon in your code
- MCP Server --- Via AI agents like Claude
Why Dimensional Analysis Matters¶
Chemical engineering calculations chain through multiple conversion factors: mass to moles (via molar mass), moles to concentration (via volume), concentration to pH (via logarithm). A single unit error in a stoichiometry chain propagates through every downstream step. Dimensional analysis catches these errors at each link.
Solution Preparation¶
Problem: Calculate the mass of NaOH required to prepare 500 mL of 0.1 M solution. The molar mass of NaOH is 40.00 g/mol.
Python API¶
from ucon import units, Scale
mg = Scale.milli * units.gram
mL = Scale.milli * units.liter
mol_per_liter = units.mole / units.liter
# Givens
target_concentration = mol_per_liter(0.1) # 0.1 M
target_volume = mL(500) # 500 mL
molar_mass = (units.gram / units.mole)(40.00) # 40.00 g/mol
# Chain: concentration x volume = moles, moles x molar_mass = mass
moles_needed = target_concentration * target_volume
print(moles_needed) # <0.05 mol>
mass_needed = moles_needed * molar_mass
print(mass_needed) # <2.0 g>
MCP Server¶
compute(
initial_value=0.1,
initial_unit="mol/L",
factors=[
{"value": 500, "numerator": "mL", "denominator": "1000 mL/L"},
{"value": 40.00, "numerator": "g", "denominator": "mol"},
]
)
Step trace:
| Step | Factor | Dimension | Result |
|---|---|---|---|
| 0 | 0.1 mol/L | concentration | 0.1 mol/L |
| 1 | x (500 mL / 1000 mL/L) | amount | 0.05 mol |
| 2 | x (40.00 g / mol) | mass | 2.0 g |
pH and Concentration¶
Problem: Given a hydrogen ion concentration of 1 x 10^-3 mol/L (vinegar), find the pH. Then convert pH 7 back to concentration.
ucon models pH as a logarithmic unit with concentration dimension, using LogMap under the hood: pH = -log10([H+]).
Python API¶
from ucon import units
mol_per_liter = units.mole / units.liter
# Concentration to pH
vinegar = mol_per_liter(1e-3)
ph = vinegar.to(units.pH)
print(ph) # <3.0 pH>
# pH to concentration
neutral = units.pH(7.0)
concentration = neutral.to(mol_per_liter)
print(concentration) # <1e-07 mol/L>
MCP Server¶
convert(value=1e-3, from_unit="mol/L", to_unit="pH")
# -> {"quantity": 3.0, "unit": "pH", "dimension": "concentration"}
convert(value=7.0, from_unit="pH", to_unit="mol/L")
# -> {"quantity": 1e-7, "unit": "mol/L", "dimension": "concentration"}
Logarithmic Conversions
The pH conversion uses a LogMap internally: pH = -1 * log10(x / 1 mol/L). The inverse (ExpMap) recovers concentration from pH. Both directions are exact round-trips.
Reaction Yield with Uncertainty¶
Problem: A reaction produces 4.82 +/- 0.15 g of product from 5.00 +/- 0.02 g of limiting reagent (theoretical yield: 6.00 g based on stoichiometry). Calculate the percent yield with uncertainty.
Python API¶
from ucon import units
# Actual yield with measurement uncertainty
actual = units.gram(4.82, uncertainty=0.15)
# Theoretical yield from stoichiometry (known precisely)
theoretical = units.gram(6.00)
# Yield ratio: actual / theoretical
yield_ratio = actual / theoretical
print(yield_ratio) # <0.8033... +/- 0.025 frac>
# Convert to percent
yield_pct = yield_ratio.to(units.percent)
print(yield_pct) # <80.3 +/- 2.5 %>
Uncertainty propagates automatically through division via quadrature: the 0.15 g uncertainty on the numerator becomes a 2.5% uncertainty on the yield.
MCP Server¶
# Step 1: compute the ratio
compute(
initial_value=4.82,
initial_unit="g",
factors=[
{"value": 1, "numerator": "1", "denominator": "6.00 g"},
]
)
# -> {"quantity": 0.8033, "unit": "fraction", "dimension": "ratio"}
# Step 2: convert to percent
convert(value=0.8033, from_unit="fraction", to_unit="%")
# -> {"quantity": 80.33, "unit": "%", "dimension": "ratio"}
Uncertainty in MCP
The MCP compute tool does not currently propagate uncertainty. For uncertainty-aware calculations, use the Python API directly.
Multi-Step Dilution Chain¶
Problem: You have a 12 M stock solution of HCl. Prepare 250 mL of 0.5 M working solution. How much stock do you need?
This uses the dilution equation: C1 x V1 = C2 x V2, rearranged as V1 = C2 x V2 / C1.
Python API¶
from ucon import units, Scale
mL = Scale.milli * units.liter
mol_per_liter = units.mole / units.liter
# Givens
stock_conc = mol_per_liter(12.0) # 12 M stock
target_conc = mol_per_liter(0.5) # 0.5 M target
target_vol = mL(250) # 250 mL target volume
# Moles needed: target concentration x target volume
moles_needed = target_conc * target_vol
print(moles_needed) # <0.125 mol>
# Volume of stock: moles / stock concentration
stock_vol = moles_needed / stock_conc
print(stock_vol) # <0.01042 L> ~ 10.4 mL
MCP Server¶
compute(
initial_value=0.5,
initial_unit="mol/L",
factors=[
{"value": 250, "numerator": "mL", "denominator": "1000 mL/L"},
{"value": 1, "numerator": "L", "denominator": "12 mol"},
]
)
Step trace:
| Step | Factor | Dimension | Result |
|---|---|---|---|
| 0 | 0.5 mol/L | concentration | 0.5 mol/L |
| 1 | x (250 mL / 1000 mL/L) | amount | 0.125 mol |
| 2 | x (1 L / 12 mol) | volume | 0.01042 L (10.4 mL) |
Dimensional Safety¶
ucon prevents nonsensical conversions in both interfaces.
Moles Are Not Grams¶
from ucon import units
from ucon.graph import ConversionNotFound
moles = units.mole(0.5)
try:
moles.to(units.gram) # mol -> g requires molar mass!
except ConversionNotFound:
print("Cannot convert amount to mass without molar mass")
Concentration Requires Volume¶
mol_per_liter = units.mole / units.liter
concentration = mol_per_liter(0.1)
try:
concentration.to(units.gram) # mol/L -> g makes no sense
except ConversionNotFound:
print("Cannot convert concentration directly to mass")
MCP Server¶
convert(value=0.5, from_unit="mol", to_unit="g")
# -> {
# "error": "Dimension mismatch: amount_of_substance != mass",
# "error_type": "dimension_mismatch",
# "likely_fix": "Use molar mass to bridge amount_of_substance and mass"
# }
Key Takeaways¶
- Stoichiometry is dimensional analysis --- concentration x volume = moles, moles x molar mass = mass
- pH is a logarithmic unit --- ucon handles the log/exp conversion automatically via
LogMap - Uncertainty propagates through arithmetic --- measurement errors on mass become errors on yield
- Moles are not grams --- you need molar mass to bridge amount and mass dimensions
- Both interfaces validate dimensions --- errors are caught, not silently computed