def test_molar_volume(self):
     # molar volume of water at [temperature(C), pressure(applied_bar), specific volume] Millero TABLE IV
     param = np.array([[5, 0, 1.000036], [30, 0, 1.004369],
                       [75, 0, 1.025805], [35, 100, 1.001597],
                       [55, 300, 1.001642]])
     # converting param to [temperature(K), pressure(atm), molar volume]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     # 1 atm = 1 applied_atm + 1, according to Millero
     param[:, 1] = (param[:, 1] / un.atm_2_bar(1)) + 1
     param[:,
           2] = (param[:, 2] /
                 1e6) * fm.WaterPropertiesFineMillero(300).MolecularWeight
     # testing molar volume up to a precision of 10^-11
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(wfm.molar_volume(), param[:, 2], 0, 1e-11)
     self.assertTrue(test_vals)
Exemple #2
0
    def test_free_energy_dp_excess(self):
        # parameters in [temperature (K), concentration of ions (M), ion size (A), x_pair, free energy excess]
        param = np.array([[273.15, 1.0, 8, 0.4, -0.0036],
                          [298.15, 1.0, 8, 0.4, -0.0038],
                          [300.00, 1.0, 9, 0.6, -0.0064],
                          [298.15, 2.0, 7, 0.4, -0.0074],
                          [300.00, 4.0, 5, 0.5, -0.0086],
                          [300.00, 3.5, 5, 0.7, -0.0071]])

        obj_water_bp = wbp.WaterPropertiesFineMillero(param[:, 0])
        obj_water_aw = waw.WaterPropertiesFineMillero(param[:, 0])

        obj_bj = bj.Bjerrum(obj_water_bp)
        obj_bj_2 = bj.Bjerrum(obj_water_aw)

        obj_dp = dp.Dipole(obj_bj)
        obj_dp_2 = dp.Dipole(obj_bj_2)

        # testing params up to a precision of 10^-4
        test_1 = np.allclose(
            obj_dp.free_energy_dp_excess(param[:, 1], param[:, 2],
                                         param[:, 3]), param[:, 4], 0, 1e-4)
        test_2 = np.allclose(
            obj_dp_2.free_energy_dp_excess(param[:, 1], param[:, 2],
                                           param[:, 3]), param[:, 4], 0, 1e-4)
        self.assertTrue(test_1)
        self.assertTrue(test_2)
Exemple #3
0
 def test_molarity_conversion(self):
     # 1 molar NaCl = 1.021411855 molar NaCl at 25C
     c = 1
     water = wfm.WaterPropertiesFineMillero(298.15)
     salt = nacl.NaClPropertiesRogersPitzer(298.15)
     convert = con.molarity_2_molality(c, water.molar_volume(), salt.molar_vol(1.021411855), water.MolecularWeight)
     # test precision up to 10^-6
     test = np.allclose(convert, 1.021411855, 0, 1e-2)
     self.assertTrue(test)
Exemple #4
0
    def test_pot_chem_dp_excess(self):
        # parameters in [temperature (K), concentration of ions (M), ion size (A), x_pair, [mu_p, mu_p, mu_0]]
        param = np.array([[
            273.15, 1.0, 8, 0.4, -1.39225705e-05, -1.39225705e-05,
            -5.82590279e-02
        ],
                          [
                              298.15, 1.0, 8, 0.4, -1.47196945e-05,
                              -1.47196945e-05, -6.08761754e-02
                          ],
                          [
                              300.00, 1.0, 9, 0.6, -2.21908764e-05,
                              -2.21908764e-05, -4.87829304e-02
                          ],
                          [
                              298.15, 2.0, 7, 0.4, -4.60404423e-05,
                              -4.60404423e-05, -8.97120601e-02
                          ],
                          [
                              300.00, 4.0, 5, 0.5, -3.07170181e-05,
                              -3.07170181e-05, -1.14731930e-01
                          ],
                          [
                              300.00, 3.5, 5, 0.7, -9.91702493e-06,
                              -9.91702493e-06, -7.65120554e-02
                          ]])

        # testing params [mu_p, mu_p, mu_0]
        for i in range(len(param)):
            for j in range(3):
                obj_water_bp = wbp.WaterPropertiesFineMillero(param[i, 0])
                obj_water_aw = waw.WaterPropertiesFineMillero(param[i, 0])

                obj_bj = bj.Bjerrum(obj_water_bp)
                obj_bj_2 = bj.Bjerrum(obj_water_aw)

                obj_dp = dp.Dipole(obj_bj)
                obj_dp_2 = dp.Dipole(obj_bj_2)

                dp_method = obj_dp.pot_chem_dp_excess(param[i, 1], param[i, 2],
                                                      param[i, 3])
                dp_method_2 = obj_dp_2.pot_chem_dp_excess(
                    param[i, 1], param[i, 2], param[i, 3])

                # testing params [mu_p, mu_p] up to a precision of 10^-7
                test_1 = np.allclose(dp_method[j], param[i, 4 + j], 0, 1e-7)
                test_2 = np.allclose(dp_method_2[j], param[i, 4 + j], 0, 1e-7)

                # testing params [mu_0] up to a precision of 10^-4
                if j == 2:
                    test_1 = np.allclose(dp_method[j], param[i, 4 + j], 0,
                                         1e-4)
                    test_2 = np.allclose(dp_method_2[j], param[i, 4 + j], 0,
                                         1e-4)

                self.assertTrue(test_1)
                self.assertTrue(test_2)
 def test_a_v(self):
     # apparent molal volume [temperature(C), Pressure(bar), molal vol (cc/mol)] Bradley & Pitzer TABLE IV
     param = np.array([[10, 100, 1.61], [60, 100, 2.55], [120, 100, 4.91],
                       [70, 400, 2.59], [25, 600, 1.66]])
     # converting param to [temperature(K), pressure(atm), molal vol (cc/mol)]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     param[:, 1] = param[:, 1] / un.atm_2_bar(1)
     # testing apparent molal volume up to a precision of 10^-2
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(wfm.a_v(), param[:, 2], 0, 1e-2)
     self.assertTrue(test_vals)
Exemple #6
0
    def molar_vol(self, m):
        """
            Molar volume of electrolyte solution according to Pitzer :cite:`Pitzer1973a`

            .. math::
                :label: molar_vol

                \\upsilon_{\\phi}(m)=\\upsilon^{\\infty}_1+\\nu|z_{+}z_{-}|A_v h(I) \\cr +2RT(\\nu_{+}\\nu_{-})m\\left[
                \\frac{\\partial \\beta^{(0)}_{\\pm}}{\\partial P}+2\\frac{\\partial \\beta^{(1)}_{\\pm}}{\\partial P}
                g_{p1}(x)+2\\frac{\\partial \\beta^{(2)}_{\\pm}}{\\partial P}g_{p1}(x)\\right] \\cr
                +2RT(\\nu_{+}\\nu_{-})^{\\frac{3}{2}}m^{2}\\left[\\frac{\\partial C^{(0)}_{\\pm}}{\\partial P}+2\\frac{
                \\partial C^{(1)}_{\\pm}}{\\partial P}g_{p1}(x) + 2\\frac{\\partial C^{(2)}_{\\pm}}{\\partial P}
                g_{p1}(x)\\right] \\cr +2RT(\\nu_{+}\\nu_{-})^2 m^{3}\\left[\\frac{\\partial D^{(0)}_{\\pm}}
                {\\partial P} + 2\\frac{\\partial D^{(1)}_{\\pm}}{\\partial P}g_{p1}(x)) + 2\\frac{\\partial
                D^{(2)}_{\\pm}}{\\partial P}g_{p1}(x)\\right]

            functions are defined in Eq. :eq:`wang_function_1`

            :return: Molar volume of electrolyte solution in SI (float)
            """
        # the factor 10 is the conversion from J to bar cm^3
        ct = 10 * un.r_gas() * self.tk

        # stoichiometric_coefficients
        nu, nu_prod, z_prod, nz_prod_plus = self.mat

        # ionic strength
        i_str = self.ionic_strength(m)

        # Pitzer parameters pressure derivative and Vp
        vp, beta0_der_p, beta1_der_p, beta2_der_p, C0_der_p, C1_der_p, C2_der_p, D0_der_p, D1_der_p, D2_der_p = self.params_der_p

        BV = (beta0_der_p +
              2 * beta1_der_p * self.g_fun_phi(self.alpha_b1, i_str**0.5) +
              2 * beta2_der_p * self.g_fun_phi(self.alpha_b1, i_str**0.5))
        CV = (C0_der_p + 2 * C1_der_p * self.g_fun_phi(self.alpha_c1, i_str) +
              2 * C2_der_p * self.g_fun_phi(self.alpha_c2, i_str))
        DV = (D0_der_p +
              2 * D1_der_p * self.g_fun_phi(self.alpha_d1, i_str**1.5) +
              2 * D2_der_p * self.g_fun_phi(self.alpha_d2, i_str**1.5))

        val_1 = vp + nu * z_prod * wp.WaterPropertiesFineMillero(
            self.tk, self.pa).a_v() * self.h_fun(i_str)
        val_2 = 2 * nu_prod * ct * m * BV
        val_3 = 2 * nu_prod**1.5 * ct * m**2 * CV
        val_4 = 2 * nu_prod**2 * ct * m**3 * DV

        # molar volume in cm^3/mol
        val = val_1 + val_2 + val_3 + val_4

        # return in m^3/mol
        molar_vol = 1e-6 * val

        return molar_vol
 def test_a_phi(self):
     # osmotic coefficient of water [temperature(C), Pressure(bar), osmotic coefficient] Bradley & Pitzer TABLE II
     param = np.array([[10, 100, 3.80e-1], [60, 100, 4.17e-1],
                       [120, 100, 4.82e-1], [70, 400, 4.19e-1],
                       [25, 600, 3.81e-1]])
     # converting param to [temperature(K), pressure(atm), osmotic coefficient]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     param[:, 1] = param[:, 1] / un.atm_2_bar(1)
     # testing osmotic coefficient up to a precision of 10^-3
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(wfm.a_phi(), param[:, 2], 0, 1e-3)
     self.assertTrue(test_vals)
 def test_dielectric_constant(self):
     # dielectric constant of water at [temperature(K), pressure(MPa), dielectric constant]
     param = np.array([[338.15, 0.1, 65.20777], [318.15, 0.1, 71.50373],
                       [353.15, 0.1, 60.84250], [273.15, 1, 87.89296],
                       [278.15, 60, 88.17593]])
     # converting param to [temperature(K), pressure(atm), dielectric constant]
     param[:, 1] = param[:, 1] * 1e6 / un.atm_2_pascal(1)
     # testing dielectric constant up to a precision of 10^-5
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(wfm.dielectric_constant(), param[:, 2], 0,
                             1e-5)
     self.assertTrue(test_vals)
Exemple #9
0
    def molar_vol_infinite_dilution(self):
        """
            Partial molal volume of solute at infinite dilution according to Pitzer :cite:`Pitzer1973a`

            .. math::
                :label: mol_infty_dilution

                \\upsilon_1^{\\infty}=\\frac{\\upsilon(m_r)}{m_r}-Y \\upsilon_0^{\\infty}-\\nu|z_{+}z_{-}|A_v h(I_r)
                -2\\nu_+\\nu_{-} RT\\left[ m_r B^{\\nu}_{\\pm}+\\nu_{+}z_{+}m^2_rC^{\\nu}_{\\pm}\\right]

            :return: Partial molal volume of solute at infinite dilution in SI (float)
            """
        # the factor 10 is the conversion from J to bar cm^3
        ct = 10 * un.r_gas() * self.tk

        # molar volume water in cm^3/mol
        vol_water = 1e6 * wp.WaterPropertiesFineMillero(
            self.tk, self.pa).molar_volume()

        # stoichiometric_coefficients
        nu, nu_prod, z_prod, nz_prod_plus = self.mat
        m_r = self.p_ref[1]
        y_r = self.p_ref[2]

        vp, beta0_der_p, beta1_der_p, beta2_der_p, C0_der_p, C1_der_p, C2_der_p, D0_der_p, D1_der_p, D2_der_p = self.params_der_p

        i_str = self.ionic_strength(m_r)

        mv_i_0 = vp / m_r - y_r * vol_water
        mv_i_1 = -nu * z_prod * wp.WaterPropertiesFineMillero(
            self.tk, self.pa).a_v() * self.h_fun(i_str)
        mv_i_2 = -2 * nu_prod * ct * (m_r * beta0_der_p +
                                      nz_prod_plus * m_r**2 * C0_der_p)
        # this is in cm^3/mol
        mv_i = mv_i_0 + mv_i_1 + mv_i_2

        # return in SI m^3
        molar_vol_infinite_dilution = 1e-6 * mv_i

        return molar_vol_infinite_dilution
 def test_compressibility(self):
     # compressibility of water at [temperature(C), pressure(applied_bar), compressibility (10^6 bar-1)] Millero TABLE V
     param = np.array([[5, 0, 49.175], [30, 0, 44.771], [75, 0, 45.622],
                       [35, 100, 43.305], [55, 300, 40.911]])
     # converting param to [temperature(K), pressure(atm), compressibility (atm-1)]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     # 1 atm = 1 applied_atm + 1, according to Millero
     param[:, 1] = (param[:, 1] / un.atm_2_bar(1)) + 1
     param[:, 2] = (param[:, 2] / 1e6) * un.atm_2_bar(1)
     # testing compressibility up to a precision of 10^-9
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(wfm.compressibility(), param[:, 2], 0, 1e-9)
     self.assertTrue(test_vals)
 def test_density(self):
     # density of water at [temperature(C), pressure(applied_bar), specific volume] Millero TABLEIV
     param = np.array([[5, 0, 1.000036], [30, 0, 1.004369],
                       [75, 0, 1.025805], [30, 100, 0.999939],
                       [55, 300, 1.001642]])
     # converting param to [temperature(K), pressure(atm), specific volume]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     # 1 atm = 1 applied_atm + 1, according to Millero
     param[:, 1] = (param[:, 1] / un.atm_2_bar(1)) + 1
     # testing density up to a precision of 10^-6
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(1e3 / wfm.density(), param[:, 2], 0, 1e-6)
     self.assertTrue(test_vals)
 def test_a_h(self):
     # enthalpy coefficient [temperature(C), Pressure(bar), enthalpy coeff (AH / RT)] Bradley & Pitzer TABLE III
     param = np.array([[10, 100, 0.641], [60, 100, 1.180], [120, 100, 2.05],
                       [70, 400, 1.24], [25, 600, 0.736]])
     # converting param to [temperature(K), pressure(atm), enthalpy coeff (AH / RT)]
     param[:, 0] = un.celsius_2_kelvin(param[:, 0])
     param[:, 1] = param[:, 1] / un.atm_2_bar(1)
     # testing enthalpy coeff up to a precision of 10^-2
     wfm = fm.WaterPropertiesFineMillero(param[:, 0], param[:, 1])
     test_vals = np.allclose(
         ((2 / 3) * wfm.a_h()) / (un.r_gas() * param[:, 0]), param[:, 2], 0,
         1e-2)
     self.assertTrue(test_vals, (wfm.a_h()) / (un.r_gas() * param[:, 0]))
Exemple #13
0
    def density_sol(self, m):
        """
            Density of electrolyte solution according to Pitzer :cite:`Pitzer1973a`

            :return: Density of electrolyte solution in SI (float)
            """
        mw = wp.WaterPropertiesFineMillero(self.tk, self.pa).MolecularWeight
        # convert to cm^3/mol
        v_water = 1e6 * wp.WaterPropertiesFineMillero(self.tk,
                                                      self.pa).molar_volume()

        # convert to cm^3/mol
        v_salt = 1e6 * self.molar_vol(m)
        mw_salt = self.p_ref[0]

        # density in g/cm^3
        dens = mw * (1 + 1e-3 * m * mw_salt) / (v_water +
                                                1e-3 * m * mw * v_salt)

        # return density in kg/m3
        density_sol = 1e3 * dens

        return density_sol
Exemple #14
0
    def apparent_molal_enthalpy(self, m):
        """
            Apparent molal enthalpy according to Wang and Pitzer :cite:`Wang1998`

            .. math::

                L_{\\phi} = \\frac{\\nu|z_{+}z_{-}|A_{H}}{2b} \\ln(1+bI^{\\frac{1}{2}}) \\cr -2RT^{2}(\\nu_{+}
                \\nu_{-})m \\left[\\frac{\\partial \\beta^{(0)}_{\\pm}}{\\partial T}+2\\frac{\\partial
                \\beta^{(1)}_{\\pm}}{\\partial T}g_{p1}(x)+2\\frac{\\partial \\beta^{(2)}_{\\pm}}{\\partial T}
                g_{p1}(x)\\right] \\cr -2RT^{2}(\\nu_{+}\\nu_{-})^{\\frac{3}{2}}m^{2}\\left[\\frac{\\partial
                C^{(0)}_{\\pm}}{\\partial T}+2\\frac{\\partial C^{(1)}_{\\pm}}{\\partial T}g_{p1}(x)+2\\frac{\\partial
                C^{(2)}_{\\pm}}{\\partial T}g_{p1}(x)\\right] \\cr -2RT^{2}(\\nu_{+}\\nu_{-})^{2}m^{3}\\left[
                \\frac{\\partial D^{(0)}_{\\pm}}{\\partial T}+2\\frac{\\partial D^{(1)}_{\\pm}}{\\partial T}g_{p1}(x)
                +2\\frac{\\partial D^{(2)}_{\\pm}}{\\partial T}g_{p1}(x)\\right]

            functions are defined in Eq. :eq:`wang_function_1`

            :return: apparent molal enthalpy in SI (float)
            """
        # stoichiometric_coefficients
        nu, nu_prod, z_prod, nz_prod_plus = self.mat

        # ionic strength
        i_str = self.ionic_strength(m)

        # Pitzer Parameters temperature derivative
        beta0_der_t, beta1_der_t, beta2_der_t, C0_der_t, C1_der_t, C2_der_t, D0_der_t, D1_der_t, D2_der_t = self.params_der_t

        BL = (beta0_der_t +
              2 * beta1_der_t * self.g_fun_phi(self.alpha_b1, i_str**0.5) +
              2 * beta2_der_t * self.g_fun_phi(self.alpha_b1, i_str**0.5))
        CL = (C0_der_t + 2 * C1_der_t * self.g_fun_phi(self.alpha_c1, i_str) +
              2 * C2_der_t * self.g_fun_phi(self.alpha_c2, i_str))
        DL = (D0_der_t +
              2 * D1_der_t * self.g_fun_phi(self.alpha_d1, i_str**1.5) +
              2 * D2_der_t * self.g_fun_phi(self.alpha_d2, i_str**1.5))

        a_h = wp.WaterPropertiesFineMillero(self.tk, self.pa).a_h()

        val_1 = nu * z_prod * (
            a_h /
            (2 * self.b_param)) * np.log(1 + self.b_param * np.sqrt(i_str))
        val_2 = -2 * un.r_gas() * self.tk**2 * nu_prod * m * BL
        val_3 = -2 * un.r_gas() * self.tk**2 * nu_prod**1.5 * m**2 * CL
        val_4 = -2 * un.r_gas() * self.tk**2 * nu_prod**2 * m**3 * DL

        l_phi = val_1 + val_2 + val_3 + val_4

        return l_phi
Exemple #15
0
    def test_bjerrum_length(self):
        # parameters to test (water objects at  param (K) temperatures)
        param = np.array([273.15, 298.15, 300, 310, 320])
        obj_water_bp = wbp.WaterPropertiesFineMillero(param)
        obj_water_aw = waw.WaterPropertiesFineMillero(param)

        obj_bj = bj.Bjerrum(obj_water_bp)
        obj_bj_2 = bj.Bjerrum(obj_water_aw)

        # testing params up to a precision of 10^-2
        bj_length_param = np.array(
            [6.95955102, 7.15043775, 7.16686699, 7.26135158, 7.36525138])
        test_1 = np.allclose(obj_bj.bjerrum_length, bj_length_param, 0, 1e-2)
        test_2 = np.allclose(obj_bj_2.bjerrum_length, bj_length_param, 0, 1e-2)
        self.assertTrue(test_1)
        self.assertTrue(test_2)
Exemple #16
0
    def log_gamma(self, m):
        """
            Activity coefficient according to Wang & Pitzer :cite:`Wang1998`

            .. math::
                :label: pitzer_activity

                \\ln \\gamma_{\\pm} = -|z_{+}z_{-}|A_{\\gamma}f_{p2}(I) \\cr
                + \\frac{2(\\nu_{+}\\nu_{-})}{\\nu} m \\left[2\\beta^{(0)}_{\\pm} + 2\\beta^{(1)}_{\\pm}
                f_{p3}(\\alpha_{B1}, I) + 2\\beta^{(2)}_{\\pm}f_{p3}(\\alpha_{B2}, I)\\right]\\cr
                + \\frac{2(\\nu_{+}\\nu_{-})^{\\frac{3}{2}}}{\\nu} m^{2}\\left[3C^{(0)}_{\\pm} + 2C^{(1)}_{\\pm}
                f_{p4}(\\alpha_{C1}, I) + 2C^{(2)}_{\\pm}f_{p4}(\\alpha_{C2}, I)\\right] \\cr
                + \\frac{2(\\nu_{+}\\nu_{-})^{2}}{\\nu} m^{3}\\left[4D^{(0)}_{\\pm} + 2D^{(1)}_{\\pm}
                f_{p5}(\\alpha_{D1}, I) + 2D^{(2)}_{\\pm}f_{p5}(\\alpha_{D2}, I)\\right]

            functions are defined in Eq. :eq:`pitzer_function_2`, :eq:`pitzer_function_3`, :eq:`pitzer_function_4`, :eq:`pitzer_function_5`

            :return: activity coefficient (float)
            """
        # pressure is 1 atm
        press = 1

        # stoichiometric_coefficients
        nu, nu_prod, z_prod, nz_prod_plus = self.mat

        # ionic strength
        i_str = self.ionic_strength(m)

        # Pitzer Parameters
        beta0, beta1, beta2, C0, C1, C2, D0, D1, D2 = self.params

        BY = (2 * beta0 + 2 * beta1 * self.p_fun_gamma(self.alpha_b1, i_str) +
              2 * beta2 * self.p_fun_gamma(self.alpha_b2, i_str))
        CY = (3 * C0 + 2 * C1 * self.p_fun_gamma_2(self.alpha_c1, i_str) +
              2 * C2 * self.p_fun_gamma_2(self.alpha_c2, i_str))
        DY = (4 * D0 + 2 * D1 * self.p_fun_gamma_3(self.alpha_d1, i_str) +
              2 * D2 * self.p_fun_gamma_3(self.alpha_d2, i_str))

        val_1 = -z_prod * wp.WaterPropertiesFineMillero(
            self.tk, press).a_phi() * self.h_fun_gamma(i_str)
        val_2 = 2 * m * (nu_prod / nu) * BY
        val_3 = (2 * nu_prod**1.5 / nu) * m**2 * CY
        val_4 = (2 * nu_prod**2 / nu) * m**3 * DY

        log_gamma = val_1 + val_2 + val_3 + val_4

        return log_gamma
Exemple #17
0
    def test_temp_star(self):
        # parameters in [temperature (K), radius (A), reduced temperature]
        param = np.array([[273.15, 2, 0.28737486], [298.15, 2, 0.27970316],
                          [300, 2, 0.27906197], [298.15, 5, 0.69925789],
                          [300, 0.5, 0.06976549], [300, 1, 0.13953098]])
        obj_water_bp = wbp.WaterPropertiesFineMillero(param[:, 0])
        obj_water_aw = waw.WaterPropertiesFineMillero(param[:, 0])
        obj_bj = bj.Bjerrum(obj_water_bp)
        obj_bj_2 = bj.Bjerrum(obj_water_aw)

        # testing params up to a precision of 10^-3
        test_1 = np.allclose(obj_bj.temp_star(param[:, 1]), param[:, 2], 0,
                             1e-3)
        test_2 = np.allclose(obj_bj_2.temp_star(param[:, 1]), param[:, 2], 0,
                             1e-3)
        self.assertTrue(test_1)
        self.assertTrue(test_2)
Exemple #18
0
    def osmotic_coeff(self, m):
        """
            Osmotic coefficient according to Wang & Pitzer :cite:`Wang1998`

            .. math::

                \\phi = 1 - |z_{+}z_{-}|A_{\\phi}\\frac{I^{\\frac{1}{2}}}{\\left(1 + bI^{\\frac{1}{2}}\\right)}\\cr
                +\\frac{2\\left(\\nu_{+}\\nu_{-}\\right)}{\\nu}m\\left[\\beta_{\\pm}^{(0)}+\\beta_{\\pm}^{(1)}e^{
                -\\alpha_{B1}I^{\\frac{1}{2}}}+ \\beta_{\\pm}^{(2)}e^{-\\alpha_{B2}I^{\\frac{1}{2}}}\\right] \\cr
                +\\frac{2\\left(\\nu_{+}\\nu_{-}\\right)^{\\frac{3}{2}}}{\\nu}m^{2}\\left[2\\left[C_{\\pm}^{(0)}+
                C_{\\pm}^{(1)}e^{-\\alpha_{C1}I}+ C_{\\pm}^{(2)}e^{-\\alpha_{C2}I}\\right]\\right] \\cr
                +\\frac{2\\left(\\nu_{+}\\nu_{-}\\right)^{2}}{\\nu}m^{3}\\left[3\\left[D_{\\pm}^{(0)}+D_{\\pm}^{(1)}e^{
                -\\alpha_{D1}I^{\\frac{3}{2}}}+ D_{\\pm}^{(2)}e^{-\\alpha_{D2}I^{\\frac{3}{2}}}\\right]\\right] \\cr

            :return: osmotic coefficient in SI (float)
            """
        # pressure is 1 atm
        press = 1

        # stoichiometric_coefficients
        nu, nu_prod, z_prod, nz_prod_plus = self.mat

        # ionic strength
        i_str = self.ionic_strength(m)

        # Pitzer Parameters
        beta0, beta1, beta2, C0, C1, C2, D0, D1, D2 = self.params

        B = (beta0 + beta1 * np.exp(-self.alpha_b1 * i_str**0.5) +
             beta2 * np.exp(-self.alpha_b2 * i_str**0.5))
        C = (2 * (C0 + C1 * np.exp(-self.alpha_c1 * i_str) +
                  C2 * np.exp(-self.alpha_c2 * i_str)))
        D = (3 * (D0 + D1 * np.exp(-self.alpha_d1 * i_str**1.5) +
                  D2 * np.exp(-self.alpha_d2 * i_str**1.5)))

        val_1 = -z_prod * wp.WaterPropertiesFineMillero(
            self.tk, press).a_phi() * np.sqrt(i_str) / (
                1 + self.b_param * np.sqrt(i_str))
        val_2 = 2 * m * (nu_prod / nu) * B
        val_3 = (2 * nu_prod**1.5 / nu) * m**2 * C
        val_4 = (2 * nu_prod**2 / nu) * m**3 * D

        osmotic_coefficient = 1 + val_1 + val_2 + val_3 + val_4

        return osmotic_coefficient
Exemple #19
0
    def test_bjerrum_constant(self):
        # parameters in [temperature (K), radius (A), Bjerrum constant]
        param = np.array([[273.15, 2, 177.15962555], [298.15, 2, 199.08793975],
                          [300, 2, 201.07303174], [298.15, 5, 4.48179914],
                          [300, 1, 5697.97522674]])

        obj_water_bp = wbp.WaterPropertiesFineMillero(param[:, 0])
        obj_water_aw = waw.WaterPropertiesFineMillero(param[:, 0])
        obj_bj = bj.Bjerrum(obj_water_bp)
        obj_bj_2 = bj.Bjerrum(obj_water_aw)

        # testing params up to a precision of 10
        test_1 = np.allclose(obj_bj.bjerrum_constant(param[:, 1]), param[:, 2],
                             0, 1e1)
        test_2 = np.allclose(obj_bj_2.bjerrum_constant(param[:, 1]),
                             param[:, 2], 0, 1e1)
        self.assertTrue(test_1)
        self.assertTrue(test_2)
Exemple #20
0
    def test_bjerrum_constant_approx(self):
        # parameters in [temperature (K), radius (A), Bjerrum constant (approx)]
        param = np.array([[273.15, 2, 175.6241625002495],
                          [298.15, 2, 197.37695820415016],
                          [300, 2, 199.34627081662805],
                          [298.15, 5, 4.437998539403452],
                          [300, 1, 5670.345869397299]])

        # testing params up to a precision of 10^2
        for i in range(len(param)):
            obj_water_bp = wbp.WaterPropertiesFineMillero(param[i, 0])
            obj_water_aw = waw.WaterPropertiesFineMillero(param[i, 0])
            obj_bj = bj.Bjerrum(obj_water_bp).bjerrum_constant_approx(param[i,
                                                                            1])
            obj_bj_2 = bj.Bjerrum(obj_water_aw).bjerrum_constant_approx(
                param[i, 1])
            test_1 = np.allclose(obj_bj[0], param[i, 2], 0, 1e2)
            test_2 = np.allclose(obj_bj_2[0], param[i, 2], 0, 1e2)
            self.assertTrue(test_1)
            self.assertTrue(test_2)
Exemple #21
0
    def __init__(self, tk, pa=1):
        """
        constructor

        :param tk: temperature in kelvin
        :param pa: pressure in atmospheres
        :instantiate: temperature, pressure, stoichiometry coefficients, Pitzer Parameters

        """
        self.tk = tk
        self.pa = pa

        # Calculations nacl parameters and coefficients
        self.mat_stoich = np.array([[1, 1], [1, -1]])

        self.m_ref = 5.550825
        self.y_ref = 10
        self.m_weight = 58.4428
        self.p_ref = np.array([self.m_weight, self.m_ref, self.y_ref])

        # values for ion strength dependence and ion size constants in the extended Pitzer model
        self.alpha_b1 = 2.0
        self.alpha_b2 = 0
        self.alpha_c1 = 0
        self.alpha_c2 = 0
        self.alpha_d1 = 0
        self.alpha_d2 = 0
        self.b_param = 1.2
        self.ion_param = np.array([
            self.alpha_b1, self.alpha_b2, self.alpha_c1, self.alpha_c2,
            self.alpha_d1, self.alpha_d2, self.b_param
        ])

        self.cm = np.zeros(28)

        self.cm[0] = 1.0249125e3
        self.cm[1] = 2.7796679e-1
        self.cm[2] = -3.0203919e-4
        self.cm[3] = 1.4977178e-6
        self.cm[4] = -7.2002329e-2
        self.cm[5] = 3.1453130e-4
        self.cm[6] = -5.9795994e-7
        self.cm[7] = -6.6596010e-6
        self.cm[8] = 3.0407621e-8
        self.cm[9] = 5.3699517e-5
        self.cm[10] = 2.2020163e-3
        self.cm[11] = -2.6538013e-7
        self.cm[12] = 8.6255554e-10
        self.cm[13] = -2.6829310e-2
        self.cm[14] = -1.1173488e-7
        self.cm[15] = -2.6249802e-7
        self.cm[16] = 3.4926500e-10
        self.cm[17] = -8.3571924e-13
        # exponent in 18 (19 in reference) is barely visible, it is 5 (confirmed)
        self.cm[18] = 3.0669940e-5
        self.cm[19] = 1.9767979e-11
        self.cm[20] = -1.9144105e-10
        self.cm[21] = 3.1387857e-14
        self.cm[22] = -9.6461948e-9
        self.cm[23] = 2.2902837e-5
        self.cm[24] = -4.3314252e-4
        self.cm[25] = -9.0550901e-8
        self.cm[26] = 8.6926600e-11
        self.cm[27] = 5.1904777e-4

        self.qm = np.zeros(19)

        self.qm[0] = 0.0765
        self.qm[1] = -777.03
        self.qm[2] = -4.4706
        self.qm[3] = 0.008946
        self.qm[4] = -3.3158e-6
        self.qm[5] = 0.2664
        # this value is not provided
        self.qm[6] = 0
        # this value is not provided
        self.qm[7] = 0
        self.qm[8] = 6.1608e-5
        self.qm[9] = 1.0715e-6
        self.qm[10] = 0.00127
        self.qm[11] = 33.317
        self.qm[12] = 0.09421
        self.qm[13] = -4.655e-5
        # this value is not provided
        self.qm[14] = 0
        self.qm[15] = 41587.11
        self.qm[16] = -315.90
        self.qm[17] = 0.8514
        self.qm[18] = -8.3637e-4

        # Pitzer Parameters
        self.tc = 298.15

        self.beta0_1 = self.qm[0] + self.qm[1] * (
            1 / self.tk - 1 / self.tc) + self.qm[2] * np.log(self.tk / self.tc)
        self.beta0_2 = self.qm[3] * (self.tk - self.tc) + self.qm[4] * (
            self.tk**2 - self.tc**2)
        self.beta0 = self.beta0_1 + self.beta0_2

        self.beta1 = self.qm[5] + self.qm[8] * (
            self.tk - self.tc) + self.qm[9] * (self.tk**2 - self.tc**2)
        self.beta2 = 0

        self.c_phi_1 = self.qm[10] + self.qm[11] * (
            1 / self.tk - 1 / self.tc) + self.qm[12] * np.log(
                self.tk / self.tc)
        self.c_phi = self.c_phi_1 + self.qm[13] * (self.tk - self.tc)
        self.C0 = self.c_phi / 2
        self.C1 = 0
        self.C2 = 0
        self.D0 = 0
        self.D1 = 0
        self.D2 = 0
        self.params = np.array([
            self.beta0, self.beta1, self.beta2, self.C0, self.C1, self.C2,
            self.D0, self.D1, self.D2
        ])

        # Pitzer Parameters pressure derivative
        self.pr = un.atm_2_bar(self.pa)
        self.pr_atm = un.atm_2_bar(1)

        self.vp_0 = self.cm[0] + self.cm[1] * self.tk + self.cm[
            2] * self.tk**2 + self.cm[3] * self.tk**3
        self.vp_1 = (self.pr - self.pr_atm) * (
            self.cm[4] + self.cm[5] * self.tk + self.cm[6] * self.tk**2)
        self.vp_2 = (self.pr - self.pr_atm)**2 * (self.cm[7] +
                                                  self.cm[8] * self.tk)

        self.vp_sum = self.vp_0 + self.vp_1 + self.vp_2

        self.bp_0 = self.cm[9] + self.cm[10] / (self.tk - 227) + self.cm[
            11] * self.tk + self.cm[12] * self.tk**2 + self.cm[13] / (680 -
                                                                      self.tk)
        self.bp_1_1 = self.cm[14] + self.cm[15] / (
            self.tk - 227) + self.cm[16] * self.tk + self.cm[17] * self.tk**2
        self.bp_1 = (self.bp_1_1 + self.cm[18] /
                     (680 - self.tk)) * (self.pr - self.pr_atm)
        self.bp_2_1 = self.cm[19] + self.cm[20] / (
            self.tk - 227) + self.cm[21] * self.tk + self.cm[22] / (680 -
                                                                    self.tk)
        self.bp_2 = self.bp_2_1 * (self.pr - self.pr_atm)**2

        self.beta0_der_p = self.bp_0 + self.bp_1 + self.bp_2
        self.beta1_der_p = 0
        self.beta2_der_p = 0

        self.cq = self.cm[23] + self.cm[24] / (self.tk - 227) + self.cm[
            25] * self.tk + self.cm[26] * self.tk**2 + self.cm[27] / (680 -
                                                                      self.tk)
        self.cp = 0.5 * self.cq
        self.C0_der_p = self.cp
        self.C1_der_p = 0
        self.C2_der_p = 0

        self.D0_der_p = 0
        self.D1_der_p = 0
        self.D2_der_p = 0

        # calculates the molar volume at infinite dilution (vp)

        # the factor 10 is the conversion from J to bar cm^3
        self.ct = 10 * un.r_gas() * self.tk

        # molar volume water in cm^3/mol
        self.vol_water = 1e6 * bp.WaterPropertiesFineMillero(
            self.tk, self.pa).molar_volume()

        self.mv_i_0 = self.vp_sum / self.m_ref - self.y_ref * self.vol_water
        self.mv_i_1 = -2 * bp.WaterPropertiesFineMillero(self.tk, self.pa).a_v(
        ) * (0.5 * np.log(1 + self.b_param * np.sqrt(self.m_ref)) /
             self.b_param)
        self.mv_i_2 = -2 * self.ct * (self.m_ref * self.beta0_der_p +
                                      self.m_ref**2 * self.C0_der_p)
        # this is in cm^3/mol
        self.mv_i = self.mv_i_0 + self.mv_i_1 + self.mv_i_2

        # return in SI m^3
        self.molar_vol_infinite_dilution = 1e-6 * self.mv_i

        # infinite molar volume, convert to cm^3/mol
        self.vp = 1e6 * self.molar_vol_infinite_dilution

        self.params_der_p = np.array([
            self.vp, self.beta0_der_p, self.beta1_der_p, self.beta2_der_p,
            self.C0_der_p, self.C1_der_p, self.C2_der_p, self.D0_der_p,
            self.D1_der_p, self.D2_der_p
        ])

        # Pitzer Parameters temperature derivative
        self.beta0_der_t = 2 * self.qm[4] * self.tk + self.qm[
            2] / self.tk - self.qm[1] / (self.tk**2) + self.qm[3]
        self.beta1_der_t = 2 * self.qm[9] * self.tk + self.qm[8]
        self.beta2_der_t = 0

        self.c_phi_der_t = self.qm[12] / self.tk - self.qm[11] / (
            self.tk**2) + self.qm[13]
        self.C0_der_t = self.c_phi_der_t / 2
        self.C1_der_t = 0
        self.C2_der_t = 0

        self.D0_der_t = 0
        self.D1_der_t = 0
        self.D2_der_t = 0
        self.params_der_t = np.array([
            self.beta0_der_t, self.beta1_der_t, self.beta2_der_t,
            self.C0_der_t, self.C1_der_t, self.C2_der_t, self.D0_der_t,
            self.D1_der_t, self.D2_der_t
        ])

        super().__init__(tk, pa)
    def __init__(
                 self, param_poly, param_salt, temp, df_w, x_ini, p_ini, n_k, chi_p, chi_e,
                 param_s):

        """
        The constructor, with the following parameters

        :param param_poly: polymer parameters :math:`(\\phi_p, \\frac{\\upsilon_w} \
        {\\upsilon_p}, \\Delta F_p)`
        :param param_salt: salt parameters (see definition below)
        :param temp: temprature in Kelvin
        :param df_w: free energy change upon formation of hydrogen bond \
        in water (in :math:`k_BT` units)
        :param x_ini: fraction of polymer hydrogen bonds
        :param p_ini: fraction of water hydrogen bonds
        :param n_k: number of Kuhn lengths for the polymer
        :param chi_p: Flory Huggins parameter between water and polymer
        :param chi_e: Flory Huggins parameter between polymer and salt
        :param param_s: microscopic salt parameters \
        :math:`(h_+, h_-, d_+, d_-, m_+, m_-, \\nu_+, \\nu_-, log(gamma), osm)` \
        (number of water molecules \
        forming the hydration shell, diameter, maximum number of water \
        molecules that maybe bound to each ion,  the number of ions per salt,\
        activity coefficient, osmotic coefficient) 

        the parameter param_salt is given by
        :math:`(m_s, \\frac{\\upsilon_w}{\\upsilon_+}, \
        \\frac{\\upsilon_w}{\\upsilon_-}, \\Delta F_a, \\Delta F_b)`

        where :math:`m_s` is the concentration in mol/kg
        """
        #concentration of salt (NaCl)

        # concentration in mol/kg
        self.conc_l = param_salt[0]

        # concentration in mol/L

        self.T = temp

        #salt_nacl = nacl.NaClPropertiesRogersPitzer(self.T)
        #param_saltolvent = obj_water_bp.molar_volume()
        #m_solvent = obj_water_bp.MolecularWeight
        #param_saltolute = salt_nacl.molar_vol(self.conc_l)

        #self.conc = con.molality_2_molarity(self.conc_l,
                                            #param_saltolvent,
                                            #param_saltolute,
                                            #m_solvent)

        obj_water_bp = wbp.WaterPropertiesFineMillero(self.T)

        # molecular volumes
        self.u_p = param_poly[1]
        self.u_a = param_salt[1]
        self.u_b = param_salt[2]
        self.u_s = 1 / (1 / self.u_a + 1 /self.u_b)
        
        v_w = obj_water_bp.molar_volume() # molar volume of water 
        den = obj_water_bp.density() # density of water in SI unit from Ref[4]
        self.D_w = 1 / den / v_w #55.509 # mol/kg water

        # volume fractions
        self.phi_p = param_poly[0]

        self.param_salt = self.conc_l / self.u_s / self.D_w
        self.V_w = 1
        self.V_all = (self.param_salt + self.V_w) / (1 - self.phi_p)

        self.phi_s = self.param_salt / self.V_all

        self.phi_w = self.V_w / self.V_all

        # polymer and polymer interaction parameters
        self.n = n_k
        self.chi_p = chi_p
        self.chi_e = chi_e

        # hydration numbers
        self.h_a = param_s[0]
        self.h_b = param_s[1]
        self.m_a = param_s[4]
        self.m_b = param_s[5]

        # number of ions per salt
        self.nu_a = param_s[6]
        self.nu_b = param_s[7]
        self.nu = self.nu_a + self.nu_a

        # fraction of hydration bonds (in water:x, in polymer:y)
        self.x = x_ini
        self.p = p_ini


        # relative free energies of water association
        self.df_w = df_w
        self.df_p = param_poly[2]
        self.df_a = param_salt[3]
        self.df_b = param_salt[4]

        self.i_size_a = param_s[2]
        self.i_size_b = param_s[3]
        self.i_size = 0.5 * (self.i_size_a + self.i_size_b)


        # fraction of water in each ion size
        self.f_a = self.h_a * self.nu_a * self.u_s * self.phi_s / self.phi_w
        self.f_b = self.h_b * self.nu_b * self.u_s * self.phi_s / self.phi_w


        # Derivative of parameters
        self.df_adp = self.f_a / self.phi_w
        self.df_ads = self.f_a * (1 / self.phi_s + 1 / self.phi_w)#

        self.df_bdp = self.f_b / self.phi_w
        self.df_bds = self.f_b * (1 / self.phi_s + 1 / self.phi_w)

        self.dxdp = - self.x / self.phi_p
        self.dxds = 0

        self.dydp = self.p / self.phi_w
        self.dyds = self.p / self.phi_w
        
        
        self.gamma = param_s[8]
        self.osm = param_s[9]
        
        #S_para = nacl.NaClPropertiesRogersPitzer(tk=self.T, pa=1)
        #self.gamma = S_para.log_gamma(self.conc_l)
        #self.osm = S_para.osmotic_coeff(self.conc_l)

        self.A_a = self.nu_a * self.m_a * self.conc_l / self.D_w
        self.B_b = self.nu_b * self.m_b * self.conc_l / self.D_w
Exemple #23
0
    def test_potential_df(self):
        """
            checks if chemical potentials add up give free energy
        """
        num_pnts = 10
        phi_val = np.linspace(1e-1, 0.8, num_pnts)
        potential_w = np.zeros_like(phi_val)
        potential_p = np.zeros_like(phi_val)
        potential_s = np.zeros_like(phi_val)
        f_com = np.zeros_like(phi_val)
        F_com = np.zeros_like(phi_val)

        v_p = np.array([0.4, 1 / 3, 10 / 3])
        v_s = np.array([2, 1, 1, -100 / 3, -100 / 3])
        temp = 298
        df_w = 10 / 3
        x_ini = 0.1
        p_ini = 0.2
        n_k = 100
        chi_p = 0.5
        chi_s = 0.4

        #param_s = np.array([7, 7, 1, 1, 8, 8, 1, 1, 0., 0.])
        param_s = np.array([7., 7., 1., 1., 8., 8., 1., 1., 0., 0.])

        obj_water_bp = wbp.WaterPropertiesFineMillero(temp)
        v_w = obj_water_bp.molar_volume()  # molar volume of water
        den = obj_water_bp.density()  # density of water in SI unit from Ref[4]
        D_w = 1 / den / v_w  #55.509 # mol/kg water

        for ind, phi_p in enumerate(phi_val):
            S_para = nacl.NaClPropertiesRogersPitzer(tk=temp, pa=1)
            param_s[8] = S_para.log_gamma(v_s[0])
            param_s[9] = S_para.osmotic_coeff(v_s[0])

            polymer_sol = Pss.PolymerSolutionSalts(
                np.array([phi_p, 1 / 3, 10 / 3]), v_s, temp, df_w, x_ini,
                p_ini, n_k, chi_p, chi_s, param_s)
            potential_w[ind] = polymer_sol.chem_potential_w_full()
            potential_p[ind] = polymer_sol.chem_potential_p_full()
            potential_s[ind] = polymer_sol.chem_potential_s_full()
            f_com[ind] = polymer_sol.free()

            # concentration in mols/litre
            conc = v_s[0]

            # molecular volumes
            u_p = v_p[1]
            u_a = v_s[1]
            u_b = v_s[2]
            u_s = 1 / (1 / u_a + 1 / u_b)

            # volume fractions

            V_s = conc / u_s / D_w
            V_w = 1
            V_all = (V_s + V_w) / (1 - phi_p)

            phi_s = V_s / V_all
            phi_w = 1 - phi_s - phi_p

            F_com[ind] = (u_p / n_k * phi_p * potential_p[ind] +
                          u_s * phi_s * potential_s[ind] +
                          phi_w * potential_w[ind])

        self.assertTrue(np.allclose(F_com, f_com, rtol=0.0, atol=1e-14))