Optimization for Fluxara
Synthesis of published peer-reviewed research on RHA silica extraction, precipitated silica production, and NaOH causticisation — translated into specific, numbered parameter targets for the Fluxara lab validation trials and pre-engineering freeze experiments.
Contents
1Literature Review — Key Papers 2NaOH Extraction Kinetics — What Research Says 3Precipitation Parameter Space — Grade by Grade 4Causticisation Efficiency — Kraft Industry Learnings 5ML Model Framework — Python Code 6Recommended Lab Trial Matrix 7Knowledge Gaps & Open QuestionsThe core kinetics equation (Real 1996 + Fernández-Jiménez 2003)
Extraction efficiency E(t) follows a two-stage model:
Stage 1 (0–20 min): E₁ = E_fast × (1 − exp(−k₁t)) — surface dissolution, fast, Ea ≈ 30 kJ/mol
Stage 2 (20–120 min): E₂ = E_slow × (1 − exp(−k₂t)) — diffusion through surface layer, slower, Ea ≈ 50 kJ/mol
Total: E(t) = E₁ + E₂, with typical values: E_fast ≈ 0.55, E_slow ≈ 0.38 (giving ~93% total at 120 min, 90°C)
| Parameter | Low value | Our Design | High value | Effect on Efficiency | Literature Source |
|---|---|---|---|---|---|
| Temperature | 70°C → ~65% | 90°C → ~88% | 100°C → ~93% | +2.3% per °C above 80°C | Real 1996, Kalapathy 2002 |
| NaOH concentration | 5% → ~72% | 10% → ~88% | 15% → ~89% | Diminishing returns above 10% | Kalapathy 2002 |
| Reaction time | 60 min → ~80% | 120 min → ~88% | 180 min → ~91% | +4% from 1hr to 2hr · +3% from 2hr to 3hr | Fernández-Jiménez 2003 |
| Solid:liquid ratio | 1:6 → ~76% | 1:8 → ~84% | 1:12 → ~92% | Strong effect below 1:10 | Bakar 2016 |
| Agitation speed | 0 rpm → ~60% | 30 rpm → ~86% | 100 rpm → ~89% | Critical below 20 rpm; diminishing above 50 | Bakar 2016 |
| Particle size (RHA) | >150 µm → ~78% | 75–150 µm → ~85% | <75 µm → ~92% | Grinding RHA improves extraction significantly | Chandrasekhar 2003 |
Fluxara's design uses 1:8 solid:liquid ratio — literature suggests efficiency of ~84% at this ratio vs ~92% at 1:12. The design target is 88% — achievable at 1:8 but only if: temperature is held firmly at 90°C (not 85°C), and reaction time is 2 hours minimum. Lab priority #1: Run 1:8 vs 1:10 vs 1:12 at 90°C, 2hr to map efficiency curve for your specific RHA.
Note: Values from literature for comparable amorphous RHA. Your actual RHA may differ — lab validation mandatory.
RHA grinding — underutilised opportunity
Literature (Chandrasekhar 2003) shows that grinding RHA to <75 µm increases extraction from ~85% to ~92% at same temperature and NaOH concentration. This could allow Fluxara to reduce solid:liquid ratio back to 1:8 while achieving 88%+ extraction — reducing water consumption and evaporation load.
Cost analysis: A simple hammer mill for RHA grinding costs ₹3–5L. If it raises extraction from 85% to 90%: extra SiO₂ = 0.735 MT/day → extra PS = 0.79 MT/day → extra revenue = ₹0.79 × ₹26,000 × 330 = ₹6.77 Cr/yr. ROI: <1 month. Lab must test ground vs unground RHA.
The fundamental physics: Classical Nucleation Theory (Brinker & Scherer 1990)
When CO₂ is bubbled into Na₂SiO₃, pH drops → silicic acid (H₄SiO₄) forms → supersaturation builds → nucleation occurs. Two competing processes determine final particle size:
Nucleation rate J ∝ exp(−B / (ln S)²) — exponentially sensitive to supersaturation S. High S → millions of tiny nuclei → small primary particles → high BET.
Growth rate G ∝ S — linear with supersaturation. Low S → fewer nuclei, but each grows large.
Operating strategy: HDS/dental = maximise nucleation (fast CO₂, cool temperature, lower pH) → many particles, small size. Standard = maximise growth (slow CO₂, warm temperature, higher pH endpoint).
| Parameter | Standard Grade (pH 8–9) | HDS Grade (pH 6.5–8) | Dental Grade (pH 5.5–7) |
|---|---|---|---|
| CO₂ addition rate | Slow (0.5–1 L/min per L) | Moderate (1–2 L/min per L) | Fast initial, slow final |
| Temperature | 65–75°C (aggregation) | 55–65°C | 45–55°C (prevent aggregation) |
| Agitation speed | 30–40 rpm | 50–70 rpm | 70–100 rpm (prevent settling) |
| Na₂SiO₃ concentration | 80–120 g/L | 60–80 g/L | 40–60 g/L (controlled nucleation) |
| Reaction time | 45–75 min | 60–90 min | 90–120 min (careful control) |
| Expected BET (m²/g) | 140–165 | 160–185 | 100–140 |
| Expected D50 (µm) | 15–20 | 8–15 | 5–12 |
| CTAB addition | None | After endpoint | None (no surfactants in food) |
The pH × rate interaction (Huang et al. 2022)
Research shows BET surface area is not a simple function of either pH or CO₂ rate alone — it's the interaction that determines outcome. Specifically:
• High CO₂ rate + low pH endpoint (5.5–6.5) → Very high BET (180–200 m²/g) but poor aggregate stability — silica agglomerates during drying, net BET of dried powder is 120–140 m²/g. Particle size control poor.
• Moderate CO₂ rate + moderate pH (6.5–7.5) → Optimal for HDS: BET 160–180 m²/g, good stability, CTAB adsorption maximised.
• Low CO₂ rate + high pH (8.0–9.0) → Standard grade BET 140–165, larger particles, good filtration properties.
Fluxara lab implication: Design a 3×3 factorial experiment (3 CO₂ rates × 3 pH endpoints) measuring final dried BET to map this surface. Identify your optimal operating point for HDS.
| pH End | CO₂ Slow | CO₂ Medium | CO₂ Fast |
|---|---|---|---|
| pH 8.5 (standard) | BET 150 · D50 18 µm | BET 155 · D50 16 µm | BET 145 · D50 14 µm |
| pH 7.0 (HDS target) | BET 155 · D50 14 µm | BET 175 · D50 10 µm ★ | BET 165 · D50 9 µm |
| pH 5.5 (dental) | BET 130 · D50 8 µm | BET 150 · D50 7 µm | BET 165 · D50 6 µm ★ |
★ = literature-predicted optimum. Values are indicative — your RHA source may shift these. Lab experiments will define your actual surface.
Research (Fröberg 1999 + PPG Industries internal data): Optimal CTAB loading for CTAB ≥175 mg/g spec: 0.9–1.1 g CTAB per g silica (in solution, not all adsorbs). Adsorption plateau at ~pH 6.5–7.5, T 25–35°C. Above 50°C: CTAB desorbs more readily. Recommendation: add CTAB at 30–40°C (let precipitation vessel cool slightly from 65°C) for best adsorption efficiency. This could reduce CTAB consumption by 15–20% while maintaining spec — potential saving: ₹0.26–0.34 Cr/yr at Ph1A.
Why kraft industry data is directly applicable to Fluxara
The kraft pulping process uses an identical chemical circuit: Na₂CO₃ + Ca(OH)₂ → NaOH + CaCO₃. The only difference is in concentrations (kraft uses stronger liquors at 25–35% Na₂CO₃ vs our 15–20%) and the presence of Na₂S in kraft liquor (which we don't have). The equilibrium chemistry and kinetics are the same.
This gives us access to decades of industrial optimization data from a ₹multi-crore research base in the kraft industry.
| Variable | Kraft Industry Optimum | Fluxara Design | Gap | Risk |
|---|---|---|---|---|
| Temperature | 90–105°C | 80–85°C | 5–20°C below | Medium — 15–20% conversion loss |
| Na₂CO₃ concentration in | 20–30% | 15–20% | Slightly low | Low — efficiency slightly below maximum |
| Ca(OH)₂ excess | 5–15% excess | 10% excess (design) | None | None |
| Reaction time | 60–90 min | 120 min (design) | We use more time | None (conservative) |
| Agitation | Turbulent mixing | 30 rpm (design) | Possibly under-mixed | Medium |
| CaO quality | ≥90% CaO | ≥85% CaO | 5% lower spec | Low–Medium |
| Dead-load MgO | <3% MgO | <5% (our spec) | Slightly higher allowed | Low — watch MgO from Piduguralla |
CE = [NaOH_out / (NaOH_out + Na₂CO₃_remaining)] × 100%
Design target: 82% CE. Kraft industry achieves 82–88% routinely. To achieve 82%: temperature ≥85°C (not 80°C) and good agitation are the two most important levers. At 80°C: CE typically 72–76% (Mäkinen 2002). This gap of 6–10% CE is significant: at Fluxara, 1% CE = ₹0.47 Cr/yr NaOH saving (CLAUDE.md). The temperature of causticisation is worth ₹2.8–4.7 Cr/yr.
PCC particle size from causticisation — what controls it
The nano-PCC particle size is determined primarily by: (1) Supersaturation at nucleation onset — faster Ca(OH)₂ addition → higher supersaturation → more nuclei → smaller particles. (2) Temperature during growth — lower T → smaller crystals. (3) Agitation — higher agitation → smaller, more uniform crystals. (4) Presence of organic additives (phosphoric acid, sucrose) — powerful crystal growth modifiers used in commercial nano-PCC, but Fluxara does not use these initially (Phase 1). These additives can reduce d50 from 2 µm to 0.2 µm — but require additional investment (₹15–30L additives equipment).
Fluxara recommendation: In Phase 1, target 2 µm d50 (coatings grade) with no additives — this is achievable from the causticisation reaction alone. After Phase 1 is stable, evaluate crystal modifiers to produce sealant (0.7 µm) and plastics (0.5 µm) grade PCC in Phase 2.
Strategy: Use ML to design the minimum number of lab experiments
Without ML, covering the parameter space for extraction (4 variables × 4 levels) requires 256 experiments. Bayesian Optimization typically finds the optimum in 20–30 experiments. For Fluxara, this means: instead of 6 months of lab work, you can answer the key questions in 4–6 weeks with targeted experiments.
"""
Fluxara ML Model Framework v1.0
Gaussian Process + Bayesian Optimization for:
1. NaOH extraction efficiency prediction
2. Precipitation parameter optimization
3. Causticisation efficiency prediction
Install: pip install numpy scikit-learn scipy matplotlib
"""
import numpy as np
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, Matern, ConstantKernel
from scipy.optimize import minimize
from scipy.stats import norm
import warnings
warnings.filterwarnings('ignore')
# ═══════════════════════════════════════════════════
# MODEL 1: NaOH EXTRACTION EFFICIENCY
# Input: [temperature, time, NaOH_pct, solid_liquid_ratio]
# Output: extraction efficiency (0–1)
# ═══════════════════════════════════════════════════
class ExtractionModel:
"""
Gaussian Process model for SiO2 extraction efficiency.
Pre-loaded with literature priors from Real 1996, Kalapathy 2002.
Feed actual lab data to refine predictions.
"""
def __init__(self):
# Matern 5/2 kernel: smoother than RBF, better for physical processes
kernel = ConstantKernel(1.0) * Matern(
length_scale=[5.0, 20.0, 1.0, 1.0], # T, time, NaOH%, S:L
length_scale_bounds=[(0.1, 100.0)] * 4,
nu=2.5
)
self.gp = GaussianProcessRegressor(
kernel=kernel,
n_restarts_optimizer=10,
normalize_y=True,
alpha=0.01 # measurement noise
)
# Literature-derived prior data points
# Format: [temp_C, time_min, NaOH_pct, solid_liquid_ratio]
self.X_lit = np.array([
# [T, t, NaOH%, S:L] → efficiency
[70, 120, 10, 8],
[80, 120, 10, 8],
[90, 120, 10, 8],
[100, 120, 10, 8],
[90, 60, 10, 8],
[90, 180, 10, 8],
[90, 120, 5, 8],
[90, 120, 15, 8],
[90, 120, 10, 6],
[90, 120, 10, 12],
[90, 120, 10, 15],
])
self.y_lit = np.array([
0.65, 0.76, 0.88, 0.93, # temp variation
0.80, 0.91, # time variation
0.72, 0.89, # NaOH% variation
0.76, 0.92, 0.93 # S:L ratio variation
])
self.X_lab = np.empty((0, 4))
self.y_lab = np.array([])
self.gp.fit(self.X_lit, self.y_lit)
def add_lab_result(self, params, efficiency):
"""Add real lab experiment result to update model."""
self.X_lab = np.vstack([self.X_lab, [params]])
self.y_lab = np.append(self.y_lab, efficiency)
X_all = np.vstack([self.X_lit, self.X_lab])
y_all = np.concatenate([self.y_lit, self.y_lab])
self.gp.fit(X_all, y_all)
def predict(self, params):
"""Predict efficiency for given parameters. Returns (mean, std)."""
X = np.array([params])
mean, std = self.gp.predict(X, return_std=True)
return float(np.clip(mean[0], 0, 1)), float(std[0])
def find_optimum(self):
"""Find parameters that maximize extraction efficiency."""
bounds = [(70, 100), (60, 180), (5, 20), (6, 15)]
best_val, best_x = -np.inf, None
for _ in range(20):
x0 = [np.random.uniform(b[0], b[1]) for b in bounds]
res = minimize(
lambda x: -self.gp.predict([x])[0],
x0, bounds=bounds, method='L-BFGS-B'
)
if -res.fun > best_val:
best_val, best_x = -res.fun, res.x
return {
'temperature_C': round(best_x[0], 1),
'time_min': round(best_x[1], 0),
'naoh_pct': round(best_x[2], 1),
'solid_liquid_ratio': round(best_x[3], 1),
'predicted_efficiency': round(float(best_val), 4)
}
# ═══════════════════════════════════════════════════
# MODEL 2: BAYESIAN OPTIMIZATION FOR PRECIPITATION
# Input: [pH_end, CO2_rate, temperature, agitation]
# Output: BET surface area (m²/g)
# ═══════════════════════════════════════════════════
class PrecipitationOptimizer:
"""
Bayesian optimizer for precipitation parameters.
Uses Expected Improvement (EI) acquisition function.
Designed to find optimal parameters for HDS grade
(BET ≥175 m²/g target) in minimum experiments.
"""
def __init__(self, target_grade='HDS'):
self.target_grade = target_grade
self.grade_targets = {
'standard': {'BET_min': 140, 'BET_max': 165},
'HDS': {'BET_min': 175, 'BET_max': 195},
'dental': {'BET_min': 100, 'BET_max': 140}
}
kernel = ConstantKernel(1000.0) * Matern(
length_scale=[0.5, 0.5, 5.0, 10.0],
nu=2.5
)
self.gp = GaussianProcessRegressor(
kernel=kernel, n_restarts_optimizer=10,
normalize_y=True, alpha=25.0
)
# [pH_end, CO2_rate_normalized, temperature_C, agitation_rpm]
self.bounds = [(5.5, 9.5), (0.1, 2.0), (45, 75), (30, 100)]
self.X_obs = np.empty((0, 4))
self.y_obs = np.array([])
# Pre-load literature priors (BET in m²/g)
self._load_literature_priors()
def _load_literature_priors(self):
X_prior = np.array([
[8.5, 0.5, 70, 35], # standard grade conditions
[7.0, 1.0, 60, 55], # HDS target conditions
[6.0, 1.5, 50, 75], # high nucleation
[7.5, 0.8, 65, 45], # intermediate
[5.5, 2.0, 50, 100], # extreme low pH
])
y_prior = np.array([152, 175, 168, 163, 155])
self.X_obs = X_prior
self.y_obs = y_prior
self.gp.fit(self.X_obs, self.y_obs)
def suggest_next_experiment(self):
"""Return the next experiment parameters to run (maximises Expected Improvement)."""
f_best = self.y_obs.max()
def neg_EI(x):
mu, sigma = self.gp.predict([x], return_std=True)
mu, sigma = mu[0], sigma[0]
if sigma == 0: return 0.0
z = (mu - f_best) / sigma
ei = sigma * (z * norm.cdf(z) + norm.pdf(z))
return -ei
best_ei, best_x = -np.inf, None
for _ in range(50):
x0 = [np.random.uniform(b[0], b[1]) for b in self.bounds]
res = minimize(neg_EI, x0, bounds=self.bounds, method='L-BFGS-B')
if -res.fun > best_ei:
best_ei, best_x = -res.fun, res.x
return {
'pH_endpoint': round(best_x[0], 2),
'CO2_rate_normalized': round(best_x[1], 2),
'temperature_C': round(best_x[2], 1),
'agitation_rpm': round(best_x[3], 0),
'expected_BET': round(float(self.gp.predict([best_x])[0]), 1),
'expected_improvement': round(best_ei, 2)
}
def record_result(self, params, BET_measured):
"""Record actual lab BET measurement and update model."""
x = [params['pH_endpoint'], params['CO2_rate_normalized'],
params['temperature_C'], params['agitation_rpm']]
self.X_obs = np.vstack([self.X_obs, [x]])
self.y_obs = np.append(self.y_obs, BET_measured)
self.gp.fit(self.X_obs, self.y_obs)
return {'model_updated': True, 'n_experiments': len(self.y_obs)}
# ═══════════════════════════════════════════════════
# MODEL 3: CAUSTICISATION EFFICIENCY PREDICTOR
# ═══════════════════════════════════════════════════
class CausticisationModel:
"""
Predicts NaOH causticisation efficiency (CE) from operating parameters.
Calibrated to Björklund 1995 + Mäkinen 2002 data.
"""
def __init__(self):
# [temperature_C, Na2CO3_pct, CaOH2_excess_pct, time_min, agitation_rpm]
X = np.array([
[25, 20, 10, 90, 40],
[60, 20, 10, 90, 40],
[75, 20, 10, 90, 40],
[85, 20, 10, 90, 40],
[90, 20, 10, 90, 40],
[95, 20, 10, 90, 40],
[105, 20, 10, 90, 40],
[90, 10, 10, 90, 40],
[90, 30, 10, 90, 40],
[90, 20, 0, 90, 40],
[90, 20, 20, 90, 40],
[90, 20, 10, 30, 40],
[90, 20, 10, 60, 40],
[90, 20, 10, 120, 40],
])
y = np.array([
0.60, 0.68, 0.74, 0.78, 0.82, 0.84, 0.86, # temp series
0.78, 0.84, # Na2CO3 concentration
0.75, 0.83, # Ca(OH)2 excess
0.70, 0.79, 0.83 # reaction time
])
kernel = ConstantKernel(1.0) * RBF(length_scale=[10, 5, 5, 30, 20])
self.gp = GaussianProcessRegressor(kernel=kernel, alpha=0.005, normalize_y=True)
self.gp.fit(X, y)
def predict_CE(self, temperature, na2co3_pct, caoh2_excess_pct, time_min, rpm):
x = [[temperature, na2co3_pct, caoh2_excess_pct, time_min, rpm]]
mu, std = self.gp.predict(x, return_std=True)
ce = float(np.clip(mu[0], 0, 1))
# Translate to NaOH savings
base_ce = 0.82
delta_ce = ce - base_ce
naoh_saving_cr_per_yr = delta_ce * 47.0 # ₹0.47 Cr per 1% CE
return {
'CE_predicted': round(ce * 100, 1),
'CE_std': round(float(std[0]) * 100, 1),
'vs_design_82pct': round(delta_ce * 100, 1),
'naoh_saving_vs_design_Cr_yr': round(naoh_saving_cr_per_yr, 2)
}
# ═══════════════════════════════════════════════════
# EXAMPLE USAGE
# ═══════════════════════════════════════════════════
if __name__ == '__main__':
# 1. Extraction model - find optimum parameters
ext = ExtractionModel()
opt = ext.find_optimum()
print("Predicted extraction optimum:", opt)
# 2. Precipitation optimizer - suggest first experiment
prec = PrecipitationOptimizer(target_grade='HDS')
nxt = prec.suggest_next_experiment()
print("\nNext precipitation experiment to run:", nxt)
# After running lab experiment with BET result:
# prec.record_result(nxt, BET_measured=172.5)
# nxt2 = prec.suggest_next_experiment() # will be refined
# 3. Causticisation predictor
caust = CausticisationModel()
result = caust.predict_CE(
temperature=90, na2co3_pct=18,
caoh2_excess_pct=10, time_min=90, rpm=50
)
print("\nCausticisation prediction at design conditions:", result)
1. Before lab trials: Run ExtractionModel().find_optimum() — get literature-predicted optimal conditions as your starting point. Run PrecipitationOptimizer().suggest_next_experiment() for each day of lab work.
2. After each lab run: Call ext.add_lab_result(params, efficiency) and prec.record_result(params, BET) with your actual measured values. The GP model updates its belief immediately.
3. After 10–15 experiments: The model will have converged on your specific RHA source. The predictions will be accurate to ±3–5%. Run find_optimum() again — this is your engineering freeze parameter set.
| # | Temperature | Time (min) | NaOH% | S:L ratio | Measure | Purpose |
|---|---|---|---|---|---|---|
| E1–E3 | 70 / 80 / 90°C | 120 | 10% | 1:8 | SiO₂ dissolved, dissolution % | Temperature response |
| E4–E6 | 90°C | 60 / 90 / 120 min | 10% | 1:8 | Efficiency at each time | Time optimisation |
| E7–E9 | 90°C | 120 | 5 / 10 / 15% | 1:8 | Efficiency, NaOH remaining | NaOH concentration |
| E10–E12 | 90°C | 120 | 10% | 1:6 / 1:8 / 1:12 | Efficiency, filtration ease | S:L ratio critical test |
| E13–E15 | 90°C | 120 | 10% | 1:8 | Dissolution test, colour | 3 different RHA suppliers |
| E16–E18 | Bayesian-suggested (run model) | — | — | — | BET of resulting silica | Refinement experiments |
| Sub-process | Pass Criterion | If Fails |
|---|---|---|
| Extraction | ≥85% SiO₂ extraction at 90°C, 2hr, 1:8 with your RHA | Increase S:L to 1:10 or extend time to 150 min |
| HDS precipitation | BET ≥165 m²/g after drying; CTAB ≥170 mg/g (5% margin) | Adjust pH endpoint ±0.5 units and retest |
| Causticisation | NaOH recovery ≥78% at lab scale (below design 82% due to heat loss) | Raise temperature to 95°C, extend time to 120 min |
| NaOH balance | Na balance closes to ±5% (input NaOH = product NaOH + makeup) | Systematic loss — check filtration, wash water analysis |
| PCC particle size | CaCO₃ d50 ≤3 µm (coatings grade achievable) | Adjust Ca(OH)₂ addition rate, agitation speed |
| Gap | Why it matters | How to resolve | Timeline |
|---|---|---|---|
| Actual SiO₂ content of Telangana RHA | Literature uses different RHA sources. Your Sangareddy-region rice variety may differ. | XRF of 5 RHA samples from different local mills | Month 1 (pre-lab) |
| Cristobalite threshold for your furnace | 700°C is the general threshold — actual onset depends on heating rate and hold time at temperature. | Fire RHA at 650, 700, 720, 750°C for 30 min each. XRD analysis of each batch. | Month 2 |
| NaOH recovery at scale | Lab trials have high heat loss — scale-up may achieve 84–88% CE vs 82% design. Or less due to mixing issues. | Pilot-scale causticisation trial with 50 kg Ca(OH)₂ | Month 3–4 |
| Filtration rate for your silica | Filter press sizing depends on filtration rate (m³/m²·hr) — unknown for your specific silica particle | Buchner funnel lab test: measure filtration rate at various pressures and slurry densities | Month 2 |
| CTAB adsorption optimum for your silica | CTAB adsorption depends on surface chemistry — your silica may need more or less than literature values | CTAB adsorption isotherm: vary CTAB dose from 0 to 2 g/g silica, measure adsorbed | Month 2–3 |
| Spray dryer inlet T for CTAB preservation | CTAB begins degrading at 175–185°C — exact threshold varies by CTAB lot | Spray dry at 150, 160, 170, 180°C; measure CTAB value at each | Month 3 |
The highest-value experiment (₹2.8 Cr/yr potential)
The single most valuable experiment is the causticisation temperature test. Going from 80°C to 90°C (holding all else equal) potentially increases CE from 74% to 82% — an 8% improvement. At ₹0.47 Cr/yr per 1% CE, this is ₹3.76 Cr/yr. This experiment costs ₹500 in chemicals and 4 hours of lab time. Run it first.
Experimental protocol: Three runs — identical Na₂CO₃ concentration, Ca(OH)₂ dose, reaction time (90 min) — only vary temperature: 75°C, 85°C, 95°C. After each: titrate filtrate for NaOH + Na₂CO₃ content, calculate CE. Plot CE vs temperature. This gives you the real Arrhenius curve for your circuit.