diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 9989f80c..32f73cfc 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -663,59 +663,78 @@ def test_decay_queue(self): def test_overrides(self): # node - no need to test # tank - tank = Tank(capacity=10, area=8, datum = 4) - tank.apply_overrides({'capacity': 3, - 'area': 2, - 'datum': 3.5}) + tank = Tank(capacity=10, area=8, datum=4) + tank.apply_overrides({"capacity": 3, "area": 2, "datum": 3.5}) self.assertEqual(tank.capacity, 3) self.assertEqual(tank.area, 2) self.assertEqual(tank.datum, 3.5) # residence tank - tank = ResidenceTank(capacity=10, area=8, datum = 4, residence_time = 8) - tank.apply_overrides({'capacity': 3, - 'area': 2, - 'datum': 3.5, - 'residence_time': 6}) + tank = ResidenceTank(capacity=10, area=8, datum=4, residence_time=8) + tank.apply_overrides( + {"capacity": 3, "area": 2, "datum": 3.5, "residence_time": 6} + ) self.assertEqual(tank.capacity, 3) self.assertEqual(tank.area, 2) self.assertEqual(tank.datum, 3.5) self.assertEqual(tank.residence_time, 6) # decay tank - tank = DecayTank(capacity=10, area=8, datum = 4, decays = {'phosphate' : {'constant' : 0.001, 'exponent' : 1.005}}) - tank.apply_overrides({'capacity': 3, - 'area': 2, - 'datum': 3.5, - 'decays': {'phosphate' : {'constant' : 1.001, 'exponent' : 10.005}} - }) + tank = DecayTank( + capacity=10, + area=8, + datum=4, + decays={"phosphate": {"constant": 0.001, "exponent": 1.005}}, + ) + tank.apply_overrides( + { + "capacity": 3, + "area": 2, + "datum": 3.5, + "decays": {"phosphate": {"constant": 1.001, "exponent": 10.005}}, + } + ) self.assertEqual(tank.capacity, 3) self.assertEqual(tank.area, 2) self.assertEqual(tank.datum, 3.5) - self.assertDictEqual(tank.decays, {'phosphate' : {'constant' : 1.001, 'exponent' : 10.005}}) + self.assertDictEqual( + tank.decays, {"phosphate": {"constant": 1.001, "exponent": 10.005}} + ) # queue tank - tank = QueueTank(capacity=10, area=8, datum = 4, number_of_timesteps = 8) - tank.apply_overrides({'capacity': 3, - 'area': 2, - 'datum': 3.5, - 'number_of_timesteps': 6}) + tank = QueueTank(capacity=10, area=8, datum=4, number_of_timesteps=8) + tank.apply_overrides( + {"capacity": 3, "area": 2, "datum": 3.5, "number_of_timesteps": 6} + ) self.assertEqual(tank.capacity, 3) self.assertEqual(tank.area, 2) self.assertEqual(tank.datum, 3.5) self.assertEqual(tank.number_of_timesteps, 6) self.assertEqual(tank.internal_arc.number_of_timesteps, 6) # decay queue tank - tank = DecayQueueTank(capacity=10, area=8, datum = 4, number_of_timesteps = 8, decays = {'phosphate' : {'constant' : 0.001, 'exponent' : 1.005}}) - tank.apply_overrides({'capacity': 3, - 'area': 2, - 'datum': 3.5, - 'number_of_timesteps': 6, - 'decays': {'phosphate' : {'constant' : 1.001, 'exponent' : 10.005}} - }) + tank = DecayQueueTank( + capacity=10, + area=8, + datum=4, + number_of_timesteps=8, + decays={"phosphate": {"constant": 0.001, "exponent": 1.005}}, + ) + tank.apply_overrides( + { + "capacity": 3, + "area": 2, + "datum": 3.5, + "number_of_timesteps": 6, + "decays": {"phosphate": {"constant": 1.001, "exponent": 10.005}}, + } + ) self.assertEqual(tank.capacity, 3) self.assertEqual(tank.area, 2) self.assertEqual(tank.datum, 3.5) self.assertEqual(tank.number_of_timesteps, 6) self.assertEqual(tank.internal_arc.number_of_timesteps, 6) - self.assertDictEqual(tank.internal_arc.decays, {'phosphate' : {'constant' : 1.001, 'exponent' : 10.005}}) + self.assertDictEqual( + tank.internal_arc.decays, + {"phosphate": {"constant": 1.001, "exponent": 10.005}}, + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_storage.py b/tests/test_storage.py index 3305f961..a761bf86 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -292,36 +292,56 @@ def test_riverreservoir_environmental(self): "temperature": (20 * 10 + 30 * 23) / 40, } self.assertDictAlmostEqual(d2, reservoir.tank.storage, 15) - + def test_storage_overrides(self): constants.set_default_pollutants() - storage = Storage(name = '', decays = {"phosphate": {"constant": 1.005, "exponent": 1.005}}) - storage.apply_overrides({'capacity': 1.43, - 'area': 2.36, - 'datum': 0.32, - 'decays': {"nitrite": {"constant": 10.005, "exponent": 1.105}} - }) + storage = Storage( + name="", decays={"phosphate": {"constant": 1.005, "exponent": 1.005}} + ) + storage.apply_overrides( + { + "capacity": 1.43, + "area": 2.36, + "datum": 0.32, + "decays": {"nitrite": {"constant": 10.005, "exponent": 1.105}}, + } + ) self.assertEqual(storage.capacity, 1.43) self.assertEqual(storage.tank.capacity, 1.43) self.assertEqual(storage.area, 2.36) self.assertEqual(storage.tank.area, 2.36) self.assertEqual(storage.datum, 0.32) self.assertEqual(storage.tank.datum, 0.32) - self.assertDictEqual(storage.decays, {"phosphate": {"constant": 1.005, "exponent": 1.005}, - "nitrite": {"constant": 10.005, "exponent": 1.105}}) - self.assertDictEqual(storage.tank.decays, {"phosphate": {"constant": 1.005, "exponent": 1.005}, - "nitrite": {"constant": 10.005, "exponent": 1.105}}) - + self.assertDictEqual( + storage.decays, + { + "phosphate": {"constant": 1.005, "exponent": 1.005}, + "nitrite": {"constant": 10.005, "exponent": 1.105}, + }, + ) + self.assertDictEqual( + storage.tank.decays, + { + "phosphate": {"constant": 1.005, "exponent": 1.005}, + "nitrite": {"constant": 10.005, "exponent": 1.105}, + }, + ) + def test_groundwater_overrides(self): - groundwater = Groundwater(name = '', decays = {"phosphate": {"constant": 1.005, "exponent": 1.005}}) - groundwater.apply_overrides({'residence_time': 27.3, - 'infiltration_threshold': 200, - 'infiltration_pct': 0.667, - 'capacity': 1.43, - 'area': 2.36, - 'datum': 0.32, - 'decays': {"nitrite": {"constant": 10.005, "exponent": 1.105}} - }) + groundwater = Groundwater( + name="", decays={"phosphate": {"constant": 1.005, "exponent": 1.005}} + ) + groundwater.apply_overrides( + { + "residence_time": 27.3, + "infiltration_threshold": 200, + "infiltration_pct": 0.667, + "capacity": 1.43, + "area": 2.36, + "datum": 0.32, + "decays": {"nitrite": {"constant": 10.005, "exponent": 1.105}}, + } + ) self.assertEqual(groundwater.residence_time, 27.3) self.assertEqual(groundwater.infiltration_threshold, 200) self.assertEqual(groundwater.infiltration_pct, 0.667) @@ -331,49 +351,61 @@ def test_groundwater_overrides(self): self.assertEqual(groundwater.tank.area, 2.36) self.assertEqual(groundwater.datum, 0.32) self.assertEqual(groundwater.tank.datum, 0.32) - self.assertDictEqual(groundwater.decays, {"phosphate": {"constant": 1.005, "exponent": 1.005}, - "nitrite": {"constant": 10.005, "exponent": 1.105}}) - self.assertDictEqual(groundwater.tank.decays, {"phosphate": {"constant": 1.005, "exponent": 1.005}, - "nitrite": {"constant": 10.005, "exponent": 1.105}}) - + self.assertDictEqual( + groundwater.decays, + { + "phosphate": {"constant": 1.005, "exponent": 1.005}, + "nitrite": {"constant": 10.005, "exponent": 1.105}, + }, + ) + self.assertDictEqual( + groundwater.tank.decays, + { + "phosphate": {"constant": 1.005, "exponent": 1.005}, + "nitrite": {"constant": 10.005, "exponent": 1.105}, + }, + ) + def test_river_overrides(self): - river = River(name = '') - overrides = {'length': 27.3, - 'width': 200, - 'velocity': 0.667, - 'damp': 1.43, - 'mrf': 2.36, - 'uptake_PNratio': 0.32, - 'bulk_density': 5.32, - 'denpar_w': 0.432, - 'T_wdays': 23.5, - 'halfsatINwater': 3.269, - 'hsatTP': 2.431, - 'limpppar': 6.473, - 'prodNpar': 7.821, - 'prodPpar': 8.231, - 'muptNpar': 6.213, - 'muptPpar': 7.021, - 'max_temp_lag': 3.213, - 'max_phosphorus_lag': 78.321, - # 'area': 75.2, - # 'capacity': 123 - } + river = River(name="") + overrides = { + "length": 27.3, + "width": 200, + "velocity": 0.667, + "damp": 1.43, + "mrf": 2.36, + "uptake_PNratio": 0.32, + "bulk_density": 5.32, + "denpar_w": 0.432, + "T_wdays": 23.5, + "halfsatINwater": 3.269, + "hsatTP": 2.431, + "limpppar": 6.473, + "prodNpar": 7.821, + "prodPpar": 8.231, + "muptNpar": 6.213, + "muptPpar": 7.021, + "max_temp_lag": 3.213, + "max_phosphorus_lag": 78.321, + # 'area': 75.2, + # 'capacity': 123 + } overrides_to_check = overrides.copy() river.apply_overrides(overrides) for k, v in overrides_to_check.items(): - if k == 'area': + if k == "area": v = 27.3 * 200 self.assertEqual(river.tank.area, v) - if k == 'capacity': + if k == "capacity": v = constants.UNBOUNDED_CAPACITY self.assertEqual(river.tank.capacity, v) self.assertEqual(getattr(river, k), v) - + def test_riverreservoir_overrides(self): - riverreservoir = RiverReservoir(name = '') - riverreservoir.apply_overrides({'environmental_flow': 154}) + riverreservoir = RiverReservoir(name="") + riverreservoir.apply_overrides({"environmental_flow": 154}) self.assertEqual(riverreservoir.environmental_flow, 154) + if __name__ == "__main__": unittest.main() diff --git a/wsimod/nodes/nodes.py b/wsimod/nodes/nodes.py index 42fa7f77..9f9b6f06 100644 --- a/wsimod/nodes/nodes.py +++ b/wsimod/nodes/nodes.py @@ -793,27 +793,27 @@ def __init__(self, capacity=0, area=1, datum=10, initial_storage=0): else: self.storage = self.empty_vqip() self.storage_ = self.empty_vqip() # Lagged storage for mass balance - + def apply_overrides(self, overrides: Dict[str, Any] = {}): """Apply overrides to the tank. - Enables a user to override any of the following parameters: + Enables a user to override any of the following parameters: area, capacity, datum. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ - self.capacity = overrides.pop("capacity", - self.capacity) + self.capacity = overrides.pop("capacity", self.capacity) if "area" in overrides.keys(): - print("warning: when overriding area, capacity is not automatically recalculated") - self.area = overrides.pop("area", - self.area) - self.datum = overrides.pop("datum", - self.datum) + print( + "warning: when overriding area, capacity is not automatically \ + recalculated" + ) + self.area = overrides.pop("area", self.area) + self.datum = overrides.pop("datum", self.datum) if len(overrides) > 0: print(f"No override behaviour defined for: {overrides.keys()}") - + def ds(self): """Should be called by parent object to get change in storage. @@ -1121,15 +1121,14 @@ def __init__(self, residence_time=2, **kwargs): def apply_overrides(self, overrides: Dict[str, Any] = {}): """Apply overrides to the residencetank. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: residence_time. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ - self.residence_time = overrides.pop("residence_time", - self.residence_time) + self.residence_time = overrides.pop("residence_time", self.residence_time) super().apply_overrides(overrides) def pull_outflow(self): @@ -1177,10 +1176,10 @@ def __init__(self, decays={}, parent=None, **kwargs): def apply_overrides(self, overrides: Dict[str, Any] = {}): """Apply overrides to the decaytank. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: decays. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ @@ -1237,15 +1236,16 @@ def __init__(self, number_of_timesteps=0, **kwargs): def apply_overrides(self, overrides: Dict[str, Any] = {}): """Apply overrides to the queuetank. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: number_of_timesteps. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ - self.number_of_timesteps = overrides.pop("number_of_timesteps", - self.number_of_timesteps) + self.number_of_timesteps = overrides.pop( + "number_of_timesteps", self.number_of_timesteps + ) self.internal_arc.number_of_timesteps = self.number_of_timesteps super().apply_overrides(overrides) @@ -1419,15 +1419,16 @@ def __init__(self, decays={}, parent=None, number_of_timesteps=1, **kwargs): def apply_overrides(self, overrides: Dict[str, Any] = {}): """Apply overrides to the decayqueuetank. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: number_of_timesteps, decays. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ - self.number_of_timesteps = overrides.pop("number_of_timesteps", - self.number_of_timesteps) + self.number_of_timesteps = overrides.pop( + "number_of_timesteps", self.number_of_timesteps + ) self.internal_arc.number_of_timesteps = self.number_of_timesteps self.internal_arc.decays.update(overrides.pop("decays", {})) super().apply_overrides(overrides) diff --git a/wsimod/nodes/storage.py b/wsimod/nodes/storage.py index 73f9c958..d1189f39 100644 --- a/wsimod/nodes/storage.py +++ b/wsimod/nodes/storage.py @@ -4,10 +4,11 @@ @author: bdobson Converted to totals on 2022-05-03 """ from math import exp +from typing import Any, Dict from wsimod.core import constants from wsimod.nodes.nodes import DecayQueueTank, DecayTank, Node, QueueTank, Tank -from typing import Any, Dict + class Storage(Node): """""" @@ -72,25 +73,26 @@ def __init__( # Mass balance self.mass_balance_ds.append(lambda: self.tank.ds()) - def apply_overrides(self, overrides = Dict[str, Any]): + def apply_overrides(self, overrides=Dict[str, Any]): """Override parameters. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: capacity, area, datum, decays. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - # not using pop as these items need to stay in the overrides to be fed into the tank overrides - if 'capacity' in overrides.keys(): - self.capacity = overrides['capacity'] - if 'area' in overrides.keys(): - self.area = overrides['area'] - if 'datum' in overrides.keys(): - self.datum = overrides['datum'] - if 'decays' in overrides.keys(): - self.decays.update(overrides['decays']) + # not using pop as these items need to stay + # in the overrides to be fed into the tank overrides + if "capacity" in overrides.keys(): + self.capacity = overrides["capacity"] + if "area" in overrides.keys(): + self.area = overrides["area"] + if "datum" in overrides.keys(): + self.datum = overrides["datum"] + if "decays" in overrides.keys(): + self.decays.update(overrides["decays"]) # apply tank overrides self.tank.apply_overrides(overrides) super().apply_overrides(overrides) @@ -194,22 +196,21 @@ def __init__( self.data_input_dict = data_input_dict super().__init__(**kwargs) - def apply_overrides(self, overrides = Dict[str, Any]): + def apply_overrides(self, overrides=Dict[str, Any]): """Override parameters. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: residence_time, infiltration_threshold, infiltration_pct. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - self.residence_time = overrides.pop("residence_time", - self.residence_time) - self.infiltration_threshold = overrides.pop("infiltration_threshold", - self.infiltration_threshold) - self.infiltration_pct = overrides.pop("infiltration_pct", - self.infiltration_pct) + self.residence_time = overrides.pop("residence_time", self.residence_time) + self.infiltration_threshold = overrides.pop( + "infiltration_threshold", self.infiltration_threshold + ) + self.infiltration_pct = overrides.pop("infiltration_pct", self.infiltration_pct) super().apply_overrides(overrides) def distribute(self): @@ -307,18 +308,17 @@ def __init__(self, timearea={0: 1}, data_input_dict={}, **kwargs): initial_storage=self.initial_storage, ) - def apply_overrides(self, overrides = Dict[str, Any]): + def apply_overrides(self, overrides=Dict[str, Any]): """Override parameters. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: timearea. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - self.timearea = overrides.pop("timearea", - self.timearea) + self.timearea = overrides.pop("timearea", self.timearea) super().apply_overrides(overrides) def push_set_timearea(self, vqip): @@ -506,7 +506,10 @@ def __init__( # Set parameters self.depth = depth if depth != 2: - print('warning: the depth parameter is unused by River nodes because it is intended for capacity to be unbounded. It may be removed in a future version.') + print( + "warning: the depth parameter is unused by River nodes because it is \ + intended for capacity to be unbounded. It may be removed in a future version." + ) self.length = length # [m] self.width = width # [m] self.velocity = velocity # [m/dt] @@ -597,33 +600,55 @@ def __init__( # self.v_change_vqip(vqip_, min(vqip_['volume'], # self.get_dt_excess()['volume'])) _ = self.tank.push_storage(vqip_, force=True) # return self.extract_vqip(vqip, vqip_) - - def apply_overrides(self, overrides = Dict[str, Any]): + + def apply_overrides(self, overrides=Dict[str, Any]): """Override parameters. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: timearea. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - overwrite_params = ["length", "width", "velocity", "damp", "mrf", - "uptake_PNratio", "bulk_density", "denpar_w", "T_wdays", - "halfsatINwater", "hsatTP", "limpppar", "prodNpar", "prodPpar", - "muptNpar", "muptPpar", "max_temp_lag", "max_phosphorus_lag"] + overwrite_params = [ + "length", + "width", + "velocity", + "damp", + "mrf", + "uptake_PNratio", + "bulk_density", + "denpar_w", + "T_wdays", + "halfsatINwater", + "hsatTP", + "limpppar", + "prodNpar", + "prodPpar", + "muptNpar", + "muptPpar", + "max_temp_lag", + "max_phosphorus_lag", + ] for param in overwrite_params: setattr(self, param, overrides.pop(param, getattr(self, param))) - - if 'area' in overrides.keys(): - print('ERROR: specifying area is depreciated in overrides for river, please specify length and width instead') - overrides['area'] = self.length * self.width - if 'capacity' in overrides.keys(): - print('ERROR: specifying capacity is depreciated in overrides for river, it is always set as unbounded capacity') - overrides['capacity'] = constants.UNBOUNDED_CAPACITY + + if "area" in overrides.keys(): + print( + "ERROR: specifying area is depreciated in overrides \ + for river, please specify length and width instead" + ) + overrides["area"] = self.length * self.width + if "capacity" in overrides.keys(): + print( + "ERROR: specifying capacity is depreciated in overrides \ + for river, it is always set as unbounded capacity" + ) + overrides["capacity"] = constants.UNBOUNDED_CAPACITY super().apply_overrides(overrides) - + def pull_check_river(self, vqip=None): """Check amount of water that can be pulled from river tank and upstream. @@ -1009,18 +1034,19 @@ def __init__(self, environmental_flow=0, **kwargs): self.__class__.__name__ = "Reservoir" - def apply_overrides(self, overrides = Dict[str, Any]): + def apply_overrides(self, overrides=Dict[str, Any]): """Override parameters. - - Enables a user to override any of the following parameters: + + Enables a user to override any of the following parameters: environmental_flow. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - self.environmental_flow = overrides.pop("environmental_flow", - self.environmental_flow) + self.environmental_flow = overrides.pop( + "environmental_flow", self.environmental_flow + ) super().apply_overrides(overrides) def push_set_river_reservoir(self, vqip):