Profiles / Chemistry & life
PR

Process & reactor engineer

Batch and continuous reactors, conversion, residence time and heat of reaction.

10 recipes on this page · open in the interactive view

Recipes
  1. Batch time to 90 % conversion
  2. CSTR versus PFR volume for 95 % conversion
  3. Adiabatic temperature rise and runaway check
  4. Yield model from a factorial design
  5. Shortcut column design: Fenske, Underwood, Gilliland
  6. Residence time distribution and tanks-in-series model
  7. Process capability of an API assay
  8. Production campaign planning
  9. Mass balance of a two-column distillation train
  10. Agitation scale-up at constant power per volume
executed on MentDB

Batch time to 90 % conversion

An isothermal batch reactor runs A + B -> C (k = 0.012 L/mol.min, CA0 = 1.5 and CB0 = 1.8 mol/L). The script integrates the mole balances and stops exactly when 90 % of A is converted (event), then checks the batch time against the analytic formula.

Pipeline
Script
admin
#1. A + B to C in a batch reactor, second order: k = 0.012 L/mol.min, CA0 = 1.5, CB0 = 1.8 mol/L;
#2. Integrate until 90 % conversion of A: event A - 0.15 = 0;
json load "rx_ch_br" (num ode "{\"A\": \"-0.012*A*B\", \"B\": \"-0.012*A*B\", \"C\": \"0.012*A*B\"}" "{\"A\": 1.5, \"B\": 1.8, \"C\": 0}" 0 1000 "{\"event\": \"A - 0.15\", \"direction\": -1}");
-> "[t90]" (json select "rx_ch_br" /event/t);
#3. Check with the analytic batch time for A + B with CA0 different from CB0;
-> "[t_an]" (math calc "1/(0.012*(1.8-1.5))*ln((0.45/1.8)/(0.15/1.5))");
concat "t(X = 90 %) = " (math round [t90] 2) " min (analytic " (math round [t_an] 2) " min), C formed = " (math round (json select "rx_ch_br" /event/C) 3) " mol/L"
Result
mentdb
t(X = 90 %) = 254.53 min (analytic 254.53 min), C formed = 1.35 mol/L
Go further
  • Add the cycle time (filling, heating, emptying) to size the reactor per year.
  • Draw A, B, C with plot ode.
executed on MentDB

CSTR versus PFR volume for 95 % conversion

A first order liquid reaction (A = 4.0e7 1/min, Ea = 60 kJ/mol) runs at 350 K with a feed of 2.5 m3/h. The script computes k by Arrhenius, the residence times tau = X/(k(1-X)) for a CSTR and -ln(1-X)/k for a PFR, then the reactor volumes in m3.

Pipeline
Script
admin
#1. First order liquid reaction at 350 K: A = 4.0e7 1/min, Ea = 60 kJ/mol;
-> "[k]" (math calc "4.0e7*exp(-60000/(_R*350))");
#2. Residence times for 95 % conversion: CSTR X/k.1-X, PFR -ln 1-X / k;
-> "[tc]" (math calc "0.95/([k]*(1-0.95))"); -> "[tp]" (math calc "-ln(1-0.95)/[k]");
#3. Reactor volumes for a feed of 2.5 m3/h;
-> "[vc]" (unit calc (concat "2.5 m3/h * " [tc] " min") "m3");
-> "[vp]" (unit calc (concat "2.5 m3/h * " [tp] " min") "m3");
concat "k = " (math round [k] 4) " 1/min; CSTR: tau = " (math round [tc] 0) " min, V = " (math round [vc] 1) " m3; PFR: tau = " (math round [tp] 0) " min, V = " (math round [vp] 1) " m3"
Result
mentdb
k = 0.0444 1/min; CSTR: tau = 428 min, V = 17.8 m3; PFR: tau = 67 min, V = 2.8 m3
Go further
  • Find the number of CSTRs in series that reach the PFR volume with num sum.
  • Optimize the temperature with num minimize on a cost function.
executed on MentDB

Adiabatic temperature rise and runaway check

An exothermic first order reaction (dHr = -85 kJ/mol, CA0 = 2.0 mol/L) is run in a batch without cooling, starting at 320 K. The script gives the adiabatic temperature rise dT_ad = (-dHr).CA0/(rho.cp), then integrates the coupled conversion and energy balances to find when 99 % conversion is reached and the maximum temperature.

Pipeline
Script
admin
#1. Adiabatic temperature rise: dHr = -85 kJ/mol, CA0 = 2.0 mol/L, rho = 1.05 kg/L, cp = 3.9 kJ/kg.K;
-> "[dtad]" (unit calc "85 kJ/mol * 2.0 mol/L / (1.05 kg/L * 3.9 kJ/(kg*K))" "K");
#2. Adiabatic batch, first order, k = 1e13.exp of -11000/T in 1/min, T0 = 320 K;
json load "rx_ch_ad" (num ode (concat "{\"X\": \"1e13*exp(-11000/T)*(1-X)\", \"T\": \"" [dtad] "*1e13*exp(-11000/T)*(1-X)\"}") "{\"X\": 0, \"T\": 320}" 0 600 "{\"event\": \"X - 0.99\", \"direction\": 1}");
#3. Time to 99 % conversion and final temperature;
concat "dT_ad = " (math round [dtad] 1) " K, X = 99 % after " (math round (json select "rx_ch_ad" /event/t) 1) " min, T max = " (math round (stat max (json select "rx_ch_ad" /T)) 1) " K"
Result
mentdb
dT_ad = 41.5 K, X = 99 % after 33 min, T max = 361.1 K
Go further
  • Compute the time to maximum rate (TMRad) for the safety study.
  • Add a cooling term UA(T - Tc) and find the critical coolant temperature.
executed on MentDB

Yield model from a factorial design

A 2^2 design with centre points gives the yield against temperature and residence time. The script fits yield = b0 + b1 T + b2 t by multiple regression, gives the standard errors, R2 and adjusted R2, and predicts the yield at 105 degC and 3.5 h.

Pipeline
Script
admin
#1. Factorial design: yield in % against temperature in degC and residence time in h;
-> "[X]" "[[80, 2], [80, 4], [90, 2], [90, 4], [100, 2], [100, 4], [85, 3], [95, 3]]";
-> "[Y]" "[62.1, 70.3, 68.9, 77.2, 74.8, 83.5, 70.0, 76.4]";
pa rm load_from_json "rx_yield" [X] [Y];
#2. Model yield = b0 + b1 T + b2 t, with the standard errors of b;
-> "[b]" (pa rm estimate_regression_parameters "rx_yield");
-> "[se]" (pa rm estimate_regression_parameters_standard_errors "rx_yield");
#3. Quality of the model;
-> "[r2]" (pa rm calculate_r_squared "rx_yield");
-> "[r2a]" (pa rm calculate_adjusted_r_squared "rx_yield");
-> "[s]" (pa rm estimate_regression_standard_error "rx_yield");
#4. Predicted yield at 105 degC and 3.5 h, then close the model;
-> "[pred]" (pa rm predict "rx_yield" "[105, 3.5]");
pa rm close "rx_yield";
concat "{\"b\": " [b] ", \"std_err\": " [se] ", \"r2\": " (math round [r2] 4) ", \"r2_adj\": " (math round [r2a] 4) ", \"s\": " (math round [s] 3) ", \"yield_105C_3.5h\": " (math round [pred] 1) "}"
Result
mentdb
{"b": [
  2.099999999999971,
  0.646666666666667,
  4.199999999999999
], "std_err": [
  1.4008925726122052,
  0.014907119849998762,
  0.129099444873582
], "r2": 0.9983, "r2_adj": 0.9976, "s": 0.316, "yield_105C_3.5h": 84.7}
Go further
  • Look at the residuals with pa rm estimate_residuals before extrapolating.
  • Add an interaction column T*t to the X rows and compare the adjusted R2.
executed on MentDB

Shortcut column design: Fenske, Underwood, Gilliland

Size a benzene-toluene column: minimum stages at total reflux (Fenske), minimum reflux ratio from the Underwood root, operating reflux 1.3 Rmin, theoretical stages by the Gilliland correlation and real trays for a 70 % efficiency.

Pipeline
Script
admin
#1. Benzene-toluene column: relative volatility 2.45, feed 50 % saturated liquid q = 1, distillate 95 %, bottoms 5 % of benzene;
-> "[al]" 2.45; -> "[xD]" 0.95; -> "[xB]" 0.05; -> "[zF]" 0.5;
#2. Fenske: minimum number of theoretical stages at total reflux;
-> "[Nmin]" (math calc "ln(([xD]/(1-[xD]))*((1-[xB])/[xB]))/ln([al])");
#3. Underwood: root theta between 1 and alpha of sum alpha.z over alpha - theta = 1 - q = 0, then Rmin;
-> "[th]" (num solve (concat [al] "*" [zF] "/(" [al] "-t)+(1-" [zF] ")/(1-t)") "t" 1.0001 2.4499);
-> "[Rmin]" (math calc "[al]*[xD]/([al]-[th])+(1-[xD])/(1-[th])-1");
#4. Operating reflux 1.3 Rmin, Gilliland correlation by Eduljee, real stages with a 70 % tray efficiency;
-> "[R]" (math calc "1.3*[Rmin]");
-> "[X]" (math calc "([R]-[Rmin])/([R]+1)");
-> "[Y]" (math calc "0.75*(1-[X]^0.5668)");
-> "[Nth]" (math calc "([Y]+[Nmin])/(1-[Y])");
concat "Nmin = " (math round [Nmin] 2) ", theta = " (math round [th] 4) ", Rmin = " (math round [Rmin] 3) ", R = " (math round [R] 3) ", X = " (math round [X] 3) ", Y = " (math round [Y] 3) ", N = " (math round [Nth] 2) " theoretical stages including the reboiler, " (math ceiling (math calc "([Nth]-1)/0.7")) " real trays"
Result
mentdb
Nmin = 6.57, theta = 1.4203, Rmin = 1.141, R = 1.484, X = 0.138, Y = 0.506, N = 14.33 theoretical stages including the reboiler, 20 real trays
Go further
  • Locate the feed tray with the Kirkbride equation
  • Find the reflux ratio that minimizes the total cost (trays + reboiler duty) with num minimize
executed on MentDB

Residence time distribution and tanks-in-series model

From a pulse tracer test, compute the mean residence time and variance of the RTD, the equivalent number of tanks in series and the peak of E(t), then the conversion of a first-order reaction compared with an ideal PFR and CSTR.

Pipeline
Script
admin
#1. Pulse tracer test on a continuous reactor: outlet concentration in mg/L every 2.5 min;
-> "[c]" "[0.0, 20.43, 36.95, 40.81, 33.43, 24.67, 17.51, 10.88, 6.69, 4.06, 2.39, 1.33, 0.76, 0.41, 0.23, 0.12, 0.06]";
-> "[tab]" (num table "t^2" "t" 0 40 2.5);
#2. Moments of the RTD: mean residence time and variance, weights = C on a regular grid;
-> "[tm]" (stat weighted_mean (matrix col [tab] 1) [c]);
-> "[s2]" (math calc (concat (stat weighted_mean (matrix col [tab] 2) [c]) " - [tm]^2"));
#3. Tanks-in-series model: N = tm^2 / sigma^2, E of t at the peak t = tm.N-1/N with Gamma of N;
-> "[n]" (math calc "[tm]^2/[s2]");
-> "[tp]" (math calc "[tm]*([n]-1)/[n]");
-> "[ep]" (math calc (concat "[n]^[n]*[tp]^([n]-1)/([tm]^[n]*" (math gamma [n]) ")*exp(-[n]*[tp]/[tm])"));
#4. First-order reaction k = 0.25 1/min: conversion with N tanks vs ideal PFR and CSTR;
-> "[x]" (math calc (concat "1 - " (math power (math calc "1+0.25*[tm]/[n]") (math calc "-[n]"))));
concat "tm = " (math round [tm] 2) " min, sigma2 = " (math round [s2] 2) " min2, N = " (math round [n] 2) " tanks, E max = " (math round [ep] 4) " 1/min at " (math round [tp] 2) " min; X = " (math round (math calc "100*[x]") 1) " % vs PFR " (math round (math calc "100*(1-exp(-0.25*[tm]))") 1) " % and CSTR " (math round (math calc "100*0.25*[tm]/(1+0.25*[tm])") 1) " %"
Result
mentdb
tm = 10.01 min, sigma2 = 32.78 min2, N = 3.06 tanks, E max = 0.0816 1/min at 6.74 min; X = 83.9 % vs PFR 91.8 % and CSTR 71.5 %
Go further
  • Fit N directly on the normalized E(t) curve with stat fit_model.
  • Use the segregation model with the measured E(t) for a second-order reaction.
executed on MentDB

Process capability of an API assay

For 20 consecutive batches of an active ingredient, compute Cp and Cpk against the 98.0-102.0 % specification and the expected fraction of out-of-specification batches from the normal tails.

Pipeline
Script
admin
#1. Assay of 20 consecutive API batches in % of label claim, specification 98.0 - 102.0;
-> "[a]" "[100.4, 99.8, 100.9, 100.2, 99.5, 100.7, 101.1, 100.0, 99.9, 100.6, 100.3, 101.4, 99.7, 100.5, 100.8, 100.1, 99.6, 100.9, 100.4, 101.0]";
-> "[lsl]" 98.0; -> "[usl]" 102.0;
#2. Process mean and standard deviation;
-> "[m]" (stat mean [a]); -> "[s]" (stat stddev [a]);
#3. Capability indices Cp and Cpk;
-> "[cp]" (math calc "([usl]-[lsl])/(6*[s])");
-> "[cpk]" (math calc "min([usl]-[m], [m]-[lsl])/(3*[s])");
#4. Expected fraction out of specification: normal tails = 1/2.erfc of z/sqrt 2;
-> "[pu]" (math calc (concat "0.5*" (math erfc (math calc "([usl]-[m])/([s]*sqrt(2))"))));
-> "[pl]" (math calc (concat "0.5*" (math erfc (math calc "([m]-[lsl])/([s]*sqrt(2))"))));
concat "mean = " (math round [m] 2) " %, s = " (math round [s] 3) " %, Cp = " (math round [cp] 2) ", Cpk = " (math round [cpk] 2) ", expected out of spec = " (math round (math calc "1e6*([pu]+[pl])") 1) " ppm of the batches"
Result
mentdb
mean = 100.39 %, s = 0.538 %, Cp = 1.24, Cpk = 1, expected out of spec = 1385.9 ppm of the batches
Go further
executed on MentDB

Production campaign planning

Plan the yearly campaign of an intermediate: overall yield of a 4-step route, number of full batches and size of the last one, campaign length with cleaning, and starting material to order.

Pipeline
Script
admin
#1. Annual demand 18.5 t of an intermediate, reactor batch 1.35 t of product, 4 steps with these yields;
-> "[dem]" 18.5; -> "[bat]" 1.35; -> "[y]" "[0.94, 0.88, 0.97, 0.91]";
#2. Overall yield = product of the step yields, i.e. geometric mean ^ n;
-> "[yo]" (math power (stat geo_mean [y]) 4);
#3. Full batches and the size of the last partial batch;
-> "[nb]" (math calc "[dem]/[bat]");
-> "[full]" (math trunc [nb]);
-> "[last]" (math calc (concat (math frac_part [nb]) "*[bat]"));
#4. Campaign length with a 38 h cycle and 3 cleaning days, starting material needed per t of product: 0.92 t at 100 % yield;
-> "[days]" (math calc (concat "(" (math ceiling [nb]) "*38)/24 + 3"));
concat "overall yield = " (math round (math calc "100*[yo]") 1) " %, " [full] " full batches + 1 batch of " (math round [last] 3) " t, campaign = " (math round [days] 1) " days, starting material = " (math round (math calc "[dem]*0.92/[yo]") 2) " t"
Result
mentdb
overall yield = 73 %, 13 full batches + 1 batch of 0.95 t, campaign = 25.2 days, starting material = 23.31 t
Go further
  • Add a safety stock and the lead time of the starting material.
  • Compare campaigns in one or two reactors with num minimize on the total cost.
executed on MentDB

Mass balance of a two-column distillation train

Solve the component balances of a benzene/toluene/xylene train with fixed product specifications to get the three product flows, check the conditioning of the system and that no flow is negative.

Pipeline
Script
admin
#1. Two columns in series, feed 100 kmol/h of benzene / toluene / xylene = 0.40 / 0.35 / 0.25;
#2. Specs: D1 = 0.98 / 0.02 / 0, D2 = 0.01 / 0.97 / 0.02, B2 = 0 / 0.03 / 0.97;
-> "[m]" "[[0.98, 0.01, 0], [0.02, 0.97, 0.03], [0, 0.02, 0.97]]";
-> "[f]" "[40, 35, 25]";
#3. Component balances M.flows = feed: solve, and check the conditioning of the system;
-> "[q]" (matrix solve [m] [f]);
-> "[k]" (matrix cond [m]);
#4. All flows must be positive: sign of the smallest one;
-> "[ok]" (math sign (stat min [q]));
concat "D1 = " (math round (matrix get (concat "[" [q] "]") 1 1) 2) ", D2 = " (math round (matrix get (concat "[" [q] "]") 1 2) 2) ", B2 = " (math round (matrix get (concat "[" [q] "]") 1 3) 2) " kmol/h, sum = " (math round (stat sum [q]) 2) ", condition number = " (math round [k] 2) ", sign of the smallest flow = " [ok]
Result
mentdb
D1 = 40.46, D2 = 34.47, B2 = 25.06 kmol/h, sum = 100, condition number = 1.06, sign of the smallest flow = 1
Go further
  • Add the energy balance of each reboiler with the latent heats.
  • Make the specs uncertain and propagate with num uncertainty.
executed on MentDB

Agitation scale-up at constant power per volume

Scale a Rushton-agitated reaction from a 2 L lab reactor to 6.3 m3 at constant P/V: vessel and impeller diameters, plant speed, Reynolds number, power draw and tip speed.

Pipeline
Script
admin
#1. Lab reactor 2 L, plant reactor 6.3 m3, H = T, Rushton turbine D = T/3, Np = 5, lab speed 450 rpm;
-> "[v1]" 0.002; -> "[v2]" 6.3; -> "[n1]" 450; -> "[rho]" 1050; -> "[mu]" 0.004;
#2. Vessel diameters from V = pi.T^3/4 by the cube root, impeller diameters;
-> "[d1]" (math calc (concat (math cbrt (math calc "4*[v1]/pi")) "/3"));
-> "[d2]" (math calc (concat (math cbrt (math calc "4*[v2]/pi")) "/3"));
#3. Scale-up at constant power per volume: N2 = N1.D1/D2 ^2/3;
-> "[n2]" (math calc (concat "[n1]*" (math power (math calc "[d1]/[d2]") (math calc "2/3"))));
#4. Plant Reynolds number, power and tip speed, N in rev/s;
-> "[re]" (math calc "[rho]*([n2]/60)*[d2]^2/[mu]");
-> "[p]" (math calc "5*[rho]*([n2]/60)^3*[d2]^5");
concat "D lab = " (math round (math calc "[d1]*1000") 1) " mm, D plant = " (math round [d2] 3) " m, N plant = " (math round [n2] 1) " rpm, Re = " (math round [re] 0) " turbulent, P = " (math round (math calc "[p]/1000") 2) " kW = " (math round (math calc "[p]/[v2]") 0) " W/m3, tip speed = " (math round (math calc "pi*[d2]*[n2]/60") 2) " m/s"
Result
mentdb
D lab = 45.5 mm, D plant = 0.667 m, N plant = 75.1 rpm, Re = 146346 turbulent, P = 1.36 kW = 216 W/m3, tip speed = 2.62 m/s
Go further
  • Compare with constant tip speed (shear-sensitive crystals) or constant mixing time.
  • Check the heat removal: U.A grows like V^2/3 only.

Also in Chemistry & life

CH
Chemist
Stoichiometry, concentrations, dilutions, pH and gases with real units.
10 recipes
AP
Advanced physical chemist
Kinetics, stiff ODEs, activation energies and equilibria from thermodynamics.
10 recipes
CR
Corrosion researcher
Mass loss, Faraday, Tafel / Stern-Geary, Nernst and Arrhenius lifetimes.
10 recipes
EB
Electrochemist & battery engineer
Nernst, cell energy, Peukert and state of charge.
10 recipes
MS
Materials scientist
Tensile curves, thermal expansion and hardness statistics.
10 recipes
PP
Pharmacist & pharmacokinetics
Compartment models, half-life, AUC and dosing regimens.
10 recipes
BM
Biologist & microbiologist
Growth curves, enzyme kinetics and dilution series.
10 recipes
EP
Epidemiologist
Epidemic models, reproduction numbers and incidence statistics: ODE models, growth fits and exact Poisson limits.
10 recipes
GB
Geneticist & bioinformatician
Sequences, allele frequencies and Mendelian risks: regex on DNA, Hardy-Weinberg tests, exact fractions.
10 recipes
MP
Medical physicist
Dose, attenuation, decay correction and image quality: MIRD dose, HVL, dual energy, MTF.
10 recipes
AG
Agronomist
Crop development, fertilization and irrigation: degree days, response curves and rainfall statistics.
10 recipes