Cyclic Vacuum Swing Adsorption simulation
This example shows how to set up and run a cyclic vacuum swing adsorption simulation as described in Haghpanah et al. 2013
This simulation inolves injection of a two component flue gas (CO2 and N2) into a column of Zeolite 13X. The CO2 is preferentially adsorbed onto the zeolite. Pressure in the column is then reduced to enable desorption of CO2 for collection.
This is a four stage process comprising:
- Pressurisation: Where the RHS of the column is closed and flue gas is injected from the LHS, at velocity $v_{feed}$, to bring the column pressure up to $P_H$ (Pressure High).
- Adsorption: Where both ends of the column are open and flue gas is injected from the RHS at velocity $v_{feed}$. Pressure at the LHS is $P_H$.
- Blowdown: Where the LHS of the column is closed and the column is evacuated at $P_I$ (Pressure Intermediate).
- Evacuation: Where the RHS of the column is closed and the column is evacuated from the LHS at $P_L$ (Pressure Low).
Each stage is modelled using the same governing equations but with different boundary conditions. Adsorption onto Zeolite 13X is modelled with a dual-site Langmuir adsorption isotherm.
First we load the necessary modules
import Jutul: si_unit
import MoccaWe define parameters, and set up the system and domain as in the Simulate DCB example.
constants = Mocca.HaghpanahConstants{Float64}()
system = Mocca.TwoComponentAdsorptionSystem(constants);Create the model
Now we can assemble the model which contains the domain and the system of equations.
ncells = 200
model = Mocca.setup_process_model(system; ncells = ncells);Setup the initial state and parameters
Initial values for pressure and temperature of the system
bar = si_unit(:bar);
P_init = 1*bar;
T_init = 298.15;
Tw_init = constants.T_a;To avoid numerical errors we set the initial CO2 concentration to be very small and not exactly zero
yCO2_2 = 1e-10
y_init = [yCO2_2, 1.0 - yCO2_2] # [CO2, N2]
state0 = Mocca.setup_process_state(model;
Pressure = P_init,
Temperature = T_init,
WallTemperature = Tw_init,
y = y_init
);
parameters = Mocca.setup_process_parameters(model);Set up the stage timings and boundary conditions
Here we have 4 stages and we specify a duration in seconds that we will run each stage.
t_press = 15.0
t_ads = 15.0
t_blow = 30.0
t_evac= 40.0
stage_times = [t_press, t_ads, t_blow, t_evac];
stage_names = ["pressurisation", "adsorption", "blowdown", "evacuation"]4-element Vector{String}:
"pressurisation"
"adsorption"
"blowdown"
"evacuation"Set up cyclic boundary conditions and timesteps for the simulation We will run 3 cycles of the process for demonstration purposes, to reach steady state num_cycles should be increased.
sim_forces, timesteps = Mocca.setup_forces(model,stage_times,stage_names;
num_cycles=3, max_dt = 1);Simulate
Now we are ready to run the simulation
case = Mocca.MoccaCase(model, timesteps, sim_forces; state0 = state0, parameters = parameters)
states, timesteps_out = Mocca.simulate_process(case;
output_substates = true,
info_level = 0
);Jutul: Simulating 5 minutes as 300 report steps
╭────────────────┬───────────┬───────────────┬───────────╮
│ Iteration type │ Avg/step │ Avg/ministep │ Total │
│ │ 300 steps │ 304 ministeps │ (wasted) │
├────────────────┼───────────┼───────────────┼───────────┤
│ Newton │ 2.64667 │ 2.61184 │ 794 (30) │
│ Linearization │ 3.66 │ 3.61184 │ 1098 (32) │
│ Linear solver │ 2.64667 │ 2.61184 │ 794 (30) │
│ Precond apply │ 0.0 │ 0.0 │ 0 (0) │
╰────────────────┴───────────┴───────────────┴───────────╯
╭───────────────┬────────┬────────────┬────────╮
│ Timing type │ Each │ Relative │ Total │
│ │ ms │ Percentage │ s │
├───────────────┼────────┼────────────┼────────┤
│ Properties │ 0.0551 │ 2.05 % │ 0.0438 │
│ Equations │ 0.5094 │ 26.26 % │ 0.5593 │
│ Assembly │ 0.0374 │ 1.93 % │ 0.0410 │
│ Linear solve │ 1.7123 │ 63.82 % │ 1.3596 │
│ Linear setup │ 0.0000 │ 0.00 % │ 0.0000 │
│ Precond apply │ 0.0000 │ 0.00 % │ 0.0000 │
│ Update │ 0.0399 │ 1.49 % │ 0.0317 │
│ Convergence │ 0.0338 │ 1.74 % │ 0.0371 │
│ Input/Output │ 0.0288 │ 0.41 % │ 0.0088 │
│ Other │ 0.0617 │ 2.30 % │ 0.0490 │
├───────────────┼────────┼────────────┼────────┤
│ Total │ 2.6830 │ 100.00 % │ 2.1303 │
╰───────────────┴────────┴────────────┴────────╯Visualisation
We plot primary variables at the outlet through time
outlet_cell = ncells
f_outlet = Mocca.plot_cell(states, model, timesteps_out, outlet_cell)
We also plot primary variables along the column at the end of the simulation
f_column = Mocca.plot_state(states[end], model)
Example on GitHub
If you would like to run this example yourself, it can be downloaded from the Mocca.jl GitHub repository.
This page was generated using Literate.jl.