Python Project: Rankine Cycle Analyzer
In this capstone lesson we combine everything from the course — property evaluation, the first and second laws, control-volume energy balances, isentropic efficiency, and the Rankine cycle — into one reusable Python tool. Given operating conditions, it computes every state point, all work and heat terms, the thermal efficiency, and the back-work ratio, then draws the T-s diagram and sweeps parameters.
The Rankine Cycle Recap
The Rankine cycle is the workhorse of steam power plants. Four components form the loop:
| Process | Component | Ideal behavior |
|---|---|---|
| 1 → 2 | Pump | Isentropic compression of saturated liquid |
| 2 → 3 | Boiler | Constant-pressure heat addition $q_{in}$ |
| 3 → 4 | Turbine | Isentropic expansion producing $w_{turbine}$ |
| 4 → 1 | Condenser | Constant-pressure heat rejection $q_{out}$ |
The defining metrics:
April batch closing soon — only 42 seats remaining
Join 3,000+ engineers who got placed at top companies
$$w_{net} = w_{turbine} - w_{pump}, \qquad \eta_{th} = \frac{w_{net}}{q_{in}}, \qquad \text{BWR} = \frac{w_{pump}}{w_{turbine}}$$
Real turbines and pumps are irreversible, so we apply isentropic efficiencies:
$$\eta_t = \frac{h_3 - h_4}{h_3 - h_{4s}} \;(\text{turbine}), \qquad \eta_p = \frac{h_{2s} - h_1}{h_2 - h_1}\;(\text{pump})$$
Gaurav Jadhav is now a CAE Engineer
Practical projects and mock interviews made the difference
Project Structure
rankine_analyzer/
├── rankine.py # RankineCycle class (state points, energy balances)
├── plotting.py # T-s diagram and parameter sweeps
└── examples.py # Runnable example cases
Complete Implementation
import numpy as np
import matplotlib.pyplot as plt
from CoolProp.CoolProp import PropsSI
FLUID = "Water"
class RankineCycle:
"""
Steam Rankine power-cycle analyzer.
Parameters
----------
p_boiler : boiler (turbine inlet) pressure, Pa
p_cond : condenser pressure, Pa
T_boiler : turbine inlet temperature, K. If None, steam is saturated
vapor at p_boiler (no superheat).
eta_turb : turbine isentropic efficiency (0-1)
eta_pump : pump isentropic efficiency (0-1)
reheat : if True, expand to p_reheat, reheat to T_reheat, then expand.
p_reheat : reheat pressure, Pa (required if reheat=True)
T_reheat : reheat temperature, K (required if reheat=True)
"""
def __init__(self, p_boiler, p_cond, T_boiler=None,
eta_turb=1.0, eta_pump=1.0,
reheat=False, p_reheat=None, T_reheat=None):
self.p_boiler = p_boiler
self.p_cond = p_cond
self.T_boiler = T_boiler
self.eta_turb = eta_turb
self.eta_pump = eta_pump
self.reheat = reheat
self.p_reheat = p_reheat
self.T_reheat = T_reheat
self.states = {}
self.results = {}
# ---- helper ----
@staticmethod
def _state(p, h):
"""Return a dict of T, s, x for given p and h."""
return {
"p": p,
"h": h,
"T": PropsSI("T", "P", p, "H", h, FLUID),
"s": PropsSI("S", "P", p, "H", h, FLUID),
"x": PropsSI("Q", "P", p, "H", h, FLUID),
}
def solve(self):
f = FLUID
# State 1: saturated liquid leaving condenser
h1 = PropsSI("H", "P", self.p_cond, "Q", 0, f)
s1 = PropsSI("S", "P", self.p_cond, "Q", 0, f)
v1 = 1.0 / PropsSI("D", "P", self.p_cond, "Q", 0, f)
# State 2: pump to boiler pressure
h2s = PropsSI("H", "P", self.p_boiler, "S", s1, f)
w_pump_s = h2s - h1 # ideal pump work
w_pump = w_pump_s / self.eta_pump # actual pump work
h2 = h1 + w_pump
# State 3: boiler exit (turbine inlet)
if self.T_boiler is None:
h3 = PropsSI("H", "P", self.p_boiler, "Q", 1, f) # saturated vapor
s3 = PropsSI("S", "P", self.p_boiler, "Q", 1, f)
else:
h3 = PropsSI("H", "P", self.p_boiler, "T", self.T_boiler, f)
s3 = PropsSI("S", "P", self.p_boiler, "T", self.T_boiler, f)
w_turb = 0.0
if not self.reheat:
# State 4: turbine expansion to condenser pressure
h4s = PropsSI("H", "P", self.p_cond, "S", s3, f)
w_t = self.eta_turb * (h3 - h4s)
h4 = h3 - w_t
w_turb += w_t
self.states = {
1: self._state(self.p_cond, h1),
2: self._state(self.p_boiler, h2),
3: self._state(self.p_boiler, h3),
4: self._state(self.p_cond, h4),
}
q_in = h3 - h2
else:
# Stage 1: expand boiler -> reheat pressure
ha_s = PropsSI("H", "P", self.p_reheat, "S", s3, f)
wa = self.eta_turb * (h3 - ha_s)
ha = h3 - wa
# Reheat at p_reheat to T_reheat
hb = PropsSI("H", "P", self.p_reheat, "T", self.T_reheat, f)
sb = PropsSI("S", "P", self.p_reheat, "T", self.T_reheat, f)
# Stage 2: expand reheat pressure -> condenser
h4s = PropsSI("H", "P", self.p_cond, "S", sb, f)
wb = self.eta_turb * (hb - h4s)
h4 = hb - wb
w_turb = wa + wb
self.states = {
1: self._state(self.p_cond, h1),
2: self._state(self.p_boiler, h2),
3: self._state(self.p_boiler, h3),
"a": self._state(self.p_reheat, ha),
"b": self._state(self.p_reheat, hb),
4: self._state(self.p_cond, h4),
}
q_in = (h3 - h2) + (hb - ha)
q_out = self.states[4]["h"] - h1
w_net = w_turb - w_pump
self.results = {
"w_turbine": w_turb,
"w_pump": w_pump,
"w_net": w_net,
"q_in": q_in,
"q_out": q_out,
"eta_th": w_net / q_in,
"bwr": w_pump / w_turb,
"x_turbine_exit": self.states[4]["x"],
}
return self.results
def report(self):
if not self.results:
self.solve()
r = self.results
print("=" * 55)
print("RANKINE CYCLE ANALYSIS")
print("=" * 55)
print(f"Boiler pressure: {self.p_boiler/1e5:8.2f} bar")
if self.T_boiler:
print(f"Turbine inlet T: {self.T_boiler-273.15:8.1f} C")
print(f"Condenser pressure:{self.p_cond/1e5:8.3f} bar")
if self.reheat:
print(f"Reheat: {self.p_reheat/1e5:.1f} bar / "
f"{self.T_reheat-273.15:.0f} C")
print(f"Turbine eff.: {self.eta_turb:8.2f}")
print(f"Pump eff.: {self.eta_pump:8.2f}")
print("-" * 55)
print(f"Turbine work: {r['w_turbine']/1000:8.1f} kJ/kg")
print(f"Pump work: {r['w_pump']/1000:8.2f} kJ/kg")
print(f"Net work: {r['w_net']/1000:8.1f} kJ/kg")
print(f"Heat in: {r['q_in']/1000:8.1f} kJ/kg")
print(f"Heat out: {r['q_out']/1000:8.1f} kJ/kg")
print(f"Thermal efficiency:{r['eta_th']*100:8.2f} %")
print(f"Back-work ratio: {r['bwr']*100:8.2f} %")
x = r['x_turbine_exit']
x_str = f"{x:.3f}" if 0 <= x <= 1 else "superheated"
print(f"Turbine exit quality: {x_str}")
print("=" * 55)