Skip to content

Commit 3766161

Browse files
authored
update bio (#1880)
* update * update * update * update * iso6976 * adsorption * add oil quality * updates * update * update * update bio * update
1 parent 49bbc2c commit 3766161

File tree

6 files changed

+4925
-161
lines changed

6 files changed

+4925
-161
lines changed

docs/examples/BeerBrewing_BioProcess_Simulation.ipynb

Lines changed: 4609 additions & 0 deletions
Large diffs are not rendered by default.

docs/process/bioprocessing.md

Lines changed: 123 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,40 @@ ProcessEquipmentBaseClass
6363
+-- Dryer
6464
```
6565

66+
### Using Bio-Processing Components (COMP_EXT)
67+
68+
Bio-processing simulations typically require components such as sugars, organic acids, and sugar alcohols that are not in the default component database (COMP). NeqSim's **extended component database** (COMP_EXT) contains thousands of additional components including many bio-relevant species.
69+
70+
**Enable COMP_EXT before creating the fluid system:**
71+
72+
```java
73+
import neqsim.util.database.NeqSimDataBase;
74+
75+
// Enable extended database
76+
NeqSimDataBase.useExtendedComponentDatabase(true);
77+
78+
SystemInterface fluid = new SystemSrkEos(273.15 + 30.0, 1.01325);
79+
fluid.addComponent("glucose", 0.10);
80+
fluid.addComponent("ethanol", 0.05);
81+
fluid.addComponent("water", 0.85);
82+
fluid.setMixingRule("classic");
83+
84+
// Reset when done (especially in tests)
85+
NeqSimDataBase.useExtendedComponentDatabase(false);
86+
```
87+
88+
**Available bio-processing components in COMP_EXT:**
89+
90+
| Category | Components |
91+
|----------|------------|
92+
| **Sugars** | glucose, fructose, sucrose, dl-Xylose, arabinose, mannose, galactose, cellobiose, maltose monohydrate |
93+
| **Organic acids** | lactic acid, citric acid, succinic acid, gluconic acid, acetic acid, propionic acid, butyric acid, itaconic acid, levulinic acid, pyruvic acid, fumaric acid, malic acid |
94+
| **Alcohols** | ethanol, methanol, 1-butanol, 2-butanol, glycerol, 2-methyl-1-propanol (isobutanol) |
95+
| **Sugar alcohols** | d-sorbitol, xylitol, d-mannitol, erythritol |
96+
| **Platform chemicals** | 5-hydroxymethylfurfural, 5-methylfurfural, furfural, vanillin, phenol |
97+
| **Amino acids** | l-lysine, l-glutamic acid |
98+
| **Other** | urea, ethylene glycol, 1,2-propanediol, acetone, 2,3-butanediol |
99+
66100
---
67101

68102
## Reactors
@@ -184,32 +218,35 @@ where $P/V$ is the specific power in kW/m$^3$ and $V$ is the vessel volume.
184218
#### Simulation Example
185219

186220
```java
187-
// Create fluid system
221+
// Enable extended component database for bio-relevant components
222+
NeqSimDataBase.useExtendedComponentDatabase(true);
223+
224+
// Create fluid system with bio-processing components from COMP_EXT
188225
SystemInterface fluid = new SystemSrkEos(273.15 + 30.0, 1.01325);
189-
fluid.addComponent("methane", 0.8);
190-
fluid.addComponent("ethane", 0.15);
191-
fluid.addComponent("propane", 0.05);
226+
fluid.addComponent("water", 0.80);
227+
fluid.addComponent("glucose", 0.10);
228+
fluid.addComponent("ethanol", 0.05);
229+
fluid.addComponent("lactic acid", 0.05);
192230
fluid.setMixingRule("classic");
193231

194232
// Feed stream
195233
Stream feed = new Stream("Reactor Feed", fluid);
196234
feed.setFlowRate(1000.0, "kg/hr");
197235
feed.run();
198236

199-
// Create CSTR
237+
// Create CSTR for lactic acid fermentation
200238
StirredTankReactor cstr = new StirredTankReactor("CSTR-1", feed);
201-
cstr.setReactorTemperature(273.15 + 60.0); // 60 C, isothermal
239+
cstr.setReactorTemperature(273.15 + 37.0); // 37 C, isothermal
202240
cstr.setVesselVolume(20.0); // 20 m3
203-
cstr.setResidenceTime(2.0, "hr");
241+
cstr.setResidenceTime(24.0, "hr");
204242
cstr.setAgitatorPowerPerVolume(1.5); // 1.5 kW/m3
205243

206-
// Define and add reaction
207-
StoichiometricReaction rxn = new StoichiometricReaction("Cracking");
208-
rxn.addReactant("propane", 1.0);
209-
rxn.addProduct("methane", 1.0);
210-
rxn.addProduct("ethane", 1.0);
211-
rxn.setLimitingReactant("propane");
212-
rxn.setConversion(0.50);
244+
// Define lactic acid fermentation: C6H12O6 -> 2 C3H6O3
245+
StoichiometricReaction rxn = new StoichiometricReaction("LacticFermentation");
246+
rxn.addReactant("glucose", 1.0);
247+
rxn.addProduct("lactic acid", 2.0);
248+
rxn.setLimitingReactant("glucose");
249+
rxn.setConversion(0.90);
213250
cstr.addReaction(rxn);
214251

215252
// Run
@@ -289,9 +326,14 @@ where $\Delta S$ is the substrate consumed [g] and $\Delta X$ is the biomass pro
289326
#### Simulation Example
290327

291328
```java
329+
NeqSimDataBase.useExtendedComponentDatabase(true);
330+
292331
SystemInterface broth = new SystemSrkEos(273.15 + 32.0, 1.01325);
293-
broth.addComponent("water", 50.0);
294-
broth.addComponent("ethanol", 0.01);
332+
broth.addComponent("water", 0.80);
333+
broth.addComponent("glucose", 0.15);
334+
broth.addComponent("ethanol", 0.0);
335+
broth.addComponent("CO2", 0.0);
336+
broth.addComponent("glycerol", 0.05);
295337
broth.setMixingRule("classic");
296338

297339
Stream feed = new Stream("Broth Feed", broth);
@@ -304,11 +346,13 @@ fermenter.setResidenceTime(48.0, "hr");
304346
fermenter.setVesselVolume(200.0);
305347
fermenter.setAerobic(false); // anaerobic ethanol fermentation
306348

349+
// Gay-Lussac equation: C6H12O6 -> 2 C2H5OH + 2 CO2
307350
StoichiometricReaction etoh = new StoichiometricReaction("EtOHFermentation");
308-
etoh.addReactant("water", 1.0); // placeholder for glucose
351+
etoh.addReactant("glucose", 1.0);
309352
etoh.addProduct("ethanol", 2.0);
310-
etoh.setLimitingReactant("water");
311-
etoh.setConversion(0.05);
353+
etoh.addProduct("CO2", 2.0);
354+
etoh.setLimitingReactant("glucose");
355+
etoh.setConversion(0.90);
312356
fermenter.addReaction(etoh);
313357

314358
fermenter.run();
@@ -378,29 +422,34 @@ $$
378422
#### Simulation Example
379423

380424
```java
425+
NeqSimDataBase.useExtendedComponentDatabase(true);
426+
381427
SystemInterface substrate = new SystemSrkEos(273.15 + 50.0, 1.01325);
382-
substrate.addComponent("water", 90.0);
383-
substrate.addComponent("methane", 10.0); // placeholder for cellulose
428+
substrate.addComponent("water", 0.80);
429+
substrate.addComponent("sucrose", 0.15);
430+
substrate.addComponent("glucose", 0.03);
431+
substrate.addComponent("fructose", 0.02);
384432
substrate.setMixingRule("classic");
385433

386434
Stream feed = new Stream("Substrate Feed", substrate);
387435
feed.setFlowRate(2000.0, "kg/hr");
388436
feed.run();
389437

390-
EnzymeTreatment hydrolysis = new EnzymeTreatment("Saccharification", feed);
438+
EnzymeTreatment hydrolysis = new EnzymeTreatment("Invertase Treatment", feed);
391439
hydrolysis.setReactorTemperature(273.15 + 50.0);
392-
hydrolysis.setResidenceTime(72.0, "hr");
393-
hydrolysis.setEnzymeLoading(20.0);
394-
hydrolysis.setEnzymeType("cellulase");
395-
hydrolysis.setOptimalPH(5.0);
440+
hydrolysis.setResidenceTime(4.0, "hr");
441+
hydrolysis.setEnzymeLoading(5.0);
442+
hydrolysis.setEnzymeType("invertase");
443+
hydrolysis.setOptimalPH(4.5);
396444
hydrolysis.setEnzymeCostPerKg(10.0);
397445

398-
// Define hydrolysis reaction (simplified)
399-
StoichiometricReaction rxn = new StoichiometricReaction("Hydrolysis");
400-
rxn.addReactant("methane", 1.0);
401-
rxn.addProduct("water", 0.5);
402-
rxn.setLimitingReactant("methane");
403-
rxn.setConversion(0.80);
446+
// Sucrose inversion: C12H22O11 + H2O -> C6H12O6 + C6H12O6
447+
StoichiometricReaction rxn = new StoichiometricReaction("SucroseInversion");
448+
rxn.addReactant("sucrose", 1.0);
449+
rxn.addProduct("glucose", 1.0);
450+
rxn.addProduct("fructose", 1.0);
451+
rxn.setLimitingReactant("sucrose");
452+
rxn.setConversion(0.95);
404453
hydrolysis.addReaction(rxn);
405454

406455
hydrolysis.run();
@@ -464,19 +513,21 @@ where $E_s$ is the specific energy [kWh/m$^3$] and $\dot{V}_\text{feed}$ is the
464513
#### Simulation Example
465514

466515
```java
516+
NeqSimDataBase.useExtendedComponentDatabase(true);
517+
467518
SystemInterface slurry = new SystemSrkEos(273.15 + 25.0, 1.01325);
468519
slurry.addComponent("water", 0.85);
469-
slurry.addComponent("methane", 0.10); // placeholder for biomass
470-
slurry.addComponent("ethane", 0.05); // placeholder for fiber
520+
slurry.addComponent("glucose", 0.10);
521+
slurry.addComponent("lactic acid", 0.05);
471522
slurry.setMixingRule("classic");
472523

473524
Stream feed = new Stream("Slurry Feed", slurry);
474525
feed.setFlowRate(500.0, "kg/hr");
475526
feed.run();
476527

477528
SolidsSeparator sep = new SolidsSeparator("Separator", feed);
478-
sep.setSolidsSplitFraction("methane", 0.95); // 95% biomass to solids
479-
sep.setSolidsSplitFraction("ethane", 0.90); // 90% fiber to solids
529+
sep.setSolidsSplitFraction("glucose", 0.95); // 95% glucose to solids
530+
sep.setSolidsSplitFraction("lactic acid", 0.10); // 10% acid to solids
480531
// water defaults to 0% solids
481532
sep.setMoistureContent(0.50);
482533
sep.run();
@@ -623,17 +674,19 @@ This is computed rigorously from the equation of state (SRK, PR, CPA, etc.) —
623674
When combining feed and solvent systems, both systems must contain all the same components (use 0.0 moles for absent components). This ensures the mixing rule interaction parameter matrices are consistently sized.
624675

625676
```java
677+
NeqSimDataBase.useExtendedComponentDatabase(true);
678+
626679
// CORRECT: Both systems have all 3 components
627680
SystemInterface feedSys = new SystemSrkEos(298.15, 1.01325);
628681
feedSys.addComponent("water", 5.0);
629-
feedSys.addComponent("methane", 0.5);
630-
feedSys.addComponent("n-hexane", 0.0); // absent but declared
682+
feedSys.addComponent("lactic acid", 0.5);
683+
feedSys.addComponent("1-butanol", 0.0); // absent but declared
631684
feedSys.setMixingRule("classic");
632685

633686
SystemInterface solventSys = new SystemSrkEos(298.15, 1.01325);
634-
solventSys.addComponent("water", 0.0); // absent but declared
635-
solventSys.addComponent("methane", 0.0); // absent but declared
636-
solventSys.addComponent("n-hexane", 3.0);
687+
solventSys.addComponent("water", 0.0); // absent but declared
688+
solventSys.addComponent("lactic acid", 0.0); // absent but declared
689+
solventSys.addComponent("1-butanol", 3.0);
637690
solventSys.setMixingRule("classic");
638691
```
639692

@@ -727,9 +780,11 @@ $$
727780
#### Simulation Example
728781

729782
```java
783+
NeqSimDataBase.useExtendedComponentDatabase(true);
784+
730785
SystemInterface juice = new SystemSrkEos(273.15 + 80.0, 1.5);
731786
juice.addComponent("water", 0.85);
732-
juice.addComponent("ethanol", 0.15); // placeholder for dissolved solids
787+
juice.addComponent("glucose", 0.15);
733788
juice.setMixingRule("classic");
734789

735790
Stream feed = new Stream("Dilute Juice", juice);
@@ -805,9 +860,11 @@ where $\eta_\text{thermal}$ is the thermal efficiency (fraction of heat input us
805860
#### Simulation Example
806861

807862
```java
863+
NeqSimDataBase.useExtendedComponentDatabase(true);
864+
808865
SystemInterface wetProduct = new SystemSrkEos(273.15 + 60.0, 1.01325);
809866
wetProduct.addComponent("water", 0.70);
810-
wetProduct.addComponent("ethanol", 0.30); // placeholder for dry solids
867+
wetProduct.addComponent("d-sorbitol", 0.30);
811868
wetProduct.setMixingRule("classic");
812869

813870
Stream feed = new Stream("Wet Feed", wetProduct);
@@ -825,7 +882,6 @@ System.out.println("Heat duty: " + dryer.getHeatDuty("kW") + " kW");
825882
StreamInterface dried = dryer.getDriedProductStream();
826883
StreamInterface vapor = dryer.getVaporStream();
827884
```
828-
829885
---
830886

831887
## Crystallization
@@ -893,9 +949,11 @@ where $H_\text{out}$ is evaluated at the target temperature/pressure after a TP-
893949
#### Simulation Example
894950

895951
```java
952+
NeqSimDataBase.useExtendedComponentDatabase(true);
953+
896954
SystemInterface solution = new SystemSrkEos(273.15 + 80.0, 1.01325);
897955
solution.addComponent("water", 0.70);
898-
solution.addComponent("ethanol", 0.30); // placeholder for solute
956+
solution.addComponent("citric acid", 0.30);
899957
solution.setMixingRule("classic");
900958

901959
Stream feed = new Stream("Saturated Solution", solution);
@@ -905,7 +963,7 @@ feed.run();
905963
Crystallizer cryst = new Crystallizer("Cooling Crystallizer", feed);
906964
cryst.setCrystallizationType("cooling");
907965
cryst.setOutletTemperature(30.0, "C");
908-
cryst.setTargetSolute("ethanol");
966+
cryst.setTargetSolute("citric acid");
909967
cryst.setSolidRecovery(0.85);
910968
cryst.setCrystalPurity(0.98);
911969
cryst.setResidenceTime(4.0);
@@ -970,23 +1028,30 @@ import neqsim.process.equipment.stream.Stream;
9701028
import neqsim.process.processmodel.ProcessSystem;
9711029
import neqsim.thermo.system.SystemSrkEos;
9721030
import neqsim.thermo.system.SystemInterface;
1031+
import neqsim.util.database.NeqSimDataBase;
1032+
1033+
// Enable extended component database for bio-processing components
1034+
NeqSimDataBase.useExtendedComponentDatabase(true);
9731035

974-
// 1. Create feed fluid
1036+
// 1. Create feed fluid with glucose substrate
9751037
SystemInterface feedFluid = new SystemSrkEos(273.15 + 30.0, 1.01325);
9761038
feedFluid.addComponent("water", 0.80);
977-
feedFluid.addComponent("ethanol", 0.01);
978-
feedFluid.addComponent("methane", 0.19); // placeholder for sugar substrate
1039+
feedFluid.addComponent("glucose", 0.15);
1040+
feedFluid.addComponent("ethanol", 0.0);
1041+
feedFluid.addComponent("CO2", 0.0);
1042+
feedFluid.addComponent("glycerol", 0.05);
9791043
feedFluid.setMixingRule("classic");
9801044

9811045
Stream feed = new Stream("Sugar Feed", feedFluid);
9821046
feed.setFlowRate(5000.0, "kg/hr");
9831047
feed.run();
9841048

985-
// 2. Fermentation
986-
StoichiometricReaction fermentation = new StoichiometricReaction("SugarToEthanol");
987-
fermentation.addReactant("methane", 1.0);
1049+
// 2. Fermentation: C6H12O6 -> 2 C2H5OH + 2 CO2
1050+
StoichiometricReaction fermentation = new StoichiometricReaction("GlucoseToEthanol");
1051+
fermentation.addReactant("glucose", 1.0);
9881052
fermentation.addProduct("ethanol", 2.0);
989-
fermentation.setLimitingReactant("methane");
1053+
fermentation.addProduct("CO2", 2.0);
1054+
fermentation.setLimitingReactant("glucose");
9901055
fermentation.setConversion(0.90);
9911056

9921057
Fermenter fermenter = new Fermenter("Fermenter", feed);
@@ -997,10 +1062,10 @@ fermenter.setAerobic(false);
9971062
fermenter.addReaction(fermentation);
9981063
fermenter.run();
9991064

1000-
// 3. Centrifuge - remove cell mass
1065+
// 3. Centrifuge - remove cell mass and residual glucose
10011066
SolidsCentrifuge centrifuge = new SolidsCentrifuge("Cell Separator",
10021067
fermenter.getOutletStream());
1003-
centrifuge.setSolidsSplitFraction("methane", 0.95);
1068+
centrifuge.setSolidsSplitFraction("glucose", 0.95);
10041069
centrifuge.setGForce(5000.0);
10051070
centrifuge.run();
10061071

@@ -1018,6 +1083,9 @@ System.out.println("Fermenter heat duty: " + fermenter.getHeatDuty("kW") + " kW"
10181083
System.out.println("Fermenter total power: " + fermenter.getTotalPower() + " kW");
10191084
System.out.println("Centrifuge power: " + centrifuge.getPowerConsumption() + " kW");
10201085
System.out.println("Evaporator steam economy: " + evaporator.getSteamEconomy());
1086+
1087+
// Reset database
1088+
NeqSimDataBase.useExtendedComponentDatabase(false);
10211089
```
10221090

10231091
---

0 commit comments

Comments
 (0)