Skip to content

How a VSA cycle works ​

A vacuum swing adsorption (VSA) process separates CO₂ from flue gas with a bed of adsorbent that holds CO₂ much more strongly than N₂. The bed is fed at about atmospheric pressure, so CO₂ is taken up while N₂ passes through. The bed is then evacuated, and the CO₂ that comes off is the product. The bed repeats the same steps over and over.

This page follows the four-step cycle of Haghpanah et al. (2013), which is in Mocca's library, through one steady cycle.

feed1PressurisationPL​ → PH​ N₂-rich productfeed2Adsorptionat PH​ N₂ and some CO₂3BlowdownPH​ → PI​ CO₂ product4EvacuationPI​ → PL​
One bed through the four steps. The shading is the CO₂ held on the adsorbent; it is drawn as a sharp front for clarity, which the real profile is not.
StepDurationOpenPressureWhat happens
Pressurisation15 sfeed, at the bottom0.1 → 1 barFeed gas fills the evacuated bed.
Adsorption15 sfeed at the bottom, product at the top1 barCO₂ is taken up near the feed end; N₂-rich gas leaves at the top.
Blowdown30 stop1 → 0.2 barMost of the N₂ left in the bed leaves through the top, with some CO₂.
Evacuation40 sbottom0.2 → 0.1 barThe vacuum pump draws the CO₂ off the adsorbent: the product.

The bottom of the bed is the feed end, z = 0, and the top the light product end, z = L. The steps are described on the Cycle steps page.

Running the cycle ​

Read the process, run it to cyclic steady state and measure it:

julia
using Mocca, Mocca.Units, CairoMakie
process = Mocca.read_process("haghpanah_2013_four_stage_vsa")
result = Mocca.cyclic_steady_state(process; progress = false)
perf = Mocca.performance(result)
println("purity $(round(100perf.purity, digits = 1))%, recovery $(round(100perf.recovery, digits = 1))%, ",
    "$(round(perf.specific_energy, digits = 1)) kWh per tonne of CO₂")
purity 79.5%, recovery 36.7%, 141.3 kWh per tonne of CO₂

At this evacuation pressure the cycle recovers only about a third of the CO₂ fed. The figures below show where the rest goes.

The pressure ​

The pressure at the two ends of the bed through the cycle:

Pressurisation takes the bed from 0.1 to 1 bar in about 10 s. During adsorption the feed end is about 0.02 bar above the top: the pressure drop of the gas flowing through the bed. Otherwise the two ends move together, as blowdown takes the bed to 0.2 bar and evacuation to 0.1 bar.

Where the CO₂ is held ​

Mole fractions and loadings along the bed at the end of each step:

julia
bed = process.flowsheet[:Bed]
step_ends = cumsum([st.duration for st in stages])
Mocca.plot_profiles(result.states, result.timesteps, bed, step_ends;
    labels = [st.name for st in stages], unit = :Bed)

Evacuated only to 0.1 bar, the adsorbent stays more than half loaded with CO₂ all along the bed. Each cycle uses just the difference between the loading at the end of adsorption and at the end of evacuation, under 2% of its saturation capacity. The bed is so full that at the end of adsorption the gas at the top already holds about 9% CO₂. Blowdown removes most of the N₂, and at the end of evacuation the gas in the bed is 77 to 97% CO₂.

What leaves the bed ​

The flow through each valve, and the CO₂ mole fraction in it, over the cycle:

julia
Mocca.plot_flowsheet_streams(result.states, process.model, result.timesteps; stages = stages)

The feed valve fills the bed during pressurisation and then delivers a steady 1 mol/s during adsorption. The product line carries about 9% CO₂ during adsorption and up to 40% in blowdown. That CO₂ is lost with the light product, which is why the recovery is low. The vacuum line delivers 60% CO₂ at first, rising to 97% as the bed empties.

How the purity, recovery and energy are worked out from these streams is on the Model equations page, under Performance.

The cyclic steady state ​

A bed that starts from some initial state ends each cycle a little different from how it began. After enough cycles the state at the end of a cycle is the state it started from: the cyclic steady state, where the performance is measured. Running cycle after cycle would take hundreds of cycles to get there. cyclic_steady_state runs three plain cycles and then solves for the steady state by Newton's method, which needs fewer than twenty more. The largest relative change of any variable over a cycle, at each step:

The plain cycles take out the fastest changes. Far from the steady state, the first Newton steps make the change larger before they bring it down; Newton's method cuts back any step that would make it far worse. From there each iteration reduces the change by a factor of about ten, to 10⁻¹⁰ after 17 iterations. The Cyclic steady state page describes the methods and their options.

Changing a setting ​

Each run from the last steady state of the process starts close to the new one, so a sweep of a setting is quick. The evacuation pressure from 0.03 to 0.15 bar:

julia
P_L = [0.03, 0.05, 0.07, 0.1, 0.15] .* bar
runs = map(P_L) do p
    process[:P_L] = p
    Mocca.performance(Mocca.cyclic_steady_state(process; progress = false))
end

A lower evacuation pressure takes more CO₂ off the adsorbent each cycle, so recovery rises steeply: from 12% at 0.15 bar to 82% at 0.03 bar. Purity changes much less and is highest near 0.07 bar. The energy per tonne is lowest between 0.07 and 0.1 bar. Below that range the pump does more work for each mole; above it, too little CO₂ is recovered to share the work.

To go further, the Gradients at cyclic steady state example gets the sensitivity to every setting at once, and Optimization of a cyclic process searches for the best settings.