BioSTEAMDevelopmentGroup / Bioindustrial-Park

BioSTEAM's Premier Repository for Biorefinery Models and Results
MIT License
36 stars 17 forks source link

Request for enthalpy calculation and excess enthalpy #65

Closed zasddsgg closed 1 year ago

zasddsgg commented 1 year ago

Hello, I have learned the code for enthalpy calculation and excess enthalpy (https://github.com/BioSTEAMDevelopmentGroup/thermosteam/blob/master/thermosteam/free_energy.py), I have two questions about enthalpy calculation and excess enthalpy. Could I consult you about these two questions. Thank you for your help. Wish you a good day.

a) For the same substance, will the selection of different phase states and reference phase states affect the enthalpy of the substance under specified conditions. For example, the phase state and the reference phase state of substance A can choose any of the liquid, gas or solid state. Does the above choice have any effect on the enthalpy of A under certain pressure and temperature and the specific phase state of A (for example, A is liquid under certain conditions, but it may change into gas after the temperature changes, but the phase state and the reference phase state of A choose only liquid state)? If not, For the existing chemical substances in corn stover model and the chemical substances added by me through bst.Chemical, can their phase states and reference phase states be randomly selected (of course, the reference phase of chemical added by bst. Chemical is always the phase at 25 C at 1 atm)? Will above selection influence the calculation of enthalpy values of the same substance in different phase states under specific conditions (only one phase state and reference phase state is selected)?

b) For class PretreatmentReactorSystem, I set up a reaction inside XYLAN→Furfural + 2H2O. It seems that excess enthalpy (heat of mixing) was not taken into account when calculating the enthalpy flow in class PretreatmentReactorSystem. Why is excess enthalpy (heat of mixing) not taken into account? Such as the following class PretreatmentReactorSystem code, it seems to has the same Hnet result as 2 (Hf_Water + Cp_average_Water(T-Tref)) + Hf_Furfural + Cp_average_Furfural(T-Tref) -hf_xylan-Cp_average_Xylan (T-Tref) times the amount of Xylan transformed, but if excess enthalpy (heat of mixing) is taken into account, the above results seem to be different. Because 2 (Hf_Water + Cp_average_Water(T-Tref)) + Hf_Furfural + Cp_average_Furfural(T-Tref) -hf_xylan - Cp_average_Xylan (T-Tref) times the amount of Xylan transformed is calculated as theoretical Hnet (i.e. Hnet when excess enthalpy or heat of mixing is not taken into account). However, there seems to be a heat of mixing when water and furfural are mixed. To illustrate the problem, here is the calculation procedure for Hnet when excess enthalpy is considered, and the class PretreatmentReactorSystem code (seems not to take into account excess enthalpy). Calculation procedure for Hnet when excess enthalpy is considered: XYLAN→Furfural + 2H2O Hf_Water = -285825.0 J/mol Cp_average_Water = 75.50243498981328 J/mol/K Hf_Furfural = -201600.0 J/mol Cp_average_Furfural = 167.0190532693366 J/mol/K Hf_Xylan = -761906.4 J/mol Cp_average_Xylan = 552.2391116 J/mol/K T = 373.91 Let's say we only have Xylan in the inlet stream (assuming that the molar flow is 6.16 kmol/h) The enthalpy flow of inlet stream is : [-761906.4 J/mol+552.24(373.91-298.15)]6.16 kmol/h=-4435623 kJ/h Theoretical outlet stream enthalpy flow is: [-201600.0+167.02(373.91-298.15)]6.16+[-285825.0+75.50(373.91-298.15)]12.32=-4614806 kJ/h Theoretical Hnet is: -4614806 kJ/h+4435623kJ/h=-179183 kJ/h If the excess enthalpy of Furfural and Water in the outlet stream is taken into account (assuming that mixing heat is 380 J/mol), the actual outlet enthalpy flow is: -4614806+380*(6.16+12.32)= -4607783.6 kJ/h Actual Hnet is: -4607783.6++4435623kJ/h=-172161 kJ/h It seems that actual Hnet is different from theoretical Hnet.

The class PretreatmentReactorSystem code is as follows:

import biosteam as bst bst.nbtutorial() from biosteam import Unit from biosteam import units

from thermosteam import MultiStream import thermosteam as tmo

from biorefineries import cellulosic cs = cellulosic.Biorefinery('corn stover ethanol') chemicals_cs = cs.chemicals bst.settings.set_thermo(chemicals_cs) bst.main_flowsheet.set_flowsheet('corn stover_ethanol')

cornstover = bst.Stream( 'Cornstover', Xylan=6.16, P=9*101325, T=100.758+273.15, )

class PretreatmentReactorSystem(bst.units.design_tools.PressureVessel, Unit): _N_ins = 1 _N_outs = 2 _graphics = bst.Flash._graphics _units = {'Residence time': 'hr', 'Reactor volume': 'm3'}

def init(self, ID='', ins=None, outs=(), T=100.758+273.15, V=0, thermo=None, tau=0.166, V_wf=0.8, length_to_diameter=2, vessel_material='Stainless steel 316', vessel_type='Horizontal', reactions=None, run_vle=True): Unit.init(self, ID, ins, outs, thermo) self._load_components() vapor, liquid = self.outs vapor.phase = 'g' self.T = T self.V = V chemicals = self.chemicals if reactions is None: self.reactions = ParallelRxn([

Reaction definition Reactant Conversion

Rxn('Xylan -> Furfural + 2 H2O',                 'Xylan',    1, chemicals),
# Rxn('Glucan + H2O -> GlucoseOligomer',           'Glucan',   0.0030, chemicals),
# Rxn('Glucan + H2O -> Glucose',                   'Glucan',   0.0990, chemicals),
# Rxn('Glucan -> HMF + 2 H2O',                     'Glucan',   0.0030, chemicals), 
# Rxn('Xylan + H2O -> XyloseOligomer',             'Xylan',    0.0240, chemicals),
# Rxn('Xylan + H2O -> Xylose',                     'Xylan',    0.9000, chemicals),
# Rxn('Mannan + H2O -> MannoseOligomer',           'Mannan',   0.0240, chemicals),
# Rxn('Mannan + H2O -> Mannose',                   'Mannan',   0.9000, chemicals), 
# Rxn('Mannan -> HMF + 2 H2O',                     'Mannan',   0.0500, chemicals),
# Rxn('Galactan + H2O -> GalactoseOligomer',       'Galactan', 0.0240, chemicals),     
# Rxn('Galactan + H2O -> Galactose',               'Galactan', 0.9000, chemicals), 
# Rxn('Galactan -> HMF + 2 H2O',                   'Galactan', 0.0500, chemicals),       
# Rxn('Arabinan + H2O -> ArabinoseOligomer',       'Arabinan', 0.0240, chemicals), 
# Rxn('Arabinan + H2O -> Arabinose',               'Arabinan', 0.9000, chemicals), 
# Rxn('Arabinan -> Furfural + 2 H2O',              'Arabinan', 0.0500, chemicals), 
# Rxn('Acetate -> AceticAcid',                     'Acetate',  1.0000, chemicals),      
# Rxn('Furfural + 3 H2O  -> Tar',                  'Furfural',  1.0000, chemicals), 
# Rxn('HMF + 3 H2O  -> 1.2 Tar',                   'HMF',       1.0000, chemicals), 
# Rxn('Lignin -> SolubleLignin',                   'Lignin',    0.0500, chemicals),   
# Rxn('Sucrose -> HMF + Glucose + 2H2O',           'Sucrose',   1.0000, chemicals)
    ])
else:
    self.reactions = reactions
self.tau = tau
self.V_wf = V_wf
self.length_to_diameter = length_to_diameter
self.vessel_material = vessel_material
self.vessel_type = vessel_type
self.run_vle = run_vle

def _load_components(self): thermo = self.thermo self._multistream = MultiStream(None, thermo=thermo)

def _run(self): feed = self.ins[0] vapor, liquid = self.outs liquid.copy_like(feed) self. Reactions(liquid) if self.T: if self.run_vle: ms = self._multistream ms.copy_like(liquid) ms.vle(T=self.T, V=self.V) vapor.mol[:] = ms.imol['g'] liquid.mol[:] = ms.imol['l'] vapor.T = liquid.T = ms.T vapor.P = liquid.P = ms.P else: liquid.T = self.T

Rxn = tmo.reaction.Reaction ParallelRxn = tmo.reaction.ParallelReaction

R201 = PretreatmentReactorSystem('R201', cornstover)

A_sys = bst.main_flowsheet.create_system('A_sys') A_sys.simulate() R201.Hnet

yoelcortes commented 1 year ago

@zasddsgg, when the state of a chemical is set (e.g., Chemical('Glucose', phase='l')), the reference phase also becomes 'l'. Unfortunately, the heat of formation is not updated automatically. I can introduce an error or a warning so that the user knows when they are setting the state of a Chemical something other than the reference state. In general, a single phase chemical should be at the reference phase (otherwise, the heat of formation should be update).

Regarding heat of solution, it would be nice to have them in biosteam (but we do not yet). Still, heats of solution are usually negligible. Any contributions for heats of solution are certainly welcome.

By the way, I could not find the heat of solution of Furfural online... I have a feeling that 380 J/mol may be high for a liquid substance. Could you let me know your reference?

Thanks,

zasddsgg commented 1 year ago

Thanks for your help.

a)For question a, may I confirm with you if my understanding is correct. When build up my own biorefinery process, the state of the chemicals imported from corn stover ethanol model has been set. So the reference phase of these chemicals has also been set. For chemicals not included in corn stover ethanol model, I will import the chemicals through bst.Chemicals and the state and reference phase of these chemicals is always the phase at 25 C at 1 atm, so the state and reference phase of these chemicals are also set. Do I need to change the phase and reference phase of above chemicals (both imported from corn stover ethanol and bst.Chemicals), or if I just use the default settings, will the right enthalpy be calculated?

b)In addition, how do I know if a single-phase chemical is in the reference phase that it would be. Besides, take ethanol, for example, the state and reference phase of ethanol is set to be liquid in the default settings, but in the process, ethanol may be converted into gaseous such as in Flash, so for both liquid state and gaseous state of ethanol in the process, will the right enthalpy of both liquid state and gaseous state of ethanol be calculated according to the default settings, in which the state of ethanol is set to be liquid.

c)For excess enthalpy (it is not heat of solution), just like in https://github.com/BioSTEAMDevelopmentGroup/thermosteam/blob/master/thermosteam/free_energy.py, it seems BioSTEAM has set excess enthalpy, but for reaction XYLAN→Furfural + 2H2O in class PretreatmentReactorSystem, it seems that excess enthalpy is not included when calculating Hnet, because the Hnet for class PretreatmentReactorSystem was the same as the results calculated according to 2 (Hf_Water + Cp_average_Water(T-Tref)) + Hf_Furfural + Cp_average_Furfural(T-Tref) -hf_xylan-Cp_average_Xylan (T-Tref) times the amount of Xylan transformed. If excess enthalpy (enthalpy change in mixing process of H2O and Furfural) is included, like 380 J/mol (it is obtained in corn stover Aspen model built by Humbird et, al.), Hnet of class PretreatmentReactorSystem seems to be different from 2 (Hf_Water + Cp_average_Water(T-Tref)) + Hf_Furfural + Cp_average_Furfural(T-Tref) -hf_xylan-Cp_average_Xylan (T-Tref) times the amount of Xylan transformed. I am a little confused about that. Could I consult you about that.

Thanks for your help. Wish you a good day.

yoelcortes commented 1 year ago

@zasddsgg

a) The right enthalpy will always be calculated. Again, no need to change the reference phase (but if you set the state of a chemical to something other than the reference phase, the chemical state becomes the reference phase). Setting the state of a chemical only make sense if it does not go through any phase equilibrium.

b) Ethanol is not a single-phase chemical. The reference phase is the chemical's phase at 25 C and 1atm. The reference phase is also an attribute: https://biosteam.readthedocs.io/en/latest/API/thermosteam/Chemical.html#thermosteam.Chemical.phase_ref

>>> from biorefineries.cellulosic import create_cellulosic_ethanol_chemicals
>>> chems = create_cellulosic_ethanol_chemicals()
>>> assert  chems.Ethanol.locked_state is None
>>> for phase in ('g', 'l', 's'): assert hasattr(chems.Ethanol.H, phase)

c) Excess enthalpy for a pure component chemical in the gas phase is due to low temperatures and high pressures, nothing to do with solutions. I recommend double checking if that value (380 J/mol) is actually the heat of solution and how does Aspen calculate it.

Thanks,

yoelcortes commented 1 year ago

One more thing, to include excess pure-component energies you can run the following:

bst.settings.set_thermo(chemicals)
bst.settings.mixture.include_excess_energies = True

Here is a longer example and with detailed explanations: https://biosteam.readthedocs.io/en/latest/tutorial/Convergence.html#Importance-of-thermodynamic-property-package

You also need to run the following for including pure-component excess energies in utility agents (this might affect results concerning flows, but too significantly):

for i in bst.settings.cooling_agents + bst.settings.heating_agents: i.mixture.include_excess_energies = True

Thanks,

zasddsgg commented 1 year ago

Thanks for your help.

a) May I confirm with you if my understanding is correct. For chemicals involved in phase equilibrium, such as water and ethanol, the phase and reference phase is the chemical's phase at 25 C and 1atm. For chemicals in corn stover ethanol model or impoted through bst.Chemicals, just use their default settings. For chemicals that don't participate in phase equilibrium, namely the single-phase chemical, if they are in the corn stover ethanol model or imported through bst.Chemicals, just use the default phase state and reference phase state (the selection of solid or liquid state does not matter). Therefore, for all the chemicals, whether in corn stover ethanol model or imported through bst.Chemicals, I do not need to modify the phase state and reference state, just use the default setting.

b) The calculation method in Aspen is: HLMX=∑_i▒x_i HL_i+HLXS HLMX is liquid mixture molar enthalpy, HL is liquid pure component molar enthalpy, HLXS is liquid mixture molar excess enthalpy. HLXS is calculated directly from the activity coefficient model. HLMX times the molar flow of the liquid mixture, so the enthalpy flow of the liquid mixture is obtained, then plus the enthalpy flow of a solid, like XYLAN, and enthalpy flow of the stream is obtained. So (∑_i▒x_i HL_i+HLXS) molar flow of the liquid mixture, namely liquid mixture enthalpy flow, is the pure component enthalpy flow plus liquid mixture excess enthalpy flow, but seems to be in BioSTEAM, only the pure component enthalpy flow is computed instead of considering liquid mixture excess enthalpy flow, this is the difference between BioSTEAM and Aspen plus. To illustrate this problem, I have selected two feed cases. The first case, the feed stream was only XYLAN, 6.16 kmol/h, and the outlet stream was 6.16 kmol/h Furfural and 12.32 kmol/h H2O. The HLXS calculated by Aspen is 380 J/mol. So liquid mixture excess enthalpy flow is 380(6.16+12.32)=7022.4 kJ/h Plus the enthalpy flow change of the pure component in the inlet and outlet stream, namely -179183 kJ/h (in this part, Aspen and BioSTEAM calculated the same results), the Hnet is -179183+7022.4=-172160.6 kJ/h

The second case. The feed is 1000 kmol/h water, 6.16kmol /h XYLAN, then the outlet strean is 6.16kmol /h Furfural and 1012.32kmol /h H2O. The HLXS calculated by Aspen was 68.8 J/mol. So is liquid mixture excess enthalpy flow is 68.8*(1012.32+6.16)=70071 kJ/h. Plus the enthalpy flow change of the pure component in the inlet and outlet stream, namely -179183 kJ/h (in this part, Aspen and BioSTEAM calculated the same results), the Hnet is -179183+70071=-109112 kJ/h. In both cases, Hnet calculated by BioSTEAM is -179183 kJ/h. It seems to be caused by liquid mixture excess enthalpy flow. Could I ask you if there is any setting for calculating liquid mixture excess enthalpy flow in BioSTEAM.

c) I added bst.settings.mixture.include_excess_energies = True in the code, calculated Hnet is still - 179183 kJ/h. I have a little confused for this, could I consult you for this.

Thanks for your help. Wish you a good day.

yoelcortes commented 1 year ago

@zasddsgg

a) Yes, this is all accurate.

b) Excellent, thanks for looking into this. Unfortunately, BioSTEAM does not have any excess mixture energy calculation yet (only pure component excess energies for the gas phase). I think what is most important is the difference between Hnet at the outlet and inlet (only the duty will affect your results). To check how off results from BioSTEAM are to Aspen, I would suggest looking at the change in enthalpy... Did you also account for the excess enthalpy flow at the inlet?

c) Your results did not change because only pure-component gas phase excess energies are implemented (liquid excess energies are not yet available).

I hope this helps!

zasddsgg commented 1 year ago

Thanks for your help.

a) For Hnet results between Aspen and BioSTEAM. For both cases, since the feed consists of either Xylan or Xylan and water (only water is liquid and Xylan is solid), so excess mixture enthalpy flow in the inlet is 0. And the outlet stream contains Furfural and water, so there is excess mixture enthalpy flow. Therefore, the Hnet differences in the two feed conditions ultimately come from excess mixture enthalpy flow of the outlet stream. In fact, Cp_average_XYLAN (solid state) simulated by Aspen is 174.45 J/mol/K, Hf_Xylan (25 ℃,solid state) -762420 J/mol, Cp_average_Furfural (liquid state) 155.44 J/mol/K,Hf_Furfural (25 ℃,liquid state) -199560 J/mol, Cp_average_Water (liquid state) 77.7 J/mol/K,Hf_Water (25 ℃,liquid state) -285800 J/mol. In BioSTEAM, Cp_average_XYLAN (solid state) 552.24 J/mol/K,Hf_Xylan (25℃,solid state) -761906.4 J/mol, Cp_average_Furfural (liquid state) 167.02 J/mol/K,Hf_Furfural (25℃,liquid state)为-201600 J/mol, Cp_average_Water (liquid state) 75.50 J/mol/K,Hf_Water (25℃,liquid state) -285825 J/mol It seems that the Cp_average_XYLAN (solid state) is quite different. If the excess mixture enthalpy flow is excluded, the Hnet is calculated according to the Cp_average and Hf of Aspen and BioSTEAM respectively. BioSTEAM calculated a Hnet of -179183 kJ/h. Aspen calculated a Hnet of 9797.13 kJ/h. This difference is mainly caused by Cp_average and Hf of each substance between BioSTEAM and Aspen. I have tried the following two cases, and the temperature change is 75.758: If Cp_average_XYLAN is changed from 552.24 of BioSTEAM to 174.45 (obtained in Aspen), and the remaining Cp_average and Hf parameters of BioSTEAM are adopted, Hnet is 2( -285825+ 75.5075.758)+(-201600+167.0275.758)-(-761906.4+174.4575.758)= -2876.63 kJ/h. If the Cp_average and Hf parameters of each substance obtained by Aspen are adopted, the Hnet calculated is 2( -285800+ 77.775.758)+(-199560+155.4475.758)-(-762420+174.4575.758)= 9808.65 kJ/h On this basis, if excess mixture enthalpy flow is taken into account, BioSTEAM's Hnet is still -179183 kJ/h. For Aspen, if there is only 6.16 kmol/h Xylan in the feed, the Hnet is 9797.13+7022.4 (excess mixture enthalpy flow)=16819.53 kJ/h. If the feed is 1000 kmol/h H2O and 6.16 kmol/h Xylan, then Hnet is 9797.13+70071 (excess mixture enthalpy flow)=79868 kJ/h. The excess mixture enthalpy flow seems to have a significant impact on Hnet.

b) May I confirm with you if my understanding is correct. In saccharification.py of corn stover ethanol model ((https://github.com/BioSTEAMDevelopmentGroup/Bioindustrial-Park/blob/master/biorefineries/cellulosic/systems/fermentation/saccharification.py), energy_balance = False was set, this and bst.settings.mixture.include_excess_energies = False is play the same role, that is do not consider pure component excess energies for the gas phase. Since the corn stover model does not involve gas under low temperature and high pressure, so energy_balance=False is set, indicating that pure component excess energies for the gas phase is not considered. In this way, compared with energy_balance=True, it's the same calculation result, but it saves calculation time.

c) Excess energy will be taken into account for low temperature and high pressure gases, could I consult you what is the specific range of low temperatures and high pressures. For energy_balance=False set in saccharification.py, does that mean the default setting is energy_balance=True? If energy_balance=False is not set, will the emulation be performed at energy_balance=True? When the gas under low temperature and high pressure is not involved, energy_balance= False and energy_balance=True have no effect on the result, so If want to save calculation time, I need to manually set energy_balance=False.

Thanks for your help. Wish you a good day.

yoelcortes commented 1 year ago

@zasddsgg.

a) Thanks so much for all the details, I will update Cp for Xylan, Glucan, and similar components. I plan on including excess mixture energies through activity coefficients by the end of the year.

b and c) When "energy_balance" is True, it means to also conserve enthalpy by solving for the temperature of the effluent. There is no need to perform an energy balance if the process is not adiabatic (which is the case for the Saccharification unit). Excess energies should be taken into account for low temperature and high pressure (10 atm or more, but not sure at what temperature) gases. You'll need to set bst.settings.mixture.include_excess_energies = True on your own to account for residual (excess) enthalpies for a pure component gases.

Thanks,

zasddsgg commented 1 year ago

Thank you very much for your help.

a) I carefully compared Cp and H of various chemicals in BioSTEAM and Aspen, and the results are as follows: The values obtained by Aspen are in parentheses. T = 373.91,Tref = 298.15, Hf is at 25℃. The phase states of matter are also in parentheses. Hf_Water(l)= -285825.0 J/mol(-285800),Cp_average_Water(l)= 75.50243498981328 J/mol/K(77.70) Hf_Glucan(s) = -975708.8 J/mol(-976360),Cp_average_Glucan(s) = 677.747708 J/mol/K(45.75) Hf_GlucoseOligomer(l) = -975708.8 J/mol(-994260),Cp_average_GlucoseOligomer(l) = 245.73278400000004 J/mol/K(502.58) Hf_Glucose(l) = -1271100.0 J/mol(-1280000),Cp_average_Glucose(l) = 245.73278400000004 J/mol/K(502.58) Hf_HMF(l) = 0 J/mol(-417330),Cp_average_HMF(l) = 195.13174845967004 J/mol/K(230.13) Hf_Xylan(s) = -761906.4 J/mol(-762420),Cp_average_Xylan(s) = 552.2391116 J/mol/K(174.45) Hf_XyloseOligomer(l) = -761906.4 J/mol(-791380),Cp_average_XyloseOligomer(l) = 204.77732 J/mol/K(476.67) Hf_Xylose(l) = -1043700.0 J/mol(-1070000),Cp_average_Xylose(l) = 204.77732 J/mol/K(458.79) Hf_Furfural(l) = -201600.0 J/mol(-199560),Cp_average_Furfural(l) = 167.0190532693366 J/mol/K(155.44) Hf_Mannan(s) = -975708.8 J/mol(-976360),Cp_average_Mannan(s) = 677.747708 J/mol/K(45.75) Hf_MannoseOligomer(l) = -975708.8 J/mol(-994260),Cp_average_MannoseOligomer(l) = 245.73278400000004 J/mol/K(502.58) Hf_Mannose(l) = -1271100.0 J/mol(-1280000),Cp_average_Mannose(l) = 245.73278400000004 J/mol/K(502.58) Hf_Galactan(s) = -975708.8 J/mol(-976360),Cp_average_Galactan(s) = 677.747708 J/mol/K(45.75) Hf_GalactoseOligomer(l) = -975708.8 J/mol(-994260),Cp_average_GalactoseOligomer(l) = 245.73278400000004 J/mol/K(502.58) Hf_Galactose(l) = -1271100.0 J/mol(-1280000),Cp_average_Galactose(l) = 245.73278400000004 J/mol/K(502.58) Hf_Arabinan(s) = -761906.4 J/mol(-762420),Cp_average_Arabinan(s) = 552.2391116 J/mol/K(174.45) Hf_ArabinoseOligomer(l) = -761906.4 J/mol(-791380),Cp_average_ArabinoseOligomer(l)= 204.77732 J/mol/K(476.67) Hf_Arabinose(l) = -1043700.0 J/mol(-1070000),Cp_average_Arabinose(l) = 204.77732 J/mol/K(476.67) Hf_Acetate(s) = -103373.0 J/mol(-456330),Cp_average_Acetate(s) = 137.39869090946124 J/mol/K(121.18) Hf_AceticAcid(l) = -483580.0 J/mol(-457110),Cp_average_AceticAcid(l) = 137.39869090946124 J/mol/K(80.50) Hf_Tar(s) = -1043700.0 J/mol(-762420),Cp_average_Tar(s) = 204.77732 J/mol/K(174.45) Hf_Lignin(s) = -452909.63200000004 J/mol(-453210),Cp_average_Lignin(s) = 207.52894447999998 J/mol/K(207.46) Hf_SolubleLignin(l) = -452909.63200000004 J/mol(-454840),Cp_average_SolubleLignin(l) = 207.52894447999998 J/mol/K(269.79) Hf_Sucrose(l) = -2221200.0 J/mol(-2010000),Cp_average_Sucrose(l) = 466.89239872 J/mol/K (444.23) Hf_Cellobiose(l) = -2012085.6 J/mol(-2010000),Cp_average_Cellobiose(l) = 1430.7992863999998 J/mol/K(444.23) Hf_NH3(g) = -45558.0 J/mol(-45898),Cp_average_NH3(g) = -185.88026253631068 J/mol/K(36.71) Hf_H2SO4(l) = -814000.0 J/mol(-793360),Cp_average_H2SO4(l) = 100.12341903878466 J/mol/K(89.56) Hf_AmmoniumAcetate(l)= 0 J/mol(-647710),Cp_average_AmmoniumAcetate(l) = 114.56857865147285 J/mol/K(61.07) Hf_AmmoniumSulfate(l) = -1180900.0 J/mol(-1210000),Cp_average_AmmoniumSulfate(l) = 180.23830528000002 J/mol/K(204.66) Hf_Ethanol(l) = -277030.0 J/mol(-277510),Cp_average_Ethanol(l) = 130.6571520761024 J/mol/K(139.76) Hf_CO2(g) = -393474.0 J/mol(-393510),Cp_average_CO2(g) = 38.7888690827739 J/mol/K(39.04) Hf_DAP(l) = -1566900.0 J/mol(-1190000),Cp_average_DAP(l) = 188.0 J/mol/K(61.07) Hf_Protein(s) = -73713.712 J/mol(-73763),Cp_average_Protein(s) = 95.46859920399999 J/mol/K(35.53) Hf_CSL = -328408.04000000004 J/mol, Cp_average_CSL = 155.65053230099997 J/mol/K Hf_Z_mobilis(s) = -130412.72776000001 J/mol(-130500),Cp_average_Z_mobilis(s) = 102.93681375999999 J/mol/K(38.41) Hf_Glycerol(l) = -668600.0 J/mol(-667410),Cp_average_Glycerol(l) = 236.5284887860894 J/mol/K(204.08) Hf_O2(g) = 0 J/mol(-3.73E-12),Cp_average_O2(g) = 29.60447195902491 J/mol/K (29.57) Hf_SuccinicAcid(l) = -940260.0 J/mol(-919790),Cp_average_SuccinicAcid(l) = 516.4585477286106 J/mol/K(260.08) Hf_Xylitol(l) = -1017318.68 J/mol(-1040000),Cp_average_Xylitol(l) = 635.9693603999999 J/mol/K(285.08) Hf_LacticAcid(l) = -668268.448 J/mol(-690500),Cp_average_LacticAcid(l) = 151.4441489926937 J/mol/K(288.58)

The following parameters seem to vary considerably: Cp_average_Glucan(s),Hf_GlucoseOligomer(l),Cp_average_GlucoseOligomer(l),Hf_Glucose(l) ,Cp_average_Glucose(l),Hf_HMF(l),Cp_average_HMF(l),Cp_average_Xylan(s),Hf_XyloseOligomer(l),Cp_average_XyloseOligomer(l),Hf_Xylose(l),Cp_average_Xylose(l), Hf_Furfural(l),Cp_average_Furfural(l),Cp_average_Mannan(s),Hf_MannoseOligomer(l),Cp_average_MannoseOligomer(l),Hf_Mannose(l),Cp_average_Mannose(l), Hf_Galactan(s),Cp_average_Galactan(s), Hf_GalactoseOligomer(l),Cp_average_GalactoseOligomer(l), Hf_Galactose(l),Cp_average_Galactose(l) , Hf_Arabinan(s),Cp_average_Arabinan(s) , Cp_average_ArabinoseOligomer(l),Hf_Arabinose(l),Cp_average_Arabinose(l) ,Hf_Acetate(s,Cp_average_Acetate(s),Hf_AceticAcid(l),Cp_average_AceticAcid(l) ,Hf_Tar(s),Cp_average_Tar(s) ,Hf_SolubleLignin(l),Cp_average_SolubleLignin(l), Hf_Sucrose(l),Cp_average_Sucrose(l) , Hf_Cellobiose(l),Cp_average_Cellobiose(l) , Hf_NH3(g),Cp_average_NH3(g), Hf_H2SO4(l),Cp_average_H2SO4(l), Hf_AmmoniumAcetate(l),Cp_average_AmmoniumAcetate(l), Hf_AmmoniumSulfate(l),Cp_average_AmmoniumSulfate(l), Hf_Ethanol(l),Cp_average_Ethanol(l) , Hf_DAP(l),Cp_average_DAP(l) , Cp_average_Protein(s), Cp_average_Z_mobilis(s) , Hf_Glycerol(l),Cp_average_Glycerol(l), Hf_SuccinicAcid(l) ,Cp_average_SuccinicAcid(l) , Hf_Xylitol(l),Cp_average_Xylitol(l) , Hf_LacticAcid(l),Cp_average_LacticAcid(l)

The above differences seem to lead to Hnet differences, for example, for Xylan -> Furfural + 2 H2O, even if Cp_average_Xylan adopts Aspen's value of 174.45 J/mol/K, for the remaining chemicals, Hf and Cpaverage, using BioSTEAM's values, the calculated Hnet is -2876.63 kJ/h, while Aspen's Hnet is 9797.13 kJ/h. This difference seems to be due to the differences between BioSTEAM and Aspen in HfXylan, Hf Furfural, Hf_ H2O, Cpaverage Furfural, Cpaverage H2O. This seemingly small difference between Hf and Cp ultimately results different Hnet between BioSTEAM and Aspen,in the same reaction, with BioSTEAM's Hnet being exothermic while Aspen's endothermic (even if the excess mixture enthalpy flow is excluded). I am a little confused for that. Could you let me know the source of BioSTEAM's data on Hf and Cp_average? Because the difference between Hf and Cp_average seems to lead to different Hnet of each reaction, which ultimately results in a little big difference between BioSTEAM's calculated results and Aspen's.

b) May I confirm with you if my understanding is correct. Energy_balance is not the same as excess energies. Energy_balance refers to the equivalence of import and export enthalpy, namely whether the unit is adiabatic. Excess energies means that excess energies should be taken into account for gas in low temperature and high pressure. Set either Energy_balance=True or self.reactions.adiabatic_reaction is all OK because they plays the same role. I don't need to set both because they are all guaranteed to be adiabatic.

c) Is Energy_balance=True the default setting for all units?

Thanks for your help. Wish you a good day.

yoelcortes commented 1 year ago

@zasddsgg,

a) Lignocellulosic heats of formation are taken directly from Humbird's 2011 corn stover report. I recently updated the heat capacities of lignocellulosic components to 1.364 J/g/K (which is common at 25C), but in the future it may be updated further to be more temperature dependent (https://www.sciencedirect.com/science/article/pii/S0016236113006856#f0005). The heat capacities of lignocellulosic components listed in your aspen model seem to be too high (around 2.7 J/g/K?).

By the way, your calculation of the average heat capacity in BioSTEAM is incorrect for some chemicals. I think you may be using the previous formulation I used which is only valid for components with a liquid reference phase. The following should work for all chemicals:

>>> import biosteam as bst
>>> bst.Chemical('SuccinicAcid').Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15)
182.12947374101495

b) Almost correct: if your unit is adiabatic, you should use the adiabatic_reaction method. The default for mixing is energy_balance=True.

c) Unit objects in general do not have have a energy_balance attribute. The energy_balance parameter is only for the Stream mix_from method. energy_balance=False is only used where it makes sense and is not an option for Unit objects.

Thanks,

zasddsgg commented 1 year ago

Thank you very much for your help. a) Could I consult you is there a problem with the enthalpy I listed above obtained from the formula (call it formula a later) you used before? b) I did use the formula (formula a) you used before, but if there was a problem in the calculated heat capacity, why was the Hnet calculated for each reaction in the pretreatment reactor with the formula (formula a) the same as that in the class PretreatmentReactorSystem? c) I compared the Hf Settings in chemicals.py (https://github.com/BioSTEAMDevelopmentGroup/Bioindustrial-Park/blob/master/biorefineries/cellulosic/chemicals.py) and the following several chemicals seem to be inconsistent with Humbird's 2011 corn stover report: GlucoseOligomer’s Hf is -2332004.184=-975708.8 J/mol, while corn stover report is -192875.344.184=-806990.42 J/mol. XyloseOligomer’s Hf is -1821004.184=-761906.4J/mol, while corn stover report is -149412.584.184=-625142.23J/mol Xylose's Hf is called directly via tmo.Chemical, is -1043700 J/mol, while corn stover report is -216752.654.184=906893.09 J/mol HMF's Hf is 0,while corn stover report is -79774.534.184=-333776.63 J/mol d) I used bst.Chemical('SuccinicAcid').Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15) (denoted as formula b) to calculate Cp of each substance: For the following chemicals whose reference phase states are liquid state, the values of Cp obtained by formula b and formula a are different. Could I consult you which formula is going to work out? The values obtained by formula a are in parentheses. Glucan, 302.66(677.75),lignin, 2537.07(207.53),Cellobiose,569.63(1430.8),Xylitol,270.63(635.97) For the substance phase_ref='s' below, which one is right, formula b or formula a? The value obtained by formula a is in parentheses. Glucose,302.66(245.73),Xylose,252.22(204.78),Mannose,302.66(245.73),Sucrose,569.63(466.89),AmmoniumAcetate,144.01(114.57),AmmoniumSulfate,197.19(180.24),SuccinicAcid,182.13(516.46) For the substance phase_ref='g' below, which one is right, formula b or formula a? The value obtained by formula a is in parentheses. NH3,88.52(-185.88),CO2,11526(38.79),O2, 33.86(29.6) For the chemicals whose reference phase is the gas state, is the Cp_average calculated by formula b refers to the Cp_average of chemicals in the gas phase or liquid state? For the chemicals whose reference phase is the liquid state, is the Cp_average calculated by formula b refers to the Cp_average of chemicals in the solid phase or liquid state? For the chemicals whose reference phase is the solid state, is the Cp_average calculated by formula b refers to the Cp_average of chemicals in the solid phase or liquid state? e) For chemicals in corn stover ethanol model and imported through bst.Chemicals, how to check the Hf and Cp_average of chemicals? f) For Cp_average, if view Cp_average by formula b, is Cp_average obtained by formula b refers to the Cp_average of chemicals in the liquid state (It doesn't matter if the reference phase of chemical is liquid or solid or gas state)\ g) For formula b, I encounter the following error: bst.Chemical('GlucoseOligomer').Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15):Cause an error,LookupError: chemical 'GlucoseOligomer' not recognized. For Xylan, XyloseOligomer, MannoseOligomer, Galactan, GalactoseOligomer, Arabinan, ArabinoseOligomer, Tar, SolubleLignin, DAP, Protein, CSL, and Z_mobilis are also the same errors. For the above error, I used the chemicals in the corn stover ethanol model. chemicals = cs.create_cellulosic_ethanol_chemicals() chemicals.GlucoseOligomer.Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15) But cause an error, AttributeError: 'HeatCapacitySolid' object has no attribute 'l'. chemicals.Xylan.Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15) also cause error, AttributeError: 'HeatCapacityLiquid' object has no attribute 'l' bst.Chemical('Mannan').Cn.l.T_dependent_property_integral(298.15, 373.15) / (373.15 - 298.15) also cause error, ValueError: math domain error Could I consult you some suggestions for above errors? h) The Cp of Glucan set by default in chemical. py is 1.364 J/g/K, and 220 J/mol/K is obtained by multiplying its molecular weight 162g/mol, which is different from the Cp obtained by formula a (677) and formula b (302). The same is true for Xylitol, 1.364152=207 J/mol/K. It's a different Cp than formula a (636) and formula b (270). Also, Cellobiose, 1.364342=467 J/mol/K, different from formula a (1430) and formula b (570). Also, Glucose, 1.364*180=246 J/mol/K, different from formula b (302). i) Like Xylan and Glucose, BioSTEAM set the Xylan reference phase l, Glucose reference phase s, if I want to compare the difference in Hf and Cp_average of chemicals in class PretreatmentReactorSystem or fermentation system, between BioSTEAM and Aspen. For chemicals whose reference phase are l, such as Xylan, should I compare the Hf and Cp_average of these chemicals in liquid state or solid state (For different states of the same chemical, the chemical’s Hf and Cp_average seems to be different)? For chemicals whose reference phase are s, such as Glucose, should I compare Hf and Cp_average of these chemicals in liquid state or solid state? (Because Xylan in Aspen is solid state and Glucose is dissolved state) j) For class PretreatmentReactorSystem or fermentation system of XYLAN, Glucan this kind of material, should I view Hf and Cp_average of chemical in solid state (even if the chemical’s reference phase is liquid state). For substances like Glucose, xylose, should I check the Hf and Cp_average of them in the liquid state (even if the reference phase state is solid). For NH3, CO2 and O2, should I check the Hf and Cp_average of them in the gaseous state. k) The molecular weight of Glucan in corn stover ethanol model and Glucan in bst.Chemical seems to be different. The molecular weight of Glucan in corn stover ethanol model is 162, and that is 180 in bst.Chemical. Hf is also different. Hf of Glucan in corn stover ethanol model is -9.7571e+05 J/mol, which is consistent with the corn stover report, while the Hf of bst.Chemical('Glucan') is -1.4922e+06 J/mol.

I'm sorry for all the questions, because I think enthalpy and Cp are important for the accuracy of the results. Thanks for your help. Wish you a good day.

yoelcortes commented 1 year ago

@zasddsgg a, b) ~Terms cancel out when calculating the enthalpy difference (that's why it gives the same Hnet).~ Edit, I'm not sure what formula are you using or if the results you are getting is actually the same as Hnet. Note that the enthalpy of a chemical with a reference phase, temperature, and pressure also includes latent heats of fusion and vaporization (it is a state function). Your calculation of Cp_average was off possibly because you are including latent heats. I really encourage you to read up more on free energies and state functions. I cannot help you further with any demonstrations on how to calculate enthalpy.

c) Check page 112. Note that Hf of glucose oligomer is 233200 cal/mol

d) The Cn.l refers to liquid, Cn.g to gas, and Cn.s to solid. Chemicals with a single phase do not have these attributes, just use Cn directly. Examples are listed in the docs: https://biosteam.readthedocs.io/en/latest/tutorial/Thermosteam_101.html. Regarding your other questions, please review the source code on enthalpy calculation or read literature on thermodynamics for additional details.

e) Use Chemical.Hf and Chemical.Cn

f) You must use the correct phase (g if its a gas, l if its a liquid, and s if its a solid).

g) Please use the chemical imported from the cornstover module.

h) You are getting different values because you have not updated your local Bioindustrial-Park, biosteam, and thermosteam repositories. The pip installation is not available yet.

i, j) There is only one phase for these chemicals in the cornstover module. The following should work Glucose.Cn(298.15).

k) The molecular weight of Glucan in Humbird's 2011 report and the BioSTEAM model are both 162: image

>>> from biorefineries import cellulosic as c
>>> brf = c.Biorefinery()
>>> brf.chemicals.Glucan.MW
162.1406

Again, use the chemicals from the cellulosic/cornstover module.

Thanks,

zasddsgg commented 1 year ago

Thank you very much for your advice and help. I have installed the latest biorefinery-park on github and checked the Cp_average and Hf of relevant components. May I confirm with you whether the Cp_average and Hf I checked and my understanding below are correct? Thanks for your help.

All the chemicals are imported via chemicals = cs.create_cellulosic_ethanol_chemicals(). For Cp_average:J/mol/K Glucan,Mannan,Galactan,221.16 Xylan,Arabinan,180.20 Lignin,SolubleLignin,Xylitol,207.53 GlucoseOligomer,MannoseOligomer,GalactoseOligomer,Glucose,Mannose,Galactose,CellulaseNutrients,Extract,245.73 XyloseOligomer,ArabinoseOligomer,Xylose,Arabinose,Tar,204.78 Sucrose,466.89 CaSO4,185.70 AmmoniumSulfate,180.24 Cellulose,221.16 Cellobiose,466.89 The Cp_average of the above chemicals is obtained by chemical.Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) (when view Cp_average of single_phase chemical,no phase (l,g,s) between above chemical.Cn and T), since the above chemicals have been set Cp_cellulosic=1.364, therefore, Cp_average can also be viewed by chemical.Cn(298.15).

Water (l),75.50 Furfural (l),167.02 Ethanol(l), 130.66 Glycerol(l), 236.53 chemical.Cn.l.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is used for the above substance. For a substance that is not single_phase, the phase state needs to be specified after between above chemical.Cn and T. To view the Cp_average of Furfural in the gaseous state, chemical.Cn g.T. dependent_property_integral(298.15, 373.91)/(373.91-298.15) should be used.

HMF,195.13 Obtained by HMF.Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15). it has been set to be liquid phase for HMF (https://github.com/BioSTEAMDevelopmentGroup/Bioindustrial-Park/blob/master/biorefineries/cellulosic/chemic als.py), so the Cp_average of HMF under the specified phase state (for HMF, the specified phase state is set as liquid state) can be viewed through HMF.Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15), and since HMF has been specified the phase state as liquid, so no phase (l,g,s) in HMF.Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15).

Acetate (l),AceticAcid (l),142.85 LacticAcid (l), 151.44 Obtained by Cn.l.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15).

SuccinicAcid (l),182.27 Obtained by Cn.l.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15).

H2SO4(l), 100.12 AmmoniumAcetate(s), 126.77 CO2(g), 38.79 DAP(s), 188.0 Protein(l), 95.47 Z_mobilis(l), 102.94 O2(g), 29.60 Obtained by Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15). Since the above substance is the single_phase substance, the Cp_average of the substance viewed by Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is the Cp_average of the substance in the default reference phase state. For example, the default reference phase for AmmoniumAcetate is solid, therefore, the Cp_average viewed by Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is the Cp_average of solid-state AmmoniumAcetate. For H2SO4, the default reference phase state is liquid, so the Cp_average viewed by Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is the Cp_average of liquid-state H2SO4. For CO2, the default reference phase is gas state, so the Cp_average viewed by Cn.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is the Cp_average of gaseous CO2.

NH3(g),36.72 The Cp_average viewed by NH3.Cn.g.T_dependent_property_integral(298.15, 373.91) / (373.91 - 298.15) is the Cp_average of gaseous NH3.

For Hf:J/mol Glucan,Mannan,Galactan,-975708.8 Xylan,Arabinan,-761906.4 Lignin,-452909.63 GlucoseOligomer,MannoseOligomer,GalactoseOligomer,-975708.8 XyloseOligomer,ArabinoseOligomer,-761906.4 Glucose,Mannose,Galactose,CellulaseNutrients,Extract,-1271100.0 Xylose,Arabinose,Tar,-1043700 SolubleLignin,-452909.63 Xylitol,-1017318.68 Sucrose,-2221200.0 CaSO4,-1434500.0 AmmoniumSulfate,-1180900.0 Cellulose,-975709.05 Cellobiose,-2012085.6 Water,-285825.0 HMF,0 Furfural,-201600.0 Acetate,AceticAcid,-483580.0 SuccinicAcid,-940260.0 NH3,-45558.0 H2SO4,-814000.0 AmmoniumAcetate,0 Ethanol,-277030.0 CO2,-393474.0 DAP,-1566900.0 Protein,-73713.712 Z_mobilis,-130412.73 Glycerol,-668600.0 O2,0 LacticAcid,-668268.45 The Hf of above substances are obtained by chemical.Hf. The Hf obtained by chemical.Hf is at 25 degrees, which is also the Hf of the chemical in the default reference phase state (default reference phase state can be viewed by calling the chemical directly). For example, SuccinicAcid, phase_ref='s' is found by code chemicals. SuccinicAcid, so the Hf obtained by chemicals. SuccinicAcid.Hf is the Hf of SuccinicAcid at 25 degrees and at solid state.

Thanks for your help. Wish you a good day.