Skip to content

Commit

Permalink
Merge branch 'main' into data_input_dict-overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
liuly12 committed Jul 26, 2024
2 parents b8a958d + 05ead2f commit 111f20a
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 82 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,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://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:

Expand Down Expand Up @@ -109,6 +110,32 @@ Find the bibtex citation below:
}
```

Please also include citation to the WSIMOD theory paper:

> Dobson, B., Liu, L. and Mijic, A. (2024)
‘Modelling water quantity and quality for integrated water cycle management with the Water Systems Integrated Modelling framework (WSIMOD) software’,
Geoscientific Model Development.
Copernicus Publications,
17(10),
p. 4495.
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},
title = {Modelling water quantity and quality for integrated water cycle management with the Water Systems Integrated Modelling framework (WSIMOD) software},
journal = {Geoscientific Model Development},
volume = {17},
year = {2024},
number = {10},
pages = {4495--4513},
url = {https://gmd.copernicus.org/articles/17/4495/2024/},
doi = {10.5194/gmd-17-4495-2024}
}
```

## Acknowledgements

WSIMOD was developed by [Barnaby Dobson](https://github.com/barneydobson) and [Leyang Liu](https://github.com/liuly12).
Expand Down
121 changes: 68 additions & 53 deletions tests/test_wtw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
6 changes: 3 additions & 3 deletions wsimod/nodes/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}.
"""
Expand Down
52 changes: 26 additions & 26 deletions wsimod/nodes/wtw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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
Expand All @@ -99,19 +99,19 @@ 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.
Returns:
(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
Expand All @@ -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).
Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 111f20a

Please sign in to comment.