diff --git a/README.md b/README.md index ab5601b5..f10b34b7 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ pip install -e .[dev,demos] ## How to cite WSIMOD -[![DOI](https://joss.theoj.org/papers/10.21105/joss.04996/status.svg)](https://doi.org/10.21105/joss.04996) +[![DOI](https://joss.theoj.org/papers/10.21105/joss.04996/status.svg)](https://doi.org/10.21105/joss.04996) [![DOI](https://img.shields.io/badge/GMD-10.5194/gmd--17--449--2024-brightgreen)](https://doi.org/10.5194/gmd-17-4495-2024) If you would like to use our software, please cite it using the following: @@ -121,6 +121,7 @@ Please also include citation to the WSIMOD theory paper: doi: 10.5194/gmd-17-4495-2024 Find the bibtex citation below: + ```bibtex @article{gmd-17-4495-2024, author = {Barnaby Dobson and Leyang Liu and Ana Mijic}, diff --git a/tests/test_wtw.py b/tests/test_wtw.py index 1a2061f9..447145e7 100644 --- a/tests/test_wtw.py +++ b/tests/test_wtw.py @@ -45,74 +45,89 @@ def test_treat(self): name="", treatment_throughput_capacity=10, ) - wtw.current_input= {'volume' : 8, - 'phosphate' : 5, - 'temperature' : constants.DECAY_REFERENCE_TEMPERATURE} + wtw.current_input = { + "volume": 8, + "phosphate": 5, + "temperature": constants.DECAY_REFERENCE_TEMPERATURE, + } wtw.treat_current_input() - self.assertEqual(8 * wtw.process_parameters['volume']['constant'], - wtw.treated["volume"]) - self.assertEqual(5 * wtw.process_parameters['phosphate']['constant'], - wtw.treated["phosphate"]) - self.assertEqual(8 * wtw.liquor_multiplier['volume'], - wtw.liquor['volume']) - self.assertEqual(5 * wtw.liquor_multiplier['phosphate'], - wtw.liquor['phosphate']) - self.assertEqual(5 - 5 * wtw.process_parameters['phosphate']['constant']\ - - 5 * wtw.liquor_multiplier['phosphate'], - wtw.solids['phosphate']) + self.assertEqual( + 8 * wtw.process_parameters["volume"]["constant"], wtw.treated["volume"] + ) + self.assertEqual( + 5 * wtw.process_parameters["phosphate"]["constant"], + wtw.treated["phosphate"], + ) + self.assertEqual(8 * wtw.liquor_multiplier["volume"], wtw.liquor["volume"]) + self.assertEqual( + 5 * wtw.liquor_multiplier["phosphate"], wtw.liquor["phosphate"] + ) + self.assertEqual( + 5 + - 5 * wtw.process_parameters["phosphate"]["constant"] + - 5 * wtw.liquor_multiplier["phosphate"], + wtw.solids["phosphate"], + ) def test_override(self): wtw = WTW( name="", treatment_throughput_capacity=10, - percent_solids = 0.1, - liquor_multiplier = {'volume' : 0.05, 'phosphate' : 0.5}, - process_parameters = {'phosphate' : {'constant' : 0.1, - 'exponent' : 1.001}} + percent_solids=0.1, + liquor_multiplier={"volume": 0.05, "phosphate": 0.5}, + process_parameters={"phosphate": {"constant": 0.1, "exponent": 1.001}}, ) - wtw.apply_overrides({'percent_solids' : 0.05}) - self.assertAlmostEqual(wtw.process_parameters['volume']['constant'], - 0.9) + wtw.apply_overrides({"percent_solids": 0.05}) + self.assertAlmostEqual(wtw.process_parameters["volume"]["constant"], 0.9) self.assertEqual(wtw.percent_solids, 0.05) - - wtw.apply_overrides({'percent_solids' : 0.1, - 'liquor_multiplier' : {'volume' : 0.1}}) - - self.assertEqual(wtw.process_parameters['volume']['constant'], - 0.8) - self.assertEqual(wtw.liquor_multiplier['volume'], 0.1) - self.assertEqual(wtw.liquor_multiplier['phosphate'], 0.5) - - wtw.apply_overrides({'percent_solids' : 0.1, - 'liquor_multiplier' : {'volume' : 0.1, - 'phosphate' : 0.01}}) - self.assertEqual(wtw.liquor_multiplier['phosphate'], 0.01) - - wtw.apply_overrides({'process_parameters' : {'phosphate' : {'constant' : 0.01}}}) - self.assertEqual(wtw.process_parameters['phosphate']['constant'], 0.01) - self.assertEqual(wtw.process_parameters['phosphate']['exponent'], 1.001) - - overrides = {'process_parameters' : {'phosphate' : {'exponent' : 1.01}}, - 'liquor_multiplier' : {'phosphate' : 0.1}, - 'percent_solids' : 0.1, - 'treatment_throughput_capacity' : 20, - 'name' : 'new_name'} + + wtw.apply_overrides( + {"percent_solids": 0.1, "liquor_multiplier": {"volume": 0.1}} + ) + + self.assertEqual(wtw.process_parameters["volume"]["constant"], 0.8) + self.assertEqual(wtw.liquor_multiplier["volume"], 0.1) + self.assertEqual(wtw.liquor_multiplier["phosphate"], 0.5) + + wtw.apply_overrides( + { + "percent_solids": 0.1, + "liquor_multiplier": {"volume": 0.1, "phosphate": 0.01}, + } + ) + self.assertEqual(wtw.liquor_multiplier["phosphate"], 0.01) + + wtw.apply_overrides({"process_parameters": {"phosphate": {"constant": 0.01}}}) + self.assertEqual(wtw.process_parameters["phosphate"]["constant"], 0.01) + self.assertEqual(wtw.process_parameters["phosphate"]["exponent"], 1.001) + + overrides = { + "process_parameters": {"phosphate": {"exponent": 1.01}}, + "liquor_multiplier": {"phosphate": 0.1}, + "percent_solids": 0.1, + "treatment_throughput_capacity": 20, + "name": "new_name", + } wtw.apply_overrides(overrides) - self.assertSetEqual(set(overrides.keys()), set(['name'])) + self.assertSetEqual(set(overrides.keys()), set(["name"])) self.assertEqual(wtw.treatment_throughput_capacity, 20) def test_wwtw_overrides(self): - wwtw = WWTW(name='') - vol = wwtw.process_parameters['volume']['constant'] - wwtw.apply_overrides({'treatment_throughput_capacity' : 20, - 'process_parameters' : {'phosphate' : - {'constant' : 0.01}}, - 'stormwater_storage_capacity': 100}) + wwtw = WWTW(name="") + vol = wwtw.process_parameters["volume"]["constant"] + wwtw.apply_overrides( + { + "treatment_throughput_capacity": 20, + "process_parameters": {"phosphate": {"constant": 0.01}}, + "stormwater_storage_capacity": 100, + } + ) self.assertEqual(wwtw.treatment_throughput_capacity, 20) - self.assertEqual(wwtw.process_parameters['phosphate']['constant'], 0.01) - self.assertEqual(wwtw.process_parameters['volume']['constant'], vol) + self.assertEqual(wwtw.process_parameters["phosphate"]["constant"], 0.01) + self.assertEqual(wwtw.process_parameters["volume"]["constant"], vol) self.assertEqual(wwtw.stormwater_storage_capacity, 100) + if __name__ == "__main__": unittest.main() diff --git a/wsimod/nodes/nodes.py b/wsimod/nodes/nodes.py index 4f9c1e4a..2e125af9 100644 --- a/wsimod/nodes/nodes.py +++ b/wsimod/nodes/nodes.py @@ -81,10 +81,10 @@ def __init__(self, name, data_input_dict=None): def apply_overrides(self, overrides: Dict[str, Any] = {}) -> None: """Apply overrides to the node. - The Node does not have any overwriteable parameters. So if any - overrides are passed up to the node, this means that there are unused + The Node does not have any overwriteable parameters. So if any + overrides are passed up to the node, this means that there are unused parameters from the Node subclass, which is flagged. - + Args: overrides (dict, optional): Dictionary of overrides. Defaults to {}. """ diff --git a/wsimod/nodes/wtw.py b/wsimod/nodes/wtw.py index db99d56e..e40f0a5d 100644 --- a/wsimod/nodes/wtw.py +++ b/wsimod/nodes/wtw.py @@ -4,13 +4,15 @@ @author: bdobson Converted to totals on 2022-05-03 """ +from typing import Any, Dict + from wsimod.core import constants from wsimod.nodes.nodes import Node, Tank -from typing import Any, Dict + class WTW(Node): """A generic Water Treatment Works (WTW) node. - + This class is a generic water treatment works node. It is intended to be subclassed into freshwater and wastewater treatment works (FWTW and WWTW respectively). @@ -86,9 +88,7 @@ def __init__( # Update args super().__init__(name) - self.process_parameters["volume"] = { - "constant": self.calculate_volume() - } + self.process_parameters["volume"] = {"constant": self.calculate_volume()} # Update handlers self.push_set_handler["default"] = self.push_set_deny @@ -99,7 +99,7 @@ def __init__( self.treated = self.empty_vqip() self.liquor = self.empty_vqip() self.solids = self.empty_vqip() - + def calculate_volume(self): """Calculate the volume proportion of treated water. @@ -107,11 +107,11 @@ def calculate_volume(self): (float): Volume of treated water """ return 1 - self._percent_solids - self._liquor_multiplier["volume"] - + @property def percent_solids(self): return self._percent_solids - + @percent_solids.setter def percent_solids(self, value): self._percent_solids = value @@ -120,16 +120,16 @@ def percent_solids(self, value): @property def liquor_multiplier(self): return self._liquor_multiplier - + @liquor_multiplier.setter def liquor_multiplier(self, value): self._liquor_multiplier.update(value) self.process_parameters["volume"]["constant"] = self.calculate_volume() - - 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: percent_solids, treatment_throughput_capacity, process_parameters (the entire dict does not need to be redefined, only changed values need to be included), liquor_multiplier (as with process_parameters). @@ -138,17 +138,17 @@ def apply_overrides(self, overrides = Dict[str, Any]): overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ - self.percent_solids = overrides.pop("percent_solids", - self._percent_solids) - self.liquor_multiplier = overrides.pop("liquor_multiplier", - self._liquor_multiplier) + self.percent_solids = overrides.pop("percent_solids", self._percent_solids) + self.liquor_multiplier = overrides.pop( + "liquor_multiplier", self._liquor_multiplier + ) process_parameters = overrides.pop("process_parameters", {}) for key, value in process_parameters.items(): self.process_parameters[key].update(value) - + self.treatment_throughput_capacity = overrides.pop( - "treatment_throughput_capacity", - self.treatment_throughput_capacity) + "treatment_throughput_capacity", self.treatment_throughput_capacity + ) super().apply_overrides(overrides) def get_excess_throughput(self): @@ -300,20 +300,20 @@ def apply_overrides(self, overrides=Dict[str, Any]): Enables a user to override any parameter of the stormwater tank, and then calls any overrides in WTW. - + Args: overrides (Dict[str, Any]): Dict describing which parameters should be overridden (keys) and new values (values). Defaults to {}. """ self.stormwater_storage_capacity = overrides.pop( - "stormwater_storage_capacity", - self.stormwater_storage_capacity) + "stormwater_storage_capacity", self.stormwater_storage_capacity + ) self.stormwater_storage_area = overrides.pop( - "stormwater_storage_area", - self.stormwater_storage_area) + "stormwater_storage_area", self.stormwater_storage_area + ) self.stormwater_storage_elevation = overrides.pop( - "stormwater_storage_elevation", - self.stormwater_storage_elevation) + "stormwater_storage_elevation", self.stormwater_storage_elevation + ) self.stormwater_tank.area = self.stormwater_storage_area self.stormwater_tank.capacity = self.stormwater_storage_capacity self.stormwater_tank.datum = self.stormwater_storage_elevation