Equipment Cost Estimation¶
The openpytea.equipment module estimates purchased and installed costs
for individual process units using published cost correlations, automatic CEPCI
inflation adjustment, and process/material installation factors.
How costs are estimated¶
Purchased cost correlations¶
Two correlation forms are supported:
Power-law
Quadratic log-log
where \(S\) is the equipment size parameter (e.g., shaft power in kW, heat transfer area in m²) and \(C_p\) is the purchased cost in the correlation’s reference year (USD).
All correlations and their coefficients are stored in
cost_correlations.csv.
OpenPyTEA does not require a database match. You can bypass the built-in
correlations entirely and supply your own purchased_cost directly — for
vendor quotes, proprietary data, or equipment types not yet in the database.
See Example 3 below.
CEPCI inflation adjustment¶
Purchased costs are inflated from the correlation’s reference year to the target year using the Chemical Engineering Plant Cost Index (CEPCI):
Historical CEPCI values are bundled with the package in
cepci_values.csv.
The default target year is 2024.
The bundled values are sourced from the University of Manchester CEPCI table (accessed 7 April 2026). Users are encouraged to verify these values and, if more recent or detailed data are available, replace them by editing ``cepci_values.csv`` directly before running their analysis.
Direct (installed) cost¶
The direct cost adds installation contributions on top of the purchased cost:
where \(f_m\) is the material factor and \(f_p\), \(f_{er}\),
\(f_{el}\), \(f_i\), \(f_c\), \(f_s\), \(f_l\) are the
piping, erection, electrical, instrumentation, civil, structural, and lagging
factors respectively. Default installation factor values depend on the process_type
(see Process installation factors below). All factors can be overridden per equipment
item via constructor keyword arguments — see Example 8 for details.
Source: Towler & Sinnott (2022)
The Equipment class¶
from openpytea import Equipment
Each Equipment object represents one piece of
process equipment. On construction it automatically:
Looks up the matching cost correlation from
cost_correlations.csv.Computes the purchased cost, with automatic parallelization if the size parameter exceeds the correlation’s upper bound.
Inflates the cost to the target year using CEPCI.
Applies process and material factors to produce the direct (installed) cost.
Constructor parameters¶
Parameter |
Type |
Description |
|---|---|---|
|
str |
Identifier for this equipment item (used in plots and reports). |
|
float |
Size/capacity parameter. Units depend on the equipment type —
check |
|
str |
|
|
str |
Equipment category — must match a row in |
|
str or None |
Equipment sub-type within the category. Required when a category has multiple types. |
|
str |
Construction material — controls the material factor \(f_m\).
Default: |
|
int |
Year to inflate costs to. Default: |
|
float or None |
Supply your own purchased cost and bypass the correlation entirely. |
|
int or None |
Reference year of a manually supplied |
|
str or None |
Explicit correlation key (the |
|
int or None |
Override the number of parallel units. By default this is set automatically by the parallelization logic. |
|
float or None |
Per-factor overrides. |
|
float or None |
Override the material factor. |
Usage examples¶
The examples below show the main ways to create Equipment objects.
To see the printed outputs of each code cell, refer to the
walkthrough notebook.
Example 1 — Standard usage¶
Define a heat exchanger using a correlation from the database:
from openpytea import Equipment
hx = Equipment(
name="HX-101",
param=250, # heat transfer area in m²
process_type="Fluids",
category="Heat exchangers",
type="Floating head",
material="316 stainless steel",
target_year=2024,
)
print(hx)
print(f"Purchased cost : ${hx.purchased_cost:,.0f}")
print(f"Direct cost : ${hx.direct_cost:,.0f}")
Example 2 — Selecting a specific correlation key¶
When multiple correlations cover the same equipment type (e.g., compressors
from different studies), use cost_func to pin the exact database key:
comp = Equipment(
name="COMP-01",
param=1, # net electric power, MW
process_type="Fluids",
category="Compressors, fans, & blowers",
type="Compressor, centrifugal",
material="Carbon steel",
cost_func="co2_compressor_manzolini_2011",
)
print(comp)
Example 3 — Manually specified purchased cost¶
Skip the correlation entirely and supply your own cost. If you also provide
cost_year, CEPCI inflation to target_year is applied automatically:
dryer = Equipment(
name="Rotary Dryer D-301",
param=0, # ignored when purchased_cost is set
process_type="Solids",
category="Dryers",
material="Carbon steel",
purchased_cost=1_500_000, # vendor quote in 2021 USD
cost_year=2021, # inflated to target_year=2024
)
print(dryer)
Example 4 — Automatic parallelization¶
When param exceeds the correlation’s upper capacity limit, the module
splits the load into the minimum number of equal parallel units:
# The centrifugal compressor correlation is valid up to 30 000 kW.
# Requesting 50 000 kW triggers automatic splitting into 2 units.
large_comp = Equipment(
name="COMP-LARGE",
param=50_000, # driver power in kW
process_type="Fluids",
category="Compressors, fans, & blowers",
type="Compressor, centrifugal",
material="Carbon steel",
)
print(large_comp)
print(f"Number of parallel units: {large_comp.num_units}")
Example 5 — Inflation to a custom target year¶
hx_2020 = Equipment(
name="HX-102",
param=250,
process_type="Fluids",
category="Heat exchangers",
type="Floating head",
material="316 stainless steel",
target_year=2020, # inflate to 2020 instead of 2024
)
print(hx_2020)
Example 6 — Fixing the number of units manually¶
fridge = Equipment(
name="Refrigerator R-201",
param=180,
process_type="Fluids",
category="Utilities",
type="Packaged mechanical refrigerator",
num_units=3, # bypass auto-parallelization
)
print(fridge)
Example 7 — Comparing materials¶
The material factor \(f_m\) multiplies the installed cost. Here the same agitator is costed in carbon steel versus Hastelloy C:
mixer_cs = Equipment(
name="Agitator M-101",
param=100,
process_type="Fluids",
category="Agitators, blenders, & mixers",
type="Propeller mixer",
material="Carbon steel", # fm = 1.00
)
mixer_alloy = Equipment(
name="Agitator M-101 (Hastelloy)",
param=100,
process_type="Fluids",
category="Agitators, blenders, & mixers",
type="Propeller mixer",
material="Hastelloy C", # fm = 1.55
)
print(f"Carbon steel direct cost : ${mixer_cs.direct_cost:,.0f}")
print(f"Hastelloy C direct cost : ${mixer_alloy.direct_cost:,.0f}")
Example 8 — Overriding installation factors¶
Individual installation factors can be overridden without affecting the rest.
The class attributes process_factors and material_factors show all
defaults:
# Inspect defaults first
print(Equipment.process_factors["Fluids"])
print(Equipment.material_factors["316 stainless steel"])
reactor = Equipment(
name="Reactor R-101",
param=50,
process_type="Fluids",
category="Reactors",
type="Glass-lined agitated",
material="316 stainless steel",
piping_factor=0.95, # override default 0.80
material_factor=1.4, # override default 1.30
)
print(f"piping_factor : {reactor.piping_factor}")
print(f"material_factor : {reactor.material_factor}")
Listing available equipment¶
Print all categories and types in the built-in database:
from openpytea.equipment import CostCorrelationDB, COST_DB_DF
db = CostCorrelationDB(COST_DB_DF)
# All unique categories
print(db.df["category"].unique())
# All types and metadata for a specific category
mask = db.df["category"].str.lower() == "heat exchangers"
print(db.df.loc[mask, ["type", "form", "cost_year", "source"]])
You can also download the full database:
cost_correlations.csv
Available materials¶
The table below lists the valid material strings and their factors
\(f_m\). Costs are relative to carbon steel (= 1.0).
Source: Towler & Sinnott (2022)
Material |
Factor \(f_m\) |
|---|---|
|
1.00 |
|
1.07 |
|
1.07 |
|
1.10 |
|
1.30 |
|
1.30 |
|
1.50 |
|
1.55 |
|
1.65 |
|
1.70 |
|
1.70 |
Process installation factors¶
Default installation factors by process_type. Any factor can be
overridden per equipment item via the corresponding constructor keyword
(e.g., piping_factor=0.95).
Source: Towler & Sinnott (2022)
Factor |
Solids |
Fluids |
Mixed |
Electrical |
|---|---|---|---|---|
Erection \((f_{er})\) |
0.60 |
0.30 |
0.50 |
0.40 |
Piping \((f_p)\) |
0.20 |
0.80 |
0.60 |
0.10 |
Instrumentation \((f_i)\) |
0.20 |
0.30 |
0.30 |
0.70 |
Electrical \((f_{el})\) |
0.15 |
0.20 |
0.20 |
0.70 |
Civil \((f_c)\) |
0.20 |
0.30 |
0.30 |
0.20 |
Structural steel \((f_s)\) |
0.10 |
0.20 |
0.20 |
0.10 |
Lagging & painting \((f_l)\) |
0.05 |
0.10 |
0.10 |
0.10 |
Standalone inflation adjustment¶
The inflation_adjustment() function can be used
independently to convert any cost between years:
from openpytea import inflation_adjustment
# Convert a $500 000 cost quoted in 2015 to 2024 USD
adjusted = inflation_adjustment(500_000, cost_year=2015, target_year=2024)
print(f"2015 cost: $500,000 → 2024 cost: ${adjusted:,.0f}")
See also¶
Equipment— full API referenceCostCorrelationDB— database interfaceinflation_adjustment()— CEPCI utilityWalkthrough notebook — end-to-end worked example
References¶
Towler, G.; Sinnott, R. Chemical Engineering Design, 3rd ed.; Elsevier, 2022. https://doi.org/10.1016/C2019-0-02025-0