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 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)
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 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
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
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)
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})
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)
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)