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