Пример #1
0
    def test7_dump_and_load(self):
        sol5a = self.pp.get_solution(5)
        self.pp.dump_solutions()
        pp2 = PhreeqPython(from_file='dump.gz')
        sol5b = pp2.get_solution(5)

        assert_almost_equal(sol5a.sc, sol5b.sc, 2)
        assert_equal(self.pp.ip.get_solution_list(),
                     pp2.ip.get_solution_list())
Пример #2
0
 def test10_use_non_default_database_directory(self):
     pp_test10 = PhreeqPython(database_directory=Path(__file__).parent)
     sol = pp_test10.add_solution_simple({'CaCl2': 1, 'Na2CO3': 1})
     # test solution number
     assert_equal(sol.number, 0)
     # test solution ph, sc, pe and temperature
     assert_equal(round(sol.pH, 2), 10.41)
     assert_equal(round(sol.sc, 2), 435.35)
     assert_equal(round(sol.pe, 2), 7.4)
     assert_equal(round(sol.temperature, 2), 25)
Пример #3
0
 def setUp(self):
     # self.net = Network(inputfile="tests/Case1.inp")
     self.net = Network(inputfile="Case1.inp")
     self.pp = PhreeqPython()
     self.vic = Victoria(self.net, self.pp)
     self.solutions = {}
     sol0 = self.pp.add_solution({'Ca': 0, 'units': 'mmol/l'})
     sol1 = self.pp.add_solution({'Ca': 1, 'units': 'mmol/l'})
     self.solutions[0] = sol0
     self.solutions[self.net.reservoirs['1'].uid] = sol1
Пример #4
0
def fixture_phreeqpython_solutions_excel():
    ''' Add the solutions of the excel file manually to test
        whether they are added correctly and to easily check
        whether all derived quantities like EC, and SI of calicite
        are correct by hgc methods '''
        #     {'temp': 10, 'Alkalinity': 0, 'O(0)': '11 ', 'C(-4)': '0 as CH4', 'pH': 4.5, 'Na': '9 charge', 'K': 0.4, 'Ca': 1, 'Mg': 1.1, 'Fe': 0.1, 'Mn': 0.02, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'},
        #     {'temp': 10, 'Alkalinity': 0, 'O(0)': '2 ', 'C(-4)': '0 as CH4', 'pH': 4.3, 'Na': '15 charge', 'K': 1.1, 'Ca': 2, 'Mg': 1.6, 'Fe': 0.29, 'Mn': 0.05, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10, 'Alkalinity': 0, 'O(0)': '1 ', 'C(-4)': '0 as CH4', 'pH': 4.4, 'Na': '19 charge', 'K': 1.8, 'Ca': 2, 'Mg': 3.0, 'Fe': 0.12, 'Mn': 0.06, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10, 'Alkalinity': 7, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 5.5, 'Na': '20 charge', 'K': 2.1, 'Ca': 3, 'Mg': 3.9, 'Fe': 2.33, 'Mn': 0.13, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10, 'Alkalinity': 13, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 5.7, 'Na': '21 charge', 'K': 2.8, 'Ca': 5, 'Mg': 5.4, 'Fe': 3.43, 'Mn': 0.03, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10, 'Alkalinity': 23, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 6.2, 'Na': '24 charge', 'K': 1.8, 'Ca': 13, 'Mg': 2.7, 'Fe': 0.7, 'Mn': 0.09, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10, 'Alkalinity': 92, 'O(0)': '0 ', 'C(-4)': '0.14 as CH4', 'pH': 7.4, 'Na': '29 charge', 'K': 1.9, 'Ca': 38, 'Mg': 2.8, 'Fe': 0.3, 'Mn': 0.13, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.1, 'Alkalinity': 146, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 7.7, 'Na': '29 charge', 'K': 2.0, 'Ca': 51, 'Mg': 3.4, 'Fe': 0.51, 'Mn': 0.13, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.2, 'Alkalinity': 151, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 7.7, 'Na': '15 charge', 'K': 1.4, 'Ca': 48, 'Mg': 3.1, 'Fe': 3.4, 'Mn': 0.18, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.5, 'Alkalinity': 156, 'O(0)': '0 ', 'C(-4)': '5 as CH4', 'pH': 7.6, 'Na': '15 charge', 'K': 1.2, 'Ca': 48, 'Mg': 2.5, 'Fe': 1.22, 'Mn': 0.13, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.7, 'Alkalinity': 169, 'O(0)': '0 ', 'C(-4)': '9.1 as CH4', 'pH': 8.1, 'Na': '24 charge', 'K': 9.5, 'Ca': 13, 'Mg': 21, 'Fe': 0.69, 'Mn': 0.04, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.8, 'Alkalinity': 398, 'O(0)': '0 ', 'C(-4)': '18.2 as CH4', 'pH': 8.5, 'Na': '155 charge', 'K': 11.5, 'Ca': 3, 'Mg': 3.1, 'Fe': 0.62, 'Mn': 0.04, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.7, 'Alkalinity': 525, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 8.2, 'Na': '190 charge', 'K': 16.8, 'Ca': 9, 'Mg': 9.5, 'Fe': 0.17, 'Mn': 0.12, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.8, 'Alkalinity': 801, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 7.7, 'Na': '445 charge', 'K': 58, 'Ca': 27, 'Mg': 19.9, 'Fe': 1.6, 'Mn': 0.12, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 10.8, 'Alkalinity': 903, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 8.5, 'Na': '910 charge', 'K': 134, 'Ca': 66, 'Mg': 71, 'Fe': 5.4, 'Mn': 0.3, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        #     {'temp': 11.0, 'Alkalinity': 2635, 'O(0)': '0 ', 'C(-4)': '0 as CH4', 'pH': 7.8, 'Na': '3380 charge', 'K': 95, 'Ca': 160, 'Mg': 390, 'Fe': 2.3, 'Mn': 0.03, 'Amm': '1.29', 'Si': '0.2 as SiO2', 'Cl': 16, 'S(6)': '7 as SO4', 'N(5)': '3.4 as NO3', 'F': 0.027, 'Mn(7)': '5.2 as KMnO4'}
        # ]
    pp = PhreeqPython()
    solution_dictionaries = [
        {'temp': 10,   'Alkalinity':    '0 as HCO3', 'O(0)': '11 ', 'C(-4)':    '0 as CH4', 'pH': 4.5, 'Na':    '9', 'K':   0.4, 'Ca':   1, 'Mg':   1.1, 'Fe': 0.10, 'Mn': 0.02, 'Amm':  1.29, 'Si':  '0.2 as SiO2', 'Cl':   16, 'S(6)':  '7 as SO4', 'N(5)':  '3.4 as NO3', 'F':  0.02700, 'Mn(7)':   '5.2 as KMnO4'},
        {'temp': 10,   'Alkalinity':    '0 as HCO3', 'O(0)':  '2 ', 'C(-4)':    '0 as CH4', 'pH': 4.3, 'Na':   '15', 'K':   1.1, 'Ca':   2, 'Mg':   1.6, 'Fe': 0.29, 'Mn': 0.05, 'Amm':  0.05, 'Si': '11.2 as SiO2', 'Cl':   19, 'S(6)': '16 as SO4', 'N(5)': '22.6 as NO3', 'F':  0.08000, 'Mn(7)':  '17.4 as KMnO4'},
        {'temp': 10,   'Alkalinity':    '0 as HCO3', 'O(0)':  '1 ', 'C(-4)':    '0 as CH4', 'pH': 4.4, 'Na':   '19', 'K':   1.8, 'Ca':   2, 'Mg':   3.0, 'Fe': 0.12, 'Mn': 0.03, 'Amm':  0.05, 'Si': '10.6 as SiO2', 'Cl':   31, 'S(6)': '18 as SO4', 'N(5)': '12.0 as NO3', 'F':  0.07000, 'Mn(7)':   '3.0 as KMnO4'},
        {'temp': 10,   'Alkalinity':    '7 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 5.5, 'Na':   '20', 'K':   2.1, 'Ca':   3, 'Mg':   3.9, 'Fe': 2.33, 'Mn': 0.06, 'Amm':  0.08, 'Si': '15.4 as SiO2', 'Cl':   34, 'S(6)': '19 as SO4', 'N(5)':  '0.1 as NO3', 'F':  0.12000, 'Mn(7)':   '5.3 as KMnO4'},
        {'temp': 10,   'Alkalinity':   '13 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 5.7, 'Na':   '21', 'K':   2.8, 'Ca':   5, 'Mg':   5.4, 'Fe': 3.43, 'Mn': 0.13, 'Amm':  0.19, 'Si': '18.6 as SiO2', 'Cl':   41, 'S(6)': '20 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00501, 'Mn(7)':   '7.3 as KMnO4'},
        {'temp': 10,   'Alkalinity':   '23 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 6.2, 'Na':   '24', 'K':   1.8, 'Ca':  13, 'Mg':   2.7, 'Fe': 0.70, 'Mn': 0.03, 'Amm':  0.23, 'Si': '15.1 as SiO2', 'Cl':   41, 'S(6)': '24 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00501, 'Mn(7)':  '13.9 as KMnO4'},
        {'temp': 10,   'Alkalinity':   '92 as HCO3', 'O(0)':  '0 ', 'C(-4)': '0.14 as CH4', 'pH': 7.4, 'Na':   '29', 'K':   1.9, 'Ca':  38, 'Mg':   2.8, 'Fe': 0.30, 'Mn': 0.09, 'Amm':  0.24, 'Si': '15.6 as SiO2', 'Cl':   44, 'S(6)': '36 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00501, 'Mn(7)':  '16.8 as KMnO4'},
        {'temp': 10,   'Alkalinity':  '121 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 7.6, 'Na':   '31', 'K':   2.0, 'Ca':  47, 'Mg':   3.3, 'Fe': 0.40, 'Mn': 0.13, 'Amm':  0.34, 'Si': '13.3 as SiO2', 'Cl':   50, 'S(6)': '35 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00501, 'Mn(7)':  '11.9 as KMnO4'},
        {'temp': 10.1, 'Alkalinity':  '146 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 7.7, 'Na':   '29', 'K':   2.0, 'Ca':  51, 'Mg':   3.4, 'Fe': 0.51, 'Mn': 0.13, 'Amm':  0.44, 'Si': '20.0 as SiO2', 'Cl':   45, 'S(6)': '22 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.01000, 'Mn(7)':   '0.0 as KMnO4'},
        {'temp': 10.2, 'Alkalinity':  '151 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 7.7, 'Na':   '15', 'K':   1.4, 'Ca':  48, 'Mg':   3.1, 'Fe': 3.40, 'Mn': 0.18, 'Amm':  0.68, 'Si': '16.0 as SiO2', 'Cl':   33, 'S(6)':  '0 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.01000, 'Mn(7)':   '0.0 as KMnO4'},
        {'temp': 10.5, 'Alkalinity':  '156 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '5 as CH4', 'pH': 7.6, 'Na':   '15', 'K':   1.2, 'Ca':  48, 'Mg':   2.5, 'Fe': 1.22, 'Mn': 0.13, 'Amm':  0.45, 'Si': '17.6 as SiO2', 'Cl':   29, 'S(6)':  '0 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.03000, 'Mn(7)':  '16.6 as KMnO4'},
        {'temp': 10.7, 'Alkalinity':  '169 as HCO3', 'O(0)':  '0 ', 'C(-4)':  '9.1 as CH4', 'pH': 8.1, 'Na':   '24', 'K':   9.5, 'Ca':  13, 'Mg':  21.0, 'Fe': 0.69, 'Mn': 0.04, 'Amm':  0.83, 'Si': '22.9 as SiO2', 'Cl':   33, 'S(6)':  '0 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.10000, 'Mn(7)':  '11.5 as KMnO4'},
        {'temp': 10.8, 'Alkalinity':  '398 as HCO3', 'O(0)':  '0 ', 'C(-4)': '18.2 as CH4', 'pH': 8.5, 'Na':  '155', 'K':  11.5, 'Ca':   3, 'Mg':   3.1, 'Fe': 0.62, 'Mn': 0.04, 'Amm':  6.19, 'Si': '17.4 as SiO2', 'Cl':   35, 'S(6)':  '0 as SO4', 'N(5)':  '0.0 as NO3', 'F':  1.50000, 'Mn(7)':  '84.9 as KMnO4'},
        {'temp': 10.7, 'Alkalinity':  '525 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 8.2, 'Na':  '190', 'K':  16.8, 'Ca':   9, 'Mg':   9.5, 'Fe': 0.17, 'Mn': 0.12, 'Amm':  8.26, 'Si': '45.0 as SiO2', 'Cl':   60, 'S(6)':  '0 as SO4', 'N(5)':  '0.0 as NO3', 'F':  1.10000, 'Mn(7)': '132.0 as KMnO4'},
        {'temp': 10.8, 'Alkalinity':  '801 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 7.7, 'Na':  '445', 'K':  58.0, 'Ca':  27, 'Mg':  19.9, 'Fe': 1.60, 'Mn': 0.12, 'Amm': 20.00, 'Si': '83.2 as SiO2', 'Cl':  390, 'S(6)':  '9 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00000, 'Mn(7)': '470.0 as KMnO4'},
        {'temp': 10.8, 'Alkalinity':  '903 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 8.5, 'Na':  '910', 'K': 134.0, 'Ca':  66, 'Mg':  71.0, 'Fe': 5.40, 'Mn': 0.30, 'Amm': 49.00, 'Si': '71.6 as SiO2', 'Cl': 1320, 'S(6)': '15 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00000, 'Mn(7)': '130.0 as KMnO4'},
        {'temp': 11.0, 'Alkalinity': '2635 as HCO3', 'O(0)':  '0 ', 'C(-4)':    '0 as CH4', 'pH': 7.8, 'Na': '3380', 'K':  95.0, 'Ca': 160, 'Mg': 390.0, 'Fe': 2.30, 'Mn': 0.03, 'Amm': 49.00, 'Si': '71.6 as SiO2', 'Cl': 5285, 'S(6)':  '4 as SO4', 'N(5)':  '0.0 as NO3', 'F':  0.00000, 'Mn(7)': '160.0 as KMnO4'},
    ]

    solutions = [None] * len(solution_dictionaries)
    for _i, sol_dict in enumerate(solution_dictionaries):
        sol_dict['units'] = 'mg/L'
        solutions[_i] = pp.add_solution(sol_dict)
    return pp, solutions
Пример #5
0
 def __init__(self, pandas_obj):
     self._obj = pandas_obj
     self._pp = PhreeqPython(
     )  # bind 1 phreeqpython instance to the dataframe
     self._valid_atoms = constants.atoms
     self._valid_ions = constants.ions
     self._valid_properties = constants.properties
Пример #6
0
def test_add_oxygen(consolidated_data, phreeqpython_solutions_excel):
    ''' Test oxygen is added and returned correctly to and from
    phreeqpython with or without. Test it in pure phreeqpython (because there
    it is not working as expected)
    - test that no O(0) added yields no O in solution
    - test that adding `O(0)` `as O2` yields wrong result
    - test that adding `O(0)` without `as O2` yields correct result
    - test that adding in the SamplesFrame O2 concentration yields correct results '''
    pp = PhreeqPython()
    test_solution_dict = {'units': 'mg/L',
                          'Cl': 8.0,
                          'Na': '2.0 charge',
                          'Alkalinity': '2.0 as HCO3',
                          'Ca': 1.0,
                          'pH': 7,
                          'temp': 11
                          }
    sol = pp.add_solution(test_solution_dict)
    assert sol.total_element('O') == 0.0

    test_solution_dict['O(0)'] = '3 as O2'
    sol1 = pp.add_solution(test_solution_dict)
    assert sol1.species['O2'] * 2 * mw('O') * 1000. != pytest.approx(3., 1.e-4)

    test_solution_dict['O(0)'] = 3
    sol1 = pp.add_solution(test_solution_dict)
    assert sol1.species['O2'] * 2 * mw('O') * 1000. == pytest.approx(3., 1.e-4)

    test_data = pd.DataFrame({'Cl': 8, 'Na': 2, 'alkalinity': 2,
                              'Ca': 1, 'O2': 3, 'ph': 7,
                              'temp': 11}, index=[0])
    test_data.hgc.make_valid()
    test_data.hgc.consolidate(
        use_so4=None, use_ph=None, use_ec=None, use_temp=None)
    sols = test_data.hgc.get_phreeqpython_solutions(inplace=False)
    assert sols[0].species['O2'] * 2 * \
        mw('O') * 1000. == pytest.approx(3., 1.e-4)
Пример #7
0
def test_phreeqpython_installed():
    '''test phreeqpython can be imported and used. test
       this by adding 1 simple solution to the PhreeqPython instance'''
    pp = PhreeqPython()
    pp.add_solution_simple({'CaCl2': 1.0, 'NaHCO3': 2.0})
Пример #8
0
class TestPhreeqPython(object):

    pp = PhreeqPython()

    def test1_basiscs(self):
        sol = self.pp.add_solution_simple({'CaCl2': 1, 'Na2CO3': 1})
        # test solution number
        assert_equal(sol.number, 0)
        # test solution ph, sc, pe and temperature
        assert_equal(round(sol.pH, 2), 10.41)
        assert_equal(round(sol.sc, 2), 435.35)
        assert_equal(round(sol.pe, 2), 7.4)
        assert_equal(round(sol.temperature, 2), 25)
        # test solution composition
        assert_equal(round(sol.total("Ca", units='mol'), 4), 0.001)
        assert_equal(round(sol.total("Cl"), 4), 2)
        assert_equal(round(sol.total_element("C"), 4), 1)
        # test si
        assert_equal(round(sol.si("Calcite"), 2), 1.71)
        # test phases
        assert_equal(len(sol.phases), 10)
        assert_equal(len(sol.elements), 5)
        # test ionic strength
        assert_equal(round(sol.I, 4), 0.0045)
        # test mass
        assert_equal(round(sol.mass, 2), 1.0)
        # test activity
        assert_equal(round(sol.activity('Ca+2', units='mol'), 5), 0.00054)
        # test moles
        assert_equal(round(sol.moles('Ca+2', units='mol'), 5), 0.00071)

        assert_equal(round(sol.molality('Ca+2', units='mol'), 5), 0.00071)

        # test species_moles
        assert_equal(round(sol.species_moles['Ca+2'], 5), 0.00071)
        assert_equal(round(sol.species_molalities['Ca+2'], 5), 0.00071)
        assert_equal(round(sol.species_activities['Ca+2'], 5), 0.00054)

    def test2_solution_functions(self):
        sol = self.pp.add_solution_simple({'CaCl2': 1})
        # add components
        sol.add('NaHCO3', 1)
        assert_equal(round(sol.total('Na'), 4), 1)
        # desaturate
        sol.desaturate('Calcite')
        assert_equal(sol.si('Calcite'), 0)

        # remove mmol
        sol.remove('Na', 0.5)
        assert_equal(round(sol.total('Na'), 4), 0.5)

        # remove fraction
        sol.remove_fraction('Na', 0.5)
        assert_equal(round(sol.total('Na'), 5), 0.25)

        # change ph using base
        sol.change_ph(10)
        assert_equal(round(sol.pH, 2), 10)
        # change ph using acid
        sol.change_ph(5)
        assert_equal(round(sol.pH, 2), 5)
        # raise ph using custom chemical (NaOH)
        sol.change_ph(8, 'NaOH')
        assert_equal(round(sol.pH, 2), 8)

        sol.saturate('Calcite', 1)
        assert_equal(sol.si('Calcite'), 1)

        sol.change_temperature(10)
        assert_equal(sol.temperature, 10)

    def test3_mixing(self):
        sol1 = self.pp.add_solution_simple({'NaCl': 1})
        sol2 = self.pp.add_solution_simple({})
        sol3 = self.pp.mix_solutions({sol1: 0.5, sol2: 0.5})
        assert_equal(round(sol3.total('Na'), 1), 0.5)

    def test4_solution_listing(self):
        # test solution list
        sol_list = self.pp.ip.get_solution_list()
        assert_equal(len(sol_list), 7)
        # test forgetting solutions
        self.pp.remove_solutions([1, 2, 3])
        sol_list = self.pp.ip.get_solution_list()
        assert_equal(len(sol_list), 4)

    def test5_addition(self):
        sol1 = self.pp.add_solution_simple({'NaCl': 1})
        sol2 = self.pp.add_solution_simple({'NaCl': 2})
        sol3 = sol1 + sol2
        assert_equal(round(sol3.mass), 2.0)

        sol4 = sol1 / 2 + sol2 / 2
        assert_equal(round(sol4.total('Na'), 1), 1.5)

        sol5 = sol1 * 0.5 + sol2 * 0.5
        assert_equal(round(sol5.total('Na'), 1), 1.5)

        # test invalid mixtures
        def testadd(sol, other):
            return sol + other

        def testdiv(sol, other):
            return sol / other

        def testmul(sol, other):
            return sol * other

        assert_raises(TypeError, testadd, sol1, 1)
        assert_raises(TypeError, testdiv, sol1, sol2)
        assert_raises(TypeError, testmul, sol1, sol2)

    def test6_misc(self):
        sol1 = self.pp.add_solution_simple({'NaCl': 1})
        sol2 = sol1.copy()
        assert_equal(sol1.sc, sol2.sc)

        sol2.forget()
        assert_equal(sol2.pH, -999)

    def test7_dump_and_load(self):
        sol5a = self.pp.get_solution(5)
        self.pp.dump_solutions()
        pp2 = PhreeqPython(from_file='dump.gz')
        sol5b = pp2.get_solution(5)

        assert_almost_equal(sol5a.sc, sol5b.sc, 2)
        assert_equal(self.pp.ip.get_solution_list(),
                     pp2.ip.get_solution_list())

    def test8_raw_solutions(self):
        sol8 = self.pp.add_solution_raw({
            'pH': '8.0',
            'temp': '20',
            'units': 'mg/l',
            'Alkalinity': '200 as HCO3',
            'Ca': '40.1',
            'Cl': '71.0'
        })
        assert_equal(sol8.pH, 8.0)
        assert_almost_equal(sol8.total_element('Ca'), 1, 2)
        assert_almost_equal(sol8.total_element('Cl'), 2, 2)

    def test9_gas_phases(self):

        gas1 = self.pp.add_gas({
            'CH4(g)': 0.5,
            'Ntg(g)': 0.5
        },
                               volume=1,
                               pressure=1,
                               fixed_pressure=False,
                               fixed_volume=True)

        assert_equal(gas1.pressure, 1)
        assert_almost_equal(gas1.volume, 1, 2)
        assert_almost_equal(gas1.total_moles, 0.041, 2)
        assert_almost_equal(gas1.pressure, 1, 2)
        assert_almost_equal(gas1.partial_pressures['CH4(g)'], 0.5, 2)
        assert_almost_equal(gas1.partial_pressures['Ntg(g)'], 0.5, 2)

        sol9 = self.pp.add_solution({})

        sol9.interact(gas1)

        assert_almost_equal(gas1.pressure, 0.975, 3)
        assert_almost_equal(gas1.volume, 1, 2)
        assert_almost_equal(gas1.partial_pressures['CH4(g)'], 0.48, 2)
        assert_almost_equal(gas1.partial_pressures['Ntg(g)'], 0.49, 2)

    def test10_use_non_default_database_directory(self):
        pp_test10 = PhreeqPython(database_directory=Path(__file__).parent)
        sol = pp_test10.add_solution_simple({'CaCl2': 1, 'Na2CO3': 1})
        # test solution number
        assert_equal(sol.number, 0)
        # test solution ph, sc, pe and temperature
        assert_equal(round(sol.pH, 2), 10.41)
        assert_equal(round(sol.sc, 2), 435.35)
        assert_equal(round(sol.pe, 2), 7.4)
        assert_equal(round(sol.temperature, 2), 25)
class TestPhreeqPython(object):

    pp = PhreeqPython()

    def test1_basiscs(self):
        sol = self.pp.add_solution({'CaCl2': 1, 'Na2CO3': 1})
        # test solution number
        assert_equal(sol.number, 1)
        # test solution ph, sc, pe and temperature
        assert_equal(round(sol.pH, 2), 10.41)
        assert_equal(round(sol.sc, 2), 435.35)
        assert_equal(round(sol.pe, 2), 7.4)
        assert_equal(round(sol.temperature, 2), 25)
        # test solution composition
        assert_equal(round(sol.total("Ca"), 4), 0.001)
        assert_equal(round(sol.total("Cl"), 4), 0.002)
        assert_equal(round(sol.total_element("C"), 4), 0.001)
        # test si
        assert_equal(round(sol.si("Calcite"), 2), 1.71)
        # test phases
        assert_equal(len(sol.phases), 10)
        assert_equal(len(sol.elements), 5)
        # test ionic strength
        assert_equal(round(sol.I, 4), 0.0045)
        # test mass
        assert_equal(round(sol.mass, 2), 1.0)
        # test activity
        assert_equal(round(sol.activity('Ca+2'), 5), 0.00054)
        # test moles
        assert_equal(round(sol.moles('Ca+2'), 5), 0.00071)

        assert_equal(round(sol.molality('Ca+2'), 5), 0.00071)

        # test species_moles
        assert_equal(round(sol.species_moles['Ca+2'], 5), 0.00071)
        assert_equal(round(sol.species_molalities['Ca+2'], 5), 0.00071)
        assert_equal(round(sol.species_activities['Ca+2'], 5), 0.00054)

    def test2_solution_functions(self):
        sol = self.pp.add_solution({'CaCl2': 1})
        # add components
        sol.add('NaHCO3', 1)
        assert_equal(round(sol.total('Na'), 4), 0.001)
        # desaturate
        sol.desaturate('Calcite')
        assert_equal(sol.si('Calcite'), 0)

        # remove mmol
        sol.remove('Na', 0.5)
        assert_equal(round(sol.total('Na'), 4), 0.0005)

        # remove fraction
        sol.remove_fraction('Na', 0.5)
        assert_equal(round(sol.total('Na'), 5), 0.00025)

        # change ph using base
        sol.change_ph(10)
        assert_equal(round(sol.pH, 2), 10)
        # change ph using acid
        sol.change_ph(5)
        assert_equal(round(sol.pH, 2), 5)
        # raise ph using custom chemical (NaOH)
        sol.change_ph(8, 'NaOH')
        assert_equal(round(sol.pH, 2), 8)

        sol.saturate('Calcite', 1)
        assert_equal(sol.si('Calcite'), 1)

        sol.change_temperature(10)
        assert_equal(sol.temperature, 10)

    def test3_mixing(self):
        sol1 = self.pp.add_solution({'NaCl': 1})
        sol2 = self.pp.add_solution({})
        sol3 = self.pp.mix_solutions({sol1: 0.5, sol2: 0.5})
        assert_equal(round(sol3.total('Na'), 4), 0.0005)

    def test4_solution_listing(self):
        # test solution list
        sol_list = self.pp.ip.get_solution_list()
        assert_equal(len(sol_list), 7)
        # test forgetting solutions
        self.pp.remove_solutions([1, 2, 3])
        sol_list = self.pp.ip.get_solution_list()
        assert_equal(len(sol_list), 4)

    def test5_addition(self):
        sol1 = self.pp.add_solution({'NaCl': 1})
        sol2 = self.pp.add_solution({'NaCl': 2})
        sol3 = sol1 + sol2
        assert_equal(round(sol3.mass), 2.0)

        sol4 = sol1 / 2 + sol2 / 2
        assert_equal(round(sol4.total('Na') * 1000, 1), 1.5)

        sol5 = sol1 * 0.5 + sol2 * 0.5
        assert_equal(round(sol5.total('Na') * 1000, 1), 1.5)

        # test invalid mixtures
        def testadd(sol, other):
            return sol + other

        def testdiv(sol, other):
            return sol / other

        def testmul(sol, other):
            return sol * other

        assert_raises(TypeError, testadd, sol1, 1)
        assert_raises(TypeError, testdiv, sol1, sol2)
        assert_raises(TypeError, testmul, sol1, sol2)

    def test6_misc(self):
        sol1 = self.pp.add_solution({'NaCl': 1})
        sol2 = sol1.copy()
        assert_equal(sol1.sc, sol2.sc)

        sol2.forget()
        assert_equal(sol2.pH, -999)

    def test7_dump_and_load(self):
        sol5a = self.pp.get_solution(5)
        self.pp.dump_solutions()
        pp2 = PhreeqPython('dump.gz')
        sol5b = pp2.get_solution(5)

        assert_almost_equal(sol5a.sc, sol5b.sc, 2)
        assert_equal(self.pp.ip.get_solution_list(),
                     pp2.ip.get_solution_list())

    def test8_raw_solutions(self):
        sol8 = self.pp.add_solution_raw({
            'pH': '8.0',
            'temp': '20',
            'units': 'mg/l',
            'Alkalinity': '200 as HCO3',
            'Ca': '40.1',
            'Cl': '71.0'
        })
        assert_equal(sol8.pH, 8.0)
        assert_almost_equal(sol8.total_element('Ca'), 1e-3, 5)
        assert_almost_equal(sol8.total_element('Cl'), 2e-3, 5)
Пример #10
0
class Test_line_network(unittest.TestCase):
    # Test simple network consisting of 4 nodes in a line
    def setUp(self):
        # self.net = Network(inputfile="tests/Case1.inp")
        self.net = Network(inputfile="Case1.inp")
        self.pp = PhreeqPython()
        self.vic = Victoria(self.net, self.pp)
        self.solutions = {}
        sol0 = self.pp.add_solution({'Ca': 0, 'units': 'mmol/l'})
        sol1 = self.pp.add_solution({'Ca': 1, 'units': 'mmol/l'})
        self.solutions[0] = sol0
        self.solutions[self.net.reservoirs['1'].uid] = sol1

    def test1(self):
        models = self.vic.solver.models
        # Test node count
        self.assertEqual(len(self.net.nodes), len(models.nodes))
        # Test junction count
        self.assertEqual(len(self.net.junctions), len(models.junctions))
        # Test reservoir count
        self.assertEqual(len(self.net.reservoirs), len(models.reservoirs))
        # Test tank count
        self.assertEqual(len(self.net.tanks), len(models.tanks))
        # Test link count
        self.assertEqual(len(self.net.links), len(models.links))
        # Test pipe count
        self.assertEqual(len(self.net.pipes), len(models.pipes))
        # Test pump count
        self.assertEqual(len(self.net.pumps), len(models.pumps))
        # Test valve count
        self.assertEqual(len(self.net.valves), len(models.valves))

    def test2(self):
        # Fill the network with a standard solution
        self.net.solve()
        self.vic.fill_network(self.solutions, from_reservoir=False)
        # Test the initial concentrations of Ca
        self.assertEqual(
            self.vic.get_conc_pipe_avg(self.net.links['1'], 'Ca', 'mmol'), 0)
        self.assertEqual(
            self.vic.get_conc_pipe_avg(self.net.links['2'], 'Ca', 'mmol'), 0)
        self.assertEqual(
            self.vic.get_conc_pipe_avg(self.net.links['3'], 'Ca', 'mmol'), 0)
        self.assertEqual(
            self.vic.get_conc_pipe_avg(self.net.links['6'], 'Ca', 'mmol'), 0)

    def test3(self):
        # Fill the network with the initial reservoir solution
        self.net.solve()
        self.vic.fill_network(self.solutions, from_reservoir=True)
        # Test the initial concentrations of Ca
        self.assertAlmostEqual(
            self.vic.get_conc_pipe_avg(self.net.links['1'], 'Ca', 'mmol'), 1,
            4)
        self.assertAlmostEqual(
            self.vic.get_conc_pipe_avg(self.net.links['2'], 'Ca', 'mmol'), 1,
            4)
        self.assertAlmostEqual(
            self.vic.get_conc_pipe_avg(self.net.links['3'], 'Ca', 'mmol'), 1,
            4)
        self.assertAlmostEqual(
            self.vic.get_conc_pipe_avg(self.net.links['6'], 'Ca', 'mmol'), 1,
            4)

    def test4(self):
        # Test the residence time in the pipes. Each pipe has a residence time of 1000 seconds

        # Time parameters Victoria
        time_end = 2  # hours
        timestep_network = 60  # minutes
        timestep_victoria = 1  # second
        # Convert units to seconds
        time_end *= 3600
        timestep_network *= 60
        time_count = 0

        # Fill the network
        self.net.solve()  # Need to run Epynet for a single timestep
        self.vic.fill_network(self.solutions, from_reservoir=False)

        for t1 in range(0, time_end, timestep_network):
            self.net.solve(simtime=t1)
            self.vic.check_flow_direction()

            for t2 in range(0, timestep_network, timestep_victoria):
                self.vic.step(timestep_victoria, self.solutions)
                time_count += t2
                if time_count == 999:
                    node = self.vic.get_conc_node(self.net.nodes['2'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 0, 4)
                elif time_count == 1000:
                    node = self.vic.get_conc_node(self.net.nodes['2'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 1, 4)
                elif time_count == 1999:
                    node = self.vic.get_conc_node(self.net.nodes['3'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 0, 4)
                elif time_count == 2000:
                    node = self.vic.get_conc_node(self.net.nodes['3'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 1, 4)
                elif time_count == 2999:
                    node = self.vic.get_conc_node(self.net.nodes['4'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 0, 4)
                elif time_count == 3000:
                    node = self.vic.get_conc_node(self.net.nodes['4'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 1, 4)
                elif time_count == 3999:
                    node = self.vic.get_conc_node(self.net.nodes['6'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 0, 4)
                elif time_count == 4000:
                    node = self.vic.get_conc_node(self.net.nodes['6'], 'Ca',
                                                  'mmol')
                    self.assertAlmostEqual(node, 1, 4)