From 564a47886eb87b6d4a5a6c4e2529301185d8ae62 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 22 Oct 2024 10:51:13 -0700 Subject: [PATCH 1/3] add doctest for `DiffusedAeration` --- qsdsan/processes/_aeration.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/qsdsan/processes/_aeration.py b/qsdsan/processes/_aeration.py index d5a0ffec..9da6d678 100644 --- a/qsdsan/processes/_aeration.py +++ b/qsdsan/processes/_aeration.py @@ -80,6 +80,25 @@ class DiffusedAeration(Process): [parameters] KLa: 240 DOsat: 8 [dynamic parameters] + + >>> aer2 = pc.DiffusedAeration('aer2', 'S_O', KLa_20=100, V=1000, d_submergence=3.7) + >>> aer2.show() + Process: aer2 + [stoichiometry] S_O: 1 + [reference] S_O + [rate equation] KLa*(DOsat - S_O) + [parameters] KLa: 60 + DOsat: 9.87 + [dynamic parameters] + + >>> aer2.Q_air # doctest: +ELLIPSIS + 12470.65... + >>> round(aer2.SOTR / 1000) + 1039 + + >>> aer3 = pc.DiffusedAeration('aer3', 'S_O', Q_air=7600, V=1000, d_submergence=3.7) + >>> aer3.kLa # doctest: +ELLIPSIS + 36.56... """ @@ -357,5 +376,7 @@ def DOsat(self): return self._DOsat @DOsat.setter def DOsat(self, DOsat): + if DOsat is not None: + self._DOsat_s20 = DOsat / (self.tau * self._beta * self.Omega * self.delta) self._DOsat = DOsat or self._calc_DOsat() self.set_parameters(DOsat = self._DOsat) \ No newline at end of file From b8b55aa14ed392dfdb84c58087e7458a77f49c6e Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 22 Oct 2024 14:14:23 -0700 Subject: [PATCH 2/3] add test for `mASM2d` --- qsdsan/processes/_asm2d.py | 46 +++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/qsdsan/processes/_asm2d.py b/qsdsan/processes/_asm2d.py index d12e90c5..c2a99b7e 100644 --- a/qsdsan/processes/_asm2d.py +++ b/qsdsan/processes/_asm2d.py @@ -73,8 +73,6 @@ def create_asm2d_cmps(set_thermo=True): return cmps_asm2d -# create_asm2d_cmps() - def create_masm2d_cmps(set_thermo=True): c2d = create_asm2d_cmps(False) ion_kwargs = dict(particle_size='Soluble', @@ -433,7 +431,7 @@ class ASM2d(CompiledProcesses): Examples -------- - >>> from qsdsan import processes as pc, set_thermo + >>> from qsdsan import processes as pc >>> cmps = pc.create_asm2d_cmps() >>> asm2d = pc.ASM2d() >>> asm2d.show() @@ -714,6 +712,8 @@ class mASM2d(CompiledProcesses): electron_acceptor_dependent_decay : bool, optional Whether biomass decay kinetics is dependent on concentrations of electron acceptors. The default is True. + pH_ctrl : float or None, optional + Whether to fix pH at a specific value or solve for pH (`None`). The default is 7.0. k_h : float, optional Hydrolysis rate constant, in [d^(-1)]. The default is 3.0. eta_NO3_Hl : float, optional @@ -766,6 +766,46 @@ class mASM2d(CompiledProcesses): >>> asm.show() mASM2d([aero_hydrolysis, anox_hydrolysis, anae_hydrolysis, hetero_growth_S_F, hetero_growth_S_A, denitri_S_F, denitri_S_A, ferment, hetero_lysis, storage_PHA, aero_storage_PP, anox_storage_PP, PAO_aero_growth_PHA, PAO_anox_growth, PAO_lysis, PP_lysis, PHA_lysis, auto_aero_growth, auto_lysis, CaCO3_precipitation_dissolution, struvite_precipitation_dissolution, newberyite_precipitation_dissolution, ACP_precipitation_dissolution, MgCO3_precipitation_dissolution, AlPO4_precipitation_dissolution, FePO4_precipitation_dissolution]) + >>> # Calculate process rate given state variable values and fixed pH. + >>> import numpy as np + >>> state_arr = np.ones(len(cmps)) + >>> rhos = asm.rate_function(state_arr) # reaction rate for each process + >>> for i,j in zip(asm.IDs, rhos): + ... print(f'{i}{(40-len(i))*" "}{j:.3g}') + aero_hydrolysis 2.27 + anox_hydrolysis 0.182 + anae_hydrolysis 0.0606 + hetero_growth_S_F 0.471 + hetero_growth_S_A 0.471 + denitri_S_F 0.0503 + denitri_S_A 0.0503 + ferment 0.0333 + hetero_lysis 0.356 + storage_PHA 0.594 + aero_storage_PP 1.06 + anox_storage_PP 0.0851 + PAO_aero_growth_PHA 0.778 + PAO_anox_growth 0.0622 + PAO_lysis 0.174 + PP_lysis 0.174 + PHA_lysis 0.174 + auto_aero_growth 0.33 + auto_lysis 0.111 + CaCO3_precipitation_dissolution 0 + struvite_precipitation_dissolution 0 + newberyite_precipitation_dissolution 0 + ACP_precipitation_dissolution 0 + MgCO3_precipitation_dissolution 0 + AlPO4_precipitation_dissolution 1.82e-11 + FePO4_precipitation_dissolution 1.82e-11 + + >>> # Estimate pH given state variable values. + >>> Ka = asm.rate_function.params['Ka'] + >>> unit_conversion = asm.rate_function.params['mass2mol'] + >>> h_ion = asm.solve_pH(state_arr, Ka, unit_conversion) + >>> pH = -np.log10(h_ion) + >>> print(f'{pH:.2f}') + 8.40 References ---------- From 7f566bb120acfa26353304cf43552485f65d2c29 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 22 Oct 2024 15:30:23 -0700 Subject: [PATCH 3/3] added doctest for `ADM1_p_extension` --- qsdsan/processes/_adm1_p_extension.py | 37 ++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/qsdsan/processes/_adm1_p_extension.py b/qsdsan/processes/_adm1_p_extension.py index 1c1a81cb..ab342969 100644 --- a/qsdsan/processes/_adm1_p_extension.py +++ b/qsdsan/processes/_adm1_p_extension.py @@ -239,7 +239,6 @@ def _rhos_adm1_p_extension(state_arr, params, h=None): rhos[9] *= Inh3 rhos[-3:] = kLa * (biogas_S - KH * biogas_p) - # print(rhos) return rhos def dydt_Sh2_AD(S_h2, state_arr, h, params, f_stoichio, V_liq, S_h2_in): @@ -355,6 +354,42 @@ class ADM1_p_extension(ADM1): >>> adm1_p.show() ADM1_p_extension([hydrolysis_carbs, hydrolysis_proteins, hydrolysis_lipids, uptake_sugars, uptake_amino_acids, uptake_LCFA, uptake_valerate, uptake_butyrate, uptake_propionate, uptake_acetate, uptake_h2, decay_Xsu, decay_Xaa, decay_Xfa, decay_Xc4, decay_Xpro, decay_Xac, decay_Xh2, storage_Sva_in_XPHA, storage_Sbu_in_XPHA, storage_Spro_in_XPHA, storage_Sac_in_XPHA, lysis_XPAO, lysis_XPP, lysis_XPHA, h2_transfer, ch4_transfer, IC_transfer]) + >>> import numpy as np + >>> state_arr = np.ones(cmps.size + len(adm1_p._biogas_IDs) + 2) # liquid-phase concentrations, gas-phase concentrations, liquid flowrate, and temperature + >>> state_arr[-1] = 273.15+35 # Temperature + >>> rhos = adm1_p.rate_function(state_arr) # reaction rate for each process + >>> for i,j in zip(adm1_p.IDs, rhos): + ... print(f'{i}{(40-len(i))*" "}{j:.3g}') + hydrolysis_carbs 10 + hydrolysis_proteins 10 + hydrolysis_lipids 10 + uptake_sugars 20 + uptake_amino_acids 38.4 + uptake_LCFA 2.14e-05 + uptake_valerate 8.32e-05 + uptake_butyrate 8.32e-05 + uptake_propionate 4.13e-05 + uptake_acetate 1.93 + uptake_h2 34.9 + decay_Xsu 0.02 + decay_Xaa 0.02 + decay_Xfa 0.02 + decay_Xc4 0.02 + decay_Xpro 0.02 + decay_Xac 0.02 + decay_Xh2 0.02 + storage_Sva_in_XPHA 0.747 + storage_Sbu_in_XPHA 0.747 + storage_Spro_in_XPHA 0.747 + storage_Sac_in_XPHA 0.747 + lysis_XPAO 0.2 + lysis_XPP 0.2 + lysis_XPHA 0.2 + h2_transfer 139 + ch4_transfer -181 + IC_transfer -1.66e+03 + + References ---------- [1] Batstone, D. J.; Keller, J.; Angelidaki, I.; Kalyuzhnyi, S. V;