def test_get_odesys__late_binding(): def _gibbs(args, T, R, backend, **kwargs): H, S = args return backend.exp(-(H - T*S)/(R*T)) def _eyring(args, T, R, k_B, h, backend, **kwargs): H, S = args return k_B/h*T*backend.exp(-(H - T*S)/(R*T)) gibbs_pk = ('temperature', 'molar_gas_constant') eyring_pk = gibbs_pk + ('Boltzmann_constant', 'Planck_constant') GibbsEC = MassActionEq.from_callback(_gibbs, argument_names=('H', 'S'), parameter_keys=gibbs_pk) EyringMA = MassAction.from_callback(_eyring, argument_names=('H', 'S'), parameter_keys=eyring_pk) uk_equil = ('He_assoc', 'Se_assoc') beta = GibbsEC(unique_keys=uk_equil) # equilibrium parameters uk_kinet = ('Ha_assoc', 'Sa_assoc') bimol_barrier = EyringMA(unique_keys=uk_kinet) # activation parameters eq = Equilibrium({'Fe+3', 'SCN-'}, {'FeSCN+2'}, beta) rsys = ReactionSystem(eq.as_reactions(kf=bimol_barrier)) odesys, extra = get_odesys(rsys, include_params=False) pk, unique, p_units = map(extra.get, 'param_keys unique p_units'.split()) assert sorted(unique) == sorted(uk_equil + uk_kinet) assert sorted(pk) == sorted(eyring_pk)
def test_get_odesys__Equilibrium_as_reactions(): from chempy import Equilibrium, ReactionSystem eq = Equilibrium({'Fe+3', 'SCN-'}, {'FeSCN+2'}, 10**2) substances = 'Fe+3 SCN- FeSCN+2'.split() rsys = ReactionSystem(eq.as_reactions(kf=3.0), substances) odesys, extra = get_odesys(rsys) init_conc = {'Fe+3': 1.0, 'SCN-': .3, 'FeSCN+2': 0} tout, Cout, info = odesys.integrate(5, init_conc, integrator='cvode', atol=1e-11, rtol=1e-12) cmplx_ref = binary_rev(tout, 3, 3.0/100, init_conc['FeSCN+2'], init_conc['Fe+3'], init_conc['SCN-']) assert np.allclose(Cout[:, 2], cmplx_ref)
def test_get_odesys__Equilibrium_as_reactions(): from chempy import Equilibrium, ReactionSystem eq = Equilibrium({"Fe+3", "SCN-"}, {"FeSCN+2"}, 10 ** 2) substances = "Fe+3 SCN- FeSCN+2".split() rsys = ReactionSystem(eq.as_reactions(kf=3.0), substances) odesys, extra = get_odesys(rsys) init_conc = {"Fe+3": 1.0, "SCN-": 0.3, "FeSCN+2": 0} tout, Cout, info = odesys.integrate( 5, init_conc, integrator="cvode", atol=1e-11, rtol=1e-12 ) cmplx_ref = binary_rev( tout, 3, 3.0 / 100, init_conc["FeSCN+2"], init_conc["Fe+3"], init_conc["SCN-"] ) assert np.allclose(Cout[:, 2], cmplx_ref)
def melange(self): '''Calcule Xmax, affiche le(s) réactif(s) limitant(s)''' #Génère la liste de tuples (n/coeff,occurence) triée par ordre croissant de n/coeff local_list=[(k, len(list(v))) for k, v in itertools.groupby(sorted(self.etat_ini.values()))] #initialisation RL='Réactif(s) limitant(s):' #Pour tout les éléments dans la liste contenant les formules (k) si le réactif est limitant for elt in [k for k,v in self.etat_ini.items() if v==local_list[0][0]]: #Incrémente la chaîne en ajoutant une virgule RL+=str(elt)+',' #Retient tout sauf la dernière virgule RL=RL[:-1] #Création d'un label avec un texte "Résultats" & incrémentation de la variable ligne Label(self.top.frame3,text="Résultats:").grid(row=self.ligne, sticky=W) self.ligne+=1 #Création d'un label avec un texte "RL" en rouge & incrémentation de la variable ligne Label(self.top.frame3,text=RL, fg="red").grid(row=self.ligne, sticky=W) self.ligne+=1 #Affectation du nb de réactifs limitant txt="Réactif(s) limitant(s): "+str(local_list[0][1])+"." #Création d'un label avec le texte 'txt' en rouge & incrémentation de la variable ligne Label(self.top.frame3,text=txt).grid(row=self.ligne, sticky=W) self.ligne+=1 #Affectation de Xmax txt="Avancement maximal: Xmax="+"{:5.2E}".format(local_list[0][0])+ " mol" #Création d'un label avec le texte 'txt' & incrémentation de la variable ligne Label(self.top.frame3,text=txt).grid(row=self.ligne, sticky=W) self.ligne+=1 #Création d'un label avec l'équation-bilan & incrémentation de la variable ligne Label(self.top.frame3,text=Equilibrium(self.Liste_reac, self.Liste_prod)).grid(row=self.ligne, sticky=W) self.ligne+=1 #retourne Xmax return local_list[0][0]
def test_equilibrate_pH_non_trivial(init_conc, env_T): equilibria = { 'water': Equilibrium.from_string(f"H2O = H+ + OH-; {K_H2O / M / M}"), 'ammonia': Equilibrium.from_string( f"NH3 + H2O = NH4+ + OH-; {EQUILIBRIUM_CONST['K_NH3'].at(env_T) / M}" ), 'sulfonic_first': Equilibrium.from_string( f"H2SO3(aq) = H+ + HSO3-; {EQUILIBRIUM_CONST['K_SO2'].at(env_T) / M}" ), 'sulfonic_second': Equilibrium.from_string( f"HSO3- = H+ + SO3-2; {EQUILIBRIUM_CONST['K_HSO3'].at(env_T) / M}" ), 'carbonic_first': Equilibrium.from_string( f"H2CO3(aq) = H+ + HCO3-; {EQUILIBRIUM_CONST['K_CO2'].at(env_T) / M}" ), 'carbonic_second': Equilibrium.from_string( f"HCO3- = H+ + CO3-2; {EQUILIBRIUM_CONST['K_HCO3'].at(env_T) / M}" ) } substances = [ Species.from_formula(f) for f in 'H2O OH- H+ NH3 NH4+ H2CO3(aq) HCO3- CO3-2 H2SO3(aq) HSO3- SO3-2'. split() ] eqsys = EqSystem(equilibria.values(), substances) x, sol, sane = eqsys.root(init_conc) assert sol['success'] and sane H_idx = 2 assert substances[H_idx].name == 'H+' expected_pH = -np.log10(x[H_idx]) eqs = {} for key in EQUILIBRIUM_CONST.keys(): eqs[key] = np.full(1, EQUILIBRIUM_CONST[key].at(env_T)) actual_pH = np.empty(1) formulae = Formulae() ChemistryMethods.equilibrate_H_body( within_tolerance=formulae.trivia.within_tolerance, pH2H=formulae.trivia.pH2H, H2pH=formulae.trivia.H2pH, N_mIII=np.full(1, init_conc['NH3'] * 1e3), N_V=np.full(1, init_conc['HNO3(aq)'] * 1e3), C_IV=np.full(1, init_conc['H2CO3(aq)'] * 1e3), S_IV=np.full(1, init_conc['H2SO3(aq)'] * 1e3), S_VI=np.full(1, init_conc['HSO4-'] * 1e3), K_HNO3=eqs['K_HNO3'].data, K_HCO3=eqs['K_HCO3'].data, K_HSO3=eqs['K_HSO3'].data, K_HSO4=eqs['K_HSO4'].data, K_CO2=eqs['K_CO2'].data, K_NH3=eqs['K_NH3'].data, K_SO2=eqs['K_SO2'].data, cell_id=np.zeros(1, dtype=int), # output do_chemistry_flag=np.empty(1), pH=actual_pH, # params H_min=formulae.trivia.pH2H(aqueous_chemistry.default_pH_max), H_max=formulae.trivia.pH2H(aqueous_chemistry.default_pH_min), ionic_strength_threshold=aqueous_chemistry. default_ionic_strength_threshold, rtol=aqueous_chemistry.default_pH_rtol) np.testing.assert_allclose(actual_pH[0], expected_pH, rtol=1e-5)
from chempy import Equilibrium from sympy import symbols def balance (first, next, some1, some2) K1, K2, Kw = symbols('K1 K2 Kw') e1 = Equilibrium(first, next, K1) e2 = Equilibrium(some1, some2, K2) coeff = Equilibrium.eliminate([e1, e2], 'e-') redox = e1*coeff[0] + e2*coeff[1] print(redox) autoprot = Equilibrium({'H2O': 1}, {'H+': 1, 'OH-': 1}, Kw) n = redox.cancel(autoprot) redox2 = redox + n*autoprot print(redox2)
# the Free Software Foundation; either version 3, or (at your option) # any later version. # This file is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with GNU Emacs; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA, #!/usr/bin/python # -*- coding: utf-8 -*- from chempy import Equilibrium from sympy import symbols K1, K2, Kw = symbols('K1 K2 Kw') e1 = Equilibrium({'MnO4-': 1, 'H+': 8, 'e-': 5}, {'Mn+2': 1, 'H2O': 4}, K1) e2 = Equilibrium({'O2': 1, 'H2O': 2, 'e-': 4}, {'OH-': 4}, K2) coeff = Equilibrium.eliminate([e1, e2], 'e-') coeff redox = e1 * coeff[0] + e2 * coeff[1] print(redox) autoprot = Equilibrium({'H2O': 1}, {'H+': 1, 'OH-': 1}, Kw) n = redox.cancel(autoprot) print(n) redox2 = redox + n * autoprot print(redox2)