From 35dff3d9ac1eb3cc9b7c32c5a508e23a2880ce89 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:41:11 +0200 Subject: [PATCH 01/19] add time as argument to infectious_virus_removal_rate --- cara/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cara/models.py b/cara/models.py index 82052fd9..ca632f6a 100644 --- a/cara/models.py +++ b/cara/models.py @@ -195,8 +195,7 @@ class Model: def virus(self): return self.infected.virus - @property - def infectious_virus_removal_rate(self): + def infectious_virus_removal_rate(self, time: float) -> float: # Particle deposition on the floor vg = 1 * 10 ** -4 # Height of the emission source to the floor - i.e. mouth/nose (m) @@ -209,7 +208,7 @@ class Model: @functools.lru_cache() def concentration(self, time: float) -> float: t = time - IVRR = self.infectious_virus_removal_rate + IVRR = self.infectious_virus_removal_rate(time) V = self.room.volume Ni = self.infected_occupants ER = self.infected.emission_rate(time) From 032bc6d0adeb370f108454e1d50d06be7e99f0e1 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:43:45 +0200 Subject: [PATCH 02/19] add window parameters as Room attributes --- cara/models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cara/models.py b/cara/models.py index ca632f6a..be49e9de 100644 --- a/cara/models.py +++ b/cara/models.py @@ -10,6 +10,12 @@ from dataclasses import dataclass class Room: volume: int + # The height of the window in the room (assumes one window) + window_height: float + + # The length of the opening-gap when the window is open + opening_length: float + @dataclass(frozen=True) class Ventilation: From 7dcdc0de84ead37217b9f95fa734c3eae035644a Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:44:29 +0200 Subject: [PATCH 03/19] replace ventilation scheme classes --- cara/models.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/cara/models.py b/cara/models.py index be49e9de..0152ba9e 100644 --- a/cara/models.py +++ b/cara/models.py @@ -1,6 +1,7 @@ import functools import numpy as np import typing +from abc import abstractmethod from dataclasses import dataclass @@ -8,6 +9,7 @@ from dataclasses import dataclass @dataclass(frozen=True) class Room: + # The total volume of the room volume: int # The height of the window in the room (assumes one window) @@ -19,10 +21,60 @@ class Room: @dataclass(frozen=True) class Ventilation: - QairNat: float = 514.74 + """ + An abstract class for ventilation schemes + """ - def air_change_per_hour(self, room: Room): - return self.QairNat / room.volume + @abstractmethod + def air_exchange(self, room: Room, time: float) -> float: + # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time + pass + + +@dataclass(frozen=True) +class PeriodicWindow(Ventilation): + + # The window is opened for minutes every minutes + period: int + duration: int + + # The temperatures, in Kelvin, inside and outside the window + inside_temp: float + outside_temp: float + + # TODO: Figure out what this coefficient represents + cd_b: float + + def air_exchange(self, room, time: float) -> float: + # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time + + # If the window is closed, no air is being exchanged + if time % self.period < (self.period - self.duration): + return 0 + + return ((3600 / (3 * room.volume)) * self.cd_b * room.window_height * + room.opening_length * np.sqrt(9.81 * room.window_height * (abs(self.inside_temp - self.outside_temp)) + / self.outside_temp)) + + +@dataclass(frozen=True) +class PeriodicHEPA(Ventilation): + + # The HEPA is switched on for minutes every minutes + period: int + duration: int + + # The rate at which the HEPA exchanges air (when switched on) + q_air_mech: int + + def air_exchange(self, room, time: float) -> float: + # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time + + # If the HEPA is off, no air is being exchanged + if time % self.period < (self.period - self.duration): + return 0 + + return self.q_air_mech / room.volume @dataclass(frozen=True) From aff4cf84ed6db9acaf8c53fc37312bb02da1ed6c Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:44:44 +0200 Subject: [PATCH 04/19] use new air_exchange function --- cara/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cara/models.py b/cara/models.py index 0152ba9e..da34bc3a 100644 --- a/cara/models.py +++ b/cara/models.py @@ -261,7 +261,7 @@ class Model: # Deposition rate (h^-1) k = (vg * 3600) / h - return k + self.virus.decay_constant + self.ventilation.air_change_per_hour(self.room) + return k + self.virus.decay_constant + self.ventilation.air_exchange(self.room, time) @functools.lru_cache() def concentration(self, time: float) -> float: From d37927d78bbf256300d714a00fe0ca39d5a44488 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:45:01 +0200 Subject: [PATCH 05/19] update baseline_model fixture --- cara/tests/test_known_quantities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 72f0c708..14424eec 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -25,8 +25,8 @@ def test_no_mask_emission_rate(baseline_model): @pytest.fixture def baseline_model(): model = models.Model( - room=models.Room(volume=75), - ventilation=models.Ventilation(), + room=models.Room(volume=75, window_height=1.6, opening_length=0.6), + ventilation=models.PeriodicWindow(period=120, duration=120, inside_temp=293, outside_temp=283, cd_b=0.6), infected=models.InfectedPerson( virus=models.Virus.types['SARS_CoV_2'], present_times=((0, 4), (5, 8)), From 5273455a11643bc0ddb5828d8435c5d78c82a062 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 14:57:08 +0200 Subject: [PATCH 06/19] update correct concentrations to reflect QairNat --- cara/tests/test_known_quantities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 14424eec..b9440bf6 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -47,6 +47,6 @@ def test_r0(baseline_model): concentrations = [baseline_model.concentration(t) for t in ts] npt.assert_allclose( concentrations, - [0.000000e+00, saturated, 1.274225e-04, saturated, 5.580870e-08], + [0.000000e+00, 2.909211e-01, 1.273836e-04, 2.909210e-01, 5.577662e-08], rtol=1e-5 ) From 496f2d2a81c9f4f91599e51342eeb837d8ac5116 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 15:43:48 +0200 Subject: [PATCH 07/19] add type hint for room --- cara/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cara/models.py b/cara/models.py index da34bc3a..032f8782 100644 --- a/cara/models.py +++ b/cara/models.py @@ -45,7 +45,7 @@ class PeriodicWindow(Ventilation): # TODO: Figure out what this coefficient represents cd_b: float - def air_exchange(self, room, time: float) -> float: + def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time # If the window is closed, no air is being exchanged @@ -67,7 +67,7 @@ class PeriodicHEPA(Ventilation): # The rate at which the HEPA exchanges air (when switched on) q_air_mech: int - def air_exchange(self, room, time: float) -> float: + def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time # If the HEPA is off, no air is being exchanged From 5fbda6afe33531e3db15014b58e61fc4ce6b74ea Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:10:52 +0200 Subject: [PATCH 08/19] move window parameters to Ventilation --- cara/models.py | 16 ++++++++-------- cara/tests/test_known_quantities.py | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cara/models.py b/cara/models.py index 032f8782..ae858f50 100644 --- a/cara/models.py +++ b/cara/models.py @@ -12,12 +12,6 @@ class Room: # The total volume of the room volume: int - # The height of the window in the room (assumes one window) - window_height: float - - # The length of the opening-gap when the window is open - opening_length: float - @dataclass(frozen=True) class Ventilation: @@ -42,6 +36,12 @@ class PeriodicWindow(Ventilation): inside_temp: float outside_temp: float + # The height of the window + window_height: float + + # The length of the opening-gap when the window is open + opening_length: float + # TODO: Figure out what this coefficient represents cd_b: float @@ -52,8 +52,8 @@ class PeriodicWindow(Ventilation): if time % self.period < (self.period - self.duration): return 0 - return ((3600 / (3 * room.volume)) * self.cd_b * room.window_height * - room.opening_length * np.sqrt(9.81 * room.window_height * (abs(self.inside_temp - self.outside_temp)) + return ((3600 / (3 * room.volume)) * self.cd_b * self.window_height * + self.opening_length * np.sqrt(9.81 * self.window_height * (abs(self.inside_temp - self.outside_temp)) / self.outside_temp)) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index b9440bf6..847e1646 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -25,8 +25,9 @@ def test_no_mask_emission_rate(baseline_model): @pytest.fixture def baseline_model(): model = models.Model( - room=models.Room(volume=75, window_height=1.6, opening_length=0.6), - ventilation=models.PeriodicWindow(period=120, duration=120, inside_temp=293, outside_temp=283, cd_b=0.6), + room=models.Room(volume=75), + ventilation=models.PeriodicWindow(period=120, duration=120, inside_temp=293, outside_temp=283, cd_b=0.6, + window_height=1.6, opening_length=0.6), infected=models.InfectedPerson( virus=models.Virus.types['SARS_CoV_2'], present_times=((0, 4), (5, 8)), From da026e62653197adaa0afeb9e44f07a1992e27ea Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:14:08 +0200 Subject: [PATCH 09/19] tidy up long expression --- cara/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cara/models.py b/cara/models.py index ae858f50..c825a58c 100644 --- a/cara/models.py +++ b/cara/models.py @@ -52,9 +52,9 @@ class PeriodicWindow(Ventilation): if time % self.period < (self.period - self.duration): return 0 - return ((3600 / (3 * room.volume)) * self.cd_b * self.window_height * - self.opening_length * np.sqrt(9.81 * self.window_height * (abs(self.inside_temp - self.outside_temp)) - / self.outside_temp)) + root = np.sqrt(9.81 * self.window_height * (abs(self.inside_temp - self.outside_temp)) / self.outside_temp) + + return (3600 / (3 * room.volume)) * self.cd_b * self.window_height * self.opening_length * root @dataclass(frozen=True) From 8e524fea1bd9bdf692786d9b038b1f7c0436e4f7 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:19:04 +0200 Subject: [PATCH 10/19] add colons to dataclass attribute docstrings --- cara/models.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/cara/models.py b/cara/models.py index c825a58c..ac2825f1 100644 --- a/cara/models.py +++ b/cara/models.py @@ -29,18 +29,15 @@ class Ventilation: class PeriodicWindow(Ventilation): # The window is opened for minutes every minutes - period: int - duration: int + period: int #: How often the window is opened (minutes) + duration: int #: How long the window remains opened for (minutes) - # The temperatures, in Kelvin, inside and outside the window - inside_temp: float - outside_temp: float + inside_temp: float #: The temperature inside the room (Kelvin) + outside_temp: float #: The temperature outside of the window (Kelvin) - # The height of the window - window_height: float + window_height: float #: The height of the window - # The length of the opening-gap when the window is open - opening_length: float + opening_length: float #: The length of the opening-gap when the window is open # TODO: Figure out what this coefficient represents cd_b: float @@ -61,11 +58,10 @@ class PeriodicWindow(Ventilation): class PeriodicHEPA(Ventilation): # The HEPA is switched on for minutes every minutes - period: int - duration: int + period: int #: How often the HEPA is switched on (minutes) + duration: int #: How long the HEPA remains switched on for (minutes) - # The rate at which the HEPA exchanges air (when switched on) - q_air_mech: int + q_air_mech: int #: The rate at which the HEPA exchanges air (when switched on) def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time From aa3a58caae783ae5132fb1b7de22e276c30f5e4b Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:23:21 +0200 Subject: [PATCH 11/19] update notebook with ventilation changes --- app/cara.ipynb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/cara.ipynb b/app/cara.ipynb index 906bf165..931d3197 100644 --- a/app/cara.ipynb +++ b/app/cara.ipynb @@ -42,7 +42,8 @@ " \"\"\"\n", " model = cara.models.Model(\n", " room=cara.models.Room(volume=volume),\n", - " ventilation=cara.models.Ventilation(),\n", + " ventilation=cara.models.PeriodicWindow(period=120, duration=120, inside_temp=293, outside_temp=283,\n", + " window_height=1.6, opening_length=0.6, cd_b=0.6),\n", " infected=cara.models.InfectedPerson(\n", " virus=cara.models.Virus.types['SARS_CoV_2'],\n", " present_times=((0, 4), (5, 8)),\n", @@ -145,7 +146,7 @@ ], "source": [ "ventilation_widgets = {\n", - " 'Natural': widgets.Label('Currently hard-coded to 514.74 / volume'),\n", + " 'Natural': widgets.Label('Currently hard-coded to window-example from mathematica notebook'),\n", " 'other': widgets.Label('Not yet implemented.')\n", "}\n", "for name, widget in ventilation_widgets.items():\n", @@ -288,4 +289,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file From 0a3785c2d18192b7a17b2931aa19f4f4ea440683 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:31:20 +0200 Subject: [PATCH 12/19] correct type hint on q_air_mech --- cara/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cara/models.py b/cara/models.py index ac2825f1..0a1ea586 100644 --- a/cara/models.py +++ b/cara/models.py @@ -61,7 +61,7 @@ class PeriodicHEPA(Ventilation): period: int #: How often the HEPA is switched on (minutes) duration: int #: How long the HEPA remains switched on for (minutes) - q_air_mech: int #: The rate at which the HEPA exchanges air (when switched on) + q_air_mech: float #: The rate at which the HEPA exchanges air (when switched on) def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time From d959e8ee0005c2f243ec7df2030b645236610f97 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:31:40 +0200 Subject: [PATCH 13/19] add new fixtures --- cara/tests/test_known_quantities.py | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 847e1646..8a56e390 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -42,6 +42,45 @@ def baseline_model(): return model +@pytest.fixture +def periodic_opening_model(): + model = models.Model( + room=models.Room(volume=75), + ventilation=models.PeriodicWindow(period=120, duration=15, inside_temp=293, outside_temp=283, cd_b=0.6, + window_height=1.6, opening_length=0.6), + infected=models.InfectedPerson( + virus=models.Virus.types['SARS_CoV_2'], + present_times=((0, 4), (5, 8)), + mask=models.Mask.types['No mask'], + activity=models.Activity.types['Light exercise'], + expiration=models.Expiration.types['Unmodulated Vocalization'], + ), + infected_occupants=1, + exposed_occupants=10, + exposed_activity=models.Activity.types['Light exercise'], + ) + return model + + +@pytest.fixture +def periodic_hepa_model(): + model = models.Model( + room=models.Room(volume=75), + ventilation=models.PeriodicHEPA(period=120, duration=15, q_air_mech=514.74), + infected=models.InfectedPerson( + virus=models.Virus.types['SARS_CoV_2'], + present_times=((0, 4), (5, 8)), + mask=models.Mask.types['No mask'], + activity=models.Activity.types['Light exercise'], + expiration=models.Expiration.types['Unmodulated Vocalization'], + ), + infected_occupants=1, + exposed_occupants=10, + exposed_activity=models.Activity.types['Light exercise'], + ) + return model + + def test_r0(baseline_model): saturated = 2.909312e-01 ts = [0, 4, 5, 7, 10] From f4dc698d1c6db3be5237e8af9ca62c631425ec90 Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:41:31 +0200 Subject: [PATCH 14/19] add test for PeriodicWindow --- cara/tests/test_known_quantities.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 8a56e390..9c632717 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -90,3 +90,9 @@ def test_r0(baseline_model): [0.000000e+00, 2.909211e-01, 1.273836e-04, 2.909210e-01, 5.577662e-08], rtol=1e-5 ) + + +def test_periodic_window(periodic_opening_model): + ts = [t for t in range(11)] + aes = [periodic_opening_model.ventilation.air_exchange(periodic_opening_model.room, t) for t in ts] + assert all(ae == (0 if t * 60 % 120 < 105 else 514.74) for ae, t in zip(aes, ts)) From 5ee96a1ddfac2646bc6dab2f7d8c7e74276a0b3c Mon Sep 17 00:00:00 2001 From: markus Date: Tue, 20 Oct 2020 16:42:41 +0200 Subject: [PATCH 15/19] add test for PeriodicHEPA --- cara/tests/test_known_quantities.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 9c632717..9a0f5711 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -96,3 +96,9 @@ def test_periodic_window(periodic_opening_model): ts = [t for t in range(11)] aes = [periodic_opening_model.ventilation.air_exchange(periodic_opening_model.room, t) for t in ts] assert all(ae == (0 if t * 60 % 120 < 105 else 514.74) for ae, t in zip(aes, ts)) + + +def test_periodic_hepa(periodic_hepa_model): + ts = [t for t in range(11)] + aes = [periodic_hepa_model.ventilation.air_exchange(periodic_hepa_model.room, t) for t in ts] + assert all(ae == (0 if t * 60 % 120 < 105 else 514.74) for ae, t in zip(aes, ts)) From 2e03934db7db6c88494e2b54661e694b44d4f2fe Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 21 Oct 2020 10:04:36 +0200 Subject: [PATCH 16/19] add docstring to cd_b --- cara/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cara/models.py b/cara/models.py index 0a1ea586..d836f61e 100644 --- a/cara/models.py +++ b/cara/models.py @@ -39,8 +39,7 @@ class PeriodicWindow(Ventilation): opening_length: float #: The length of the opening-gap when the window is open - # TODO: Figure out what this coefficient represents - cd_b: float + cd_b: float #: Discharge coefficient: what portion effective area is used to exchange air (0 <= cd_b <= 1) def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time From 964aff6217231715f87ca21324d8e307614546fd Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 21 Oct 2020 10:05:06 +0200 Subject: [PATCH 17/19] add default value to cd_b --- cara/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cara/models.py b/cara/models.py index d836f61e..31649aa4 100644 --- a/cara/models.py +++ b/cara/models.py @@ -39,7 +39,7 @@ class PeriodicWindow(Ventilation): opening_length: float #: The length of the opening-gap when the window is open - cd_b: float #: Discharge coefficient: what portion effective area is used to exchange air (0 <= cd_b <= 1) + cd_b: float = 0.6 #: Discharge coefficient: what portion effective area is used to exchange air (0 <= cd_b <= 1) def air_exchange(self, room: Room, time: float) -> float: # Returns the rate at which air is being exchanged in the given room per cubic meter at a given time From ea47010e3bb5fad9f038b549c5632554ba029fa0 Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 21 Oct 2020 10:18:43 +0200 Subject: [PATCH 18/19] hard-code correct answers in tests --- cara/tests/test_known_quantities.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 9a0f5711..3d047c0b 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -1,5 +1,6 @@ import numpy.testing as npt import pytest +from numpy import linspace import cara.models as models @@ -93,12 +94,14 @@ def test_r0(baseline_model): def test_periodic_window(periodic_opening_model): - ts = [t for t in range(11)] + ts = linspace(0, 9 * 60, 9) aes = [periodic_opening_model.ventilation.air_exchange(periodic_opening_model.room, t) for t in ts] - assert all(ae == (0 if t * 60 % 120 < 105 else 514.74) for ae, t in zip(aes, ts)) + answers = [0, 0, 0, 0, 0, 0, 0, 514.76 / 75, 0] + npt.assert_allclose(aes, answers, rtol=1e-5) def test_periodic_hepa(periodic_hepa_model): - ts = [t for t in range(11)] + ts = linspace(0, 9 * 60, 9) aes = [periodic_hepa_model.ventilation.air_exchange(periodic_hepa_model.room, t) for t in ts] - assert all(ae == (0 if t * 60 % 120 < 105 else 514.74) for ae, t in zip(aes, ts)) + answers = [0, 0, 0, 0, 0, 0, 0, 514.74 / 75, 0] + npt.assert_allclose(aes, answers, rtol=1e-5) From ffd0bc80cd962e0e0c648409c92b0393fc34aabd Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 21 Oct 2020 10:22:28 +0200 Subject: [PATCH 19/19] use smaller fixtures --- cara/tests/test_known_quantities.py | 51 ++++++++--------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 3d047c0b..206c5f05 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -44,42 +44,19 @@ def baseline_model(): @pytest.fixture -def periodic_opening_model(): - model = models.Model( - room=models.Room(volume=75), - ventilation=models.PeriodicWindow(period=120, duration=15, inside_temp=293, outside_temp=283, cd_b=0.6, - window_height=1.6, opening_length=0.6), - infected=models.InfectedPerson( - virus=models.Virus.types['SARS_CoV_2'], - present_times=((0, 4), (5, 8)), - mask=models.Mask.types['No mask'], - activity=models.Activity.types['Light exercise'], - expiration=models.Expiration.types['Unmodulated Vocalization'], - ), - infected_occupants=1, - exposed_occupants=10, - exposed_activity=models.Activity.types['Light exercise'], - ) - return model +def baseline_periodic_window(): + return models.PeriodicWindow(period=120, duration=15, inside_temp=293, outside_temp=283, cd_b=0.6, + window_height=1.6, opening_length=0.6) @pytest.fixture -def periodic_hepa_model(): - model = models.Model( - room=models.Room(volume=75), - ventilation=models.PeriodicHEPA(period=120, duration=15, q_air_mech=514.74), - infected=models.InfectedPerson( - virus=models.Virus.types['SARS_CoV_2'], - present_times=((0, 4), (5, 8)), - mask=models.Mask.types['No mask'], - activity=models.Activity.types['Light exercise'], - expiration=models.Expiration.types['Unmodulated Vocalization'], - ), - infected_occupants=1, - exposed_occupants=10, - exposed_activity=models.Activity.types['Light exercise'], - ) - return model +def baseline_room(): + return models.Room(volume=75) + + +@pytest.fixture +def baseline_periodic_hepa(): + return models.PeriodicHEPA(period=120, duration=15, q_air_mech=514.74) def test_r0(baseline_model): @@ -93,15 +70,15 @@ def test_r0(baseline_model): ) -def test_periodic_window(periodic_opening_model): +def test_periodic_window(baseline_periodic_window, baseline_room): ts = linspace(0, 9 * 60, 9) - aes = [periodic_opening_model.ventilation.air_exchange(periodic_opening_model.room, t) for t in ts] + aes = [baseline_periodic_window.air_exchange(baseline_room, t) for t in ts] answers = [0, 0, 0, 0, 0, 0, 0, 514.76 / 75, 0] npt.assert_allclose(aes, answers, rtol=1e-5) -def test_periodic_hepa(periodic_hepa_model): +def test_periodic_hepa(baseline_periodic_hepa, baseline_room): ts = linspace(0, 9 * 60, 9) - aes = [periodic_hepa_model.ventilation.air_exchange(periodic_hepa_model.room, t) for t in ts] + aes = [baseline_periodic_hepa.air_exchange(baseline_room, t) for t in ts] answers = [0, 0, 0, 0, 0, 0, 0, 514.74 / 75, 0] npt.assert_allclose(aes, answers, rtol=1e-5)