@@ -10,20 +10,54 @@ def test_flash():
1010 import biosteam as bst
1111 import numpy as np
1212 from numpy .testing import assert_allclose
13- bst .System .strict_phenomena_decomposition = True
14-
13+ bst .settings .set_thermo (['Water' , 'Ethanol' ], ideal = True )
14+ feed_liquid = bst .Stream ('feed_liquid' , Water = 50 , Ethanol = 50 , phase = 'l' , T = 400 )
15+ feed_gas = bst .Stream ('feed_gas' , Water = 50 , Ethanol = 50 , phase = 'g' , T = 400 )
16+ flash_1 = bst .StageEquilibrium ('flash_1' , ins = [feed_liquid , feed_gas ], Q = 0 , P = 101325 , phases = ('g' , 'l' ))
17+ flashes = [flash_1 ]
18+ for flash in flashes :
19+ flash .T = 350
20+ flash .K = np .array ([0.5 , 1.5 ])
21+ flash .B = 1.
22+ flash .outs [0 ].mol [:] = [50 , 50 ]
23+ flash .outs [1 ].mol [:] = [50 , 50 ]
24+ sys = bst .System ('sys' , path = flashes , algorithm = 'phenomena-oriented' )
25+ sys .track_convergence ()
26+ for i in range (10 ):
27+ sys .run_phenomena ()
28+ phenomena_graph = sys .get_phenomena_graph ()
29+ shape = phenomena_graph .variable_profiles .shape
30+ assert shape == (30 , 8 )
31+
1532
1633def test_2_stage_flash ():
1734 import biosteam as bst
1835 import numpy as np
1936 from numpy .testing import assert_allclose
20- bst .System .strict_phenomena_decomposition = True
37+ bst .settings .set_thermo (['Water' , 'Ethanol' ], ideal = True )
38+ feed_liquid = bst .Stream ('feed_liquid' , Water = 50 , Ethanol = 50 , phase = 'l' , T = 400 )
39+ feed_gas = bst .Stream ('feed_gas' , Water = 50 , Ethanol = 50 , phase = 'g' , T = 400 )
40+ flash_1 = bst .StageEquilibrium ('flash_1' , ins = [feed_liquid , feed_gas ], Q = 0 , P = 101325 , phases = ('g' , 'l' ))
41+ flash_2 = bst .StageEquilibrium ('flash_2' , ins = [flash_1 - 0 , feed_liquid ], B = 1 , P = 101325 , phases = ('g' , 'l' ))
42+ flashes = [flash_1 , flash_2 ]
43+ for flash in flashes :
44+ flash .T = 350
45+ flash .K = np .array ([0.5 , 1.5 ])
46+ flash .B = 1.
47+ flash .outs [0 ].mol [:] = [50 , 50 ]
48+ flash .outs [1 ].mol [:] = [50 , 50 ]
49+ sys = bst .System ('sys' , path = flashes , algorithm = 'phenomena-oriented' )
50+ sys .track_convergence ()
51+ for i in range (10 ):
52+ sys .run_phenomena ()
53+ phenomena_graph = sys .get_phenomena_graph ()
54+ shape = phenomena_graph .variable_profiles .shape
55+ assert shape == (30 , 15 )
2156
2257def test_column ():
2358 import biosteam as bst
2459 import numpy as np
2560 from numpy .testing import assert_allclose
26- bst .System .strict_phenomena_decomposition = True
2761 bst .settings .set_thermo (['Water' , 'Ethanol' ], cache = True )
2862 feed = bst .Stream ('feed' , Ethanol = 80 , Water = 100 , T = 80.215 + 273.15 )
2963 D1 = bst .MESHDistillation ('D1' , N_stages = 5 , ins = [feed ], feed_stages = [2 ],
@@ -33,9 +67,88 @@ def test_column():
3367 D1 .set_flow_rates (D1 .hot_start ())
3468 sys = bst .System ('sys' , path = [D1 ])
3569 sys .track_convergence (True )
36- for i in range (80 ):
70+ for i in range (10 ):
71+ sys .run_phenomena ()
72+ phenomena_graph = sys .get_phenomena_graph ()
73+ shape = phenomena_graph .variable_profiles .shape
74+ assert shape == (30 , 38 )
75+
76+ def test_system ():
77+ import biosteam as bst
78+ import numpy as np
79+ from numpy .testing import assert_allclose
80+ bst .settings .set_thermo (['Water' , 'AceticAcid' , 'EthylAcetate' ], cache = True )
81+ solvent_feed_ratio = 1
82+ @bst .SystemFactory
83+ def system (ins , outs ):
84+ feed = bst .Stream ('feed' , AceticAcid = 6660 , Water = 43600 )
85+ solvent = bst .Stream ('solvent' , EthylAcetate = 65000 )
86+ recycle = bst .Stream ('recycle' )
87+ LE = bst .MultiStageEquilibrium (
88+ N_stages = 6 , ins = [feed , solvent , recycle ],
89+ feed_stages = (0 , - 1 , - 1 ),
90+ phases = ('L' , 'l' ),
91+ maxiter = 200 ,
92+ use_cache = True ,
93+ )
94+ # DAA = bst.MultiStageEquilibrium(N_stages=6, ins=[LE-0], feed_stages=[3],
95+ # outs=['vapor', 'liquid'],
96+ # stage_specifications={0: ('Reflux', 0.673), -1: ('Boilup', 2.57)},
97+ # maxiter=200,
98+ # phases=('g', 'l'),
99+ # use_cache=True,
100+ # )
101+ DEA = bst .MultiStageEquilibrium (N_stages = 6 , ins = [LE - 1 ], feed_stages = [3 ],
102+ outs = ['vapor' , 'liquid' ],
103+ stage_specifications = {0 : ('Reflux' , 0.673 ), - 1 : ('Boilup' , 2.57 )},
104+ phases = ('g' , 'l' ),
105+ maxiter = 200 ,
106+ use_cache = True ,
107+ )
108+ HX = bst .SinglePhaseStage (ins = DEA - 0 , outs = recycle , T = 320 , phase = 'l' )
109+
110+ chemicals = bst .settings .chemicals
111+
112+ @LE .add_specification (run = True )
113+ def fresh_solvent_flow_rate ():
114+ broth = feed .F_mass
115+ EtAc_recycle = recycle .imass ['EthylAcetate' ]
116+ EtAc_required = broth * solvent_feed_ratio
117+ if EtAc_required < EtAc_recycle :
118+ recycle .F_mass *= EtAc_required / EtAc_recycle
119+ EtAc_recycle = recycle .imass ['EthylAcetate' ]
120+ EtAc_fresh = EtAc_required - EtAc_recycle
121+ solvent .imass ['EthylAcetate' ] = max (
122+ 0 , EtAc_fresh
123+ )
124+
125+ @solvent .material_balance
126+ def fresh_solvent_flow_rate ():
127+ s = np .ones (chemicals .size )
128+ r = np .zeros (chemicals .size )
129+ v = r .copy ()
130+ index = chemicals .index ('EthylAcetate' )
131+ r [index ] = 1
132+ v [index ] = solvent_feed_ratio * feed .F_mass / chemicals .EthylAcetate .MW
133+ return (
134+ {solvent : s ,
135+ recycle : r },
136+ v
137+ )
138+ sys = system (algorithm = 'phenomena oriented' ,
139+ molar_tolerance = 1e-9 ,
140+ relative_molar_tolerance = 1e-9 ,
141+ maxiter = 2000 ,
142+ method = 'fixed-point' )
143+ sys .track_convergence (True )
144+ for i in range (10 ):
37145 sys .run_phenomena ()
38146 phenomena_graph = sys .get_phenomena_graph ()
147+ shape = phenomena_graph .variable_profiles .shape
148+ assert shape == (37 , 133 )
39149
40150if __name__ == '__main__' :
41- pass
151+ test_flash ()
152+ test_2_stage_flash ()
153+ test_column ()
154+ test_system ()
0 commit comments