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

\[C_p = a + b \cdot S^n\]

Quadratic log-log

\[\log_{10} C_p = K_1 + K_2 \log_{10} S + K_3 \left(\log_{10} S\right)^2\]

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):

\[C_{\text{target}} = C_{\text{ref}} \times \frac{\text{CEPCI}_{\text{target}}}{\text{CEPCI}_{\text{ref}}}\]

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:

\[C_D = C_p \left[ (1 + f_p) \cdot f_m + \left( f_{er} + f_{el} + f_i + f_c + f_s + f_l \right) \right]\]

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:

  1. Looks up the matching cost correlation from cost_correlations.csv.

  2. Computes the purchased cost, with automatic parallelization if the size parameter exceeds the correlation’s upper bound.

  3. Inflates the cost to the target year using CEPCI.

  4. Applies process and material factors to produce the direct (installed) cost.

Constructor parameters

Parameter

Type

Description

name

str

Identifier for this equipment item (used in plots and reports).

param

float

Size/capacity parameter. Units depend on the equipment type — check cost_correlations.csv. Ignored when purchased_cost is given.

process_type

str

"Solids", "Fluids", "Mixed", or "Electrical" — controls default installation factor values.

category

str

Equipment category — must match a row in cost_correlations.csv (case-insensitive).

type

str or None

Equipment sub-type within the category. Required when a category has multiple types.

material

str

Construction material — controls the material factor \(f_m\). Default: "Carbon steel".

target_year

int

Year to inflate costs to. Default: 2024.

purchased_cost

float or None

Supply your own purchased cost and bypass the correlation entirely.

cost_year

int or None

Reference year of a manually supplied purchased_cost. If given, CEPCI inflation is applied from this year to target_year.

cost_func

str or None

Explicit correlation key (the key column in the CSV). Use this to select a specific correlation when multiple exist for the same category/type.

num_units

int or None

Override the number of parallel units. By default this is set automatically by the parallelization logic.

piping_factor, erection_factor, … lagging_factor

float or None

Per-factor overrides. None uses the process_type default.

material_factor

float or None

Override the material factor. None uses the material table.

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\)

"Carbon steel"

1.00

"Aluminum"

1.07

"Bronze"

1.07

"Cast steel"

1.10

"304 stainless steel"

1.30

"316 stainless steel"

1.30

"321 stainless steel"

1.50

"Hastelloy C"

1.55

"Monel"

1.65

"Nickel"

1.70

"Inconel"

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

References