Merge branch 'develop/hepa_in_calculator' into 'master'
Adding support to HEPA in calculator See merge request cara/cara!37
This commit is contained in:
commit
16f3e6943b
3 changed files with 92 additions and 9 deletions
|
|
@ -22,6 +22,7 @@ class FormData:
|
|||
coffee_option: bool
|
||||
event_type: str
|
||||
floor_area: float
|
||||
hepa_option: bool
|
||||
infected_people: int
|
||||
lunch_option: bool
|
||||
mask_wearing: str
|
||||
|
|
@ -59,6 +60,7 @@ class FormData:
|
|||
coffee_option=(form_data['coffee_option'] == '1'),
|
||||
event_type=form_data['event_type'],
|
||||
floor_area=float(form_data['floor_area']),
|
||||
hepa_option=(form_data['hepa_option'] == '1'),
|
||||
infected_people=int(form_data['infected_people']),
|
||||
lunch_finish=time_string_to_minutes(form_data['lunch_finish']),
|
||||
lunch_option=(form_data['lunch_option'] == '1'),
|
||||
|
|
@ -106,12 +108,19 @@ class FormData:
|
|||
window_height=self.window_height,
|
||||
opening_length=self.opening_distance * self.windows_number)
|
||||
else:
|
||||
q_air_mech = (self.air_changes * self.room_volume if self.mechanical_ventilation_type == 'air_changes'
|
||||
else self.air_supply)
|
||||
ventilation = models.HEPAFilter(active=models.PeriodicInterval(period=120, duration=120),
|
||||
q_air_mech=q_air_mech)
|
||||
if self.mechanical_ventilation_type == 'air_changes':
|
||||
ventilation = models.AirChange(active=models.PeriodicInterval(period=120, duration=120),
|
||||
air_exch=self.air_changes)
|
||||
else:
|
||||
ventilation = models.HVACMechanical(active=models.PeriodicInterval(period=120, duration=120),
|
||||
q_air_mech=self.air_supply)
|
||||
|
||||
return ventilation
|
||||
if self.hepa_option:
|
||||
hepa = models.HEPAFilter(active=models.PeriodicInterval(period=120, duration=120),
|
||||
q_air_mech=250.)
|
||||
return models.MultipleVentilation((ventilation,hepa))
|
||||
else:
|
||||
return ventilation
|
||||
|
||||
def present_interval(self) -> models.Interval:
|
||||
coffee_period = (self.activity_finish - self.activity_start) // self.coffee_breaks
|
||||
|
|
@ -232,6 +241,7 @@ def baseline_raw_form_data():
|
|||
'coffee_option': '1',
|
||||
'event_type': 'single_event',
|
||||
'floor_area': '',
|
||||
'hepa_option': '0',
|
||||
'infected_people': '1',
|
||||
'lunch_finish': '13:30',
|
||||
'lunch_option': '1',
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ def test_model_from_dict(baseline_form_data):
|
|||
# assert model.ventilation == cara.models.Ventilation()
|
||||
|
||||
|
||||
def test_ventilation(baseline_form):
|
||||
def test_ventilation_window(baseline_form):
|
||||
room = models.Room(75)
|
||||
window = models.WindowOpening(
|
||||
active=models.PeriodicInterval(period=120, duration=10),
|
||||
|
|
@ -40,6 +40,63 @@ def test_ventilation(baseline_form):
|
|||
[baseline_form.ventilation().air_exchange(room, t) for t in ts])
|
||||
|
||||
|
||||
def test_ventilation_mechanical(baseline_form):
|
||||
room = models.Room(75)
|
||||
mech = models.HVACMechanical(
|
||||
active=models.PeriodicInterval(period=120, duration=120),
|
||||
q_air_mech=500.,
|
||||
)
|
||||
baseline_form.ventilation_type = 'mechanical'
|
||||
baseline_form.mechanical_ventilation_type = 'mechanical'
|
||||
baseline_form.air_supply = 500.
|
||||
|
||||
ts = np.linspace(8, 16, 100)
|
||||
np.testing.assert_allclose([mech.air_exchange(room, t) for t in ts],
|
||||
[baseline_form.ventilation().air_exchange(room, t) for t in ts])
|
||||
|
||||
|
||||
def test_ventilation_airchanges(baseline_form):
|
||||
room = models.Room(75)
|
||||
airchange = models.AirChange(
|
||||
active=models.PeriodicInterval(period=120, duration=120),
|
||||
air_exch=3.,
|
||||
)
|
||||
baseline_form.ventilation_type = 'mechanical'
|
||||
baseline_form.mechanical_ventilation_type = 'air_changes'
|
||||
baseline_form.air_changes = 3.
|
||||
|
||||
ts = np.linspace(8, 16, 100)
|
||||
np.testing.assert_allclose([airchange.air_exchange(room, t) for t in ts],
|
||||
[baseline_form.ventilation().air_exchange(room, t) for t in ts])
|
||||
|
||||
|
||||
def test_ventilation_window_hepa(baseline_form):
|
||||
room = models.Room(75)
|
||||
window = models.WindowOpening(
|
||||
active=models.PeriodicInterval(period=120, duration=10),
|
||||
inside_temp=models.PiecewiseConstant((0, 24), (293,)),
|
||||
outside_temp=models.GenevaTemperatures['Dec'],
|
||||
cd_b=0.6, window_height=1.6, opening_length=0.6,
|
||||
)
|
||||
hepa = models.HEPAFilter(
|
||||
active=models.PeriodicInterval(period=120, duration=120),
|
||||
q_air_mech=250.,
|
||||
)
|
||||
ventilation = models.MultipleVentilation((window,hepa))
|
||||
|
||||
baseline_form.ventilation_type = 'natural'
|
||||
baseline_form.windows_open = '10 min / 2h'
|
||||
baseline_form.event_type = 'recurrent_event'
|
||||
baseline_form.recurrent_event_month = 'December'
|
||||
baseline_form.window_height = 1.6
|
||||
baseline_form.opening_distance = 0.6
|
||||
baseline_form.hepa_option = '1'
|
||||
|
||||
ts = np.linspace(8, 16, 100)
|
||||
np.testing.assert_allclose([ventilation.air_exchange(room, t) for t in ts],
|
||||
[baseline_form.ventilation().air_exchange(room, t) for t in ts])
|
||||
|
||||
|
||||
def test_present_intervals(baseline_form):
|
||||
baseline_form.coffee_duration = 15
|
||||
baseline_form.coffee_option = True
|
||||
|
|
|
|||
|
|
@ -288,7 +288,8 @@ def test_windowopening(time, expected_value):
|
|||
expected_value,rtol=1e-5)
|
||||
|
||||
|
||||
def build_hourly_dependent_model(month, intervals_open=((7.5, 8.5),)):
|
||||
def build_hourly_dependent_model(month, intervals_open=((7.5, 8.5),),
|
||||
intervals_presence_infected=((0, 4), (5, 7.5))):
|
||||
model = models.Model(
|
||||
room=models.Room(volume=75),
|
||||
ventilation=models.WindowOpening(
|
||||
|
|
@ -299,7 +300,7 @@ def build_hourly_dependent_model(month, intervals_open=((7.5, 8.5),)):
|
|||
),
|
||||
infected=models.InfectedPerson(
|
||||
virus=models.Virus.types['SARS_CoV_2'],
|
||||
presence=models.SpecificInterval(((0, 4), (5, 7.5))),
|
||||
presence=models.SpecificInterval(intervals_presence_infected),
|
||||
mask=models.Mask.types['No mask'],
|
||||
activity=models.Activity.types['Light exercise'],
|
||||
expiration=models.Expiration.types['Unmodulated Vocalization'],
|
||||
|
|
@ -371,13 +372,28 @@ def build_hourly_dependent_model_multipleventilation(month, intervals_open=((7.5
|
|||
"time",
|
||||
[0.5, 1.2, 2., 3.5, 5., 6.5, 7.5, 7.9, 8.],
|
||||
)
|
||||
def test_concentrations_hourly_dep_startup(month, temperatures, time):
|
||||
def test_concentrations_hourly_dep_temp_vs_constant(month, temperatures, time):
|
||||
# The concentrations should be the same up to 8 AM (time when the
|
||||
# temperature changes DURING the window opening).
|
||||
m1 = build_hourly_dependent_model(month)
|
||||
m2 = build_constant_temp_model(temperatures[7]+273.15)
|
||||
npt.assert_allclose(m1.concentration(time), m2.concentration(time), rtol=1e-5)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"month, temperatures",
|
||||
models.Geneva_hourly_temperatures_celsius_per_hour.items(),
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"time",
|
||||
[0.5, 1.2, 2., 3.5, 5., 6.5, 7.5, 7.9, 8.],
|
||||
)
|
||||
def test_concentrations_hourly_dep_temp_startup(month, temperatures, time):
|
||||
# The concentrations should be the zero up to the first presence time
|
||||
# of an infecter person.
|
||||
m = build_hourly_dependent_model(month,((0.,0.5),(1,1.5),(4,4.5),(7.5,8)),
|
||||
((8,12.),))
|
||||
assert m.concentration(time) == 0.
|
||||
|
||||
|
||||
def test_concentrations_hourly_dep_multipleventilation():
|
||||
m = build_hourly_dependent_model_multipleventilation('Jan')
|
||||
|
|
|
|||
Loading…
Reference in a new issue