Merge branch 'feature/n_windows' into 'master'
Allow WindowOpening to have more than one window of the given dimensions. See merge request cara/cara!68
This commit is contained in:
commit
ca7f8745aa
4 changed files with 56 additions and 21 deletions
|
|
@ -120,12 +120,9 @@ class FormData:
|
|||
# Initializes a ventilation instance as a window if 'natural' is selected, or as a HEPA-filter otherwise
|
||||
if self.ventilation_type == 'natural':
|
||||
if self.windows_open == 'interval':
|
||||
period, duration = 120, 10
|
||||
elif self.windows_number == 'breaks':
|
||||
# TODO: Implement windows open in breaks
|
||||
period, duration = 120, 120
|
||||
window_interval = models.PeriodicInterval(120, 10)
|
||||
else:
|
||||
period, duration = 120, 120
|
||||
window_interval = always_on
|
||||
|
||||
if self.event_type == 'single_event':
|
||||
month_number = int(self.single_event_date.split('/')[1])
|
||||
|
|
@ -136,11 +133,13 @@ class FormData:
|
|||
inside_temp = models.PiecewiseConstant((0, 24), (293,))
|
||||
outside_temp = models.GenevaTemperatures[month]
|
||||
|
||||
# I multiply the opening width by the number of windows to simulate the correct window area
|
||||
ventilation = models.WindowOpening(active=models.PeriodicInterval(period=period, duration=duration),
|
||||
inside_temp=inside_temp, outside_temp=outside_temp, cd_b=0.6,
|
||||
window_height=self.window_height,
|
||||
opening_length=self.opening_distance * self.windows_number)
|
||||
ventilation = models.WindowOpening(
|
||||
active=window_interval,
|
||||
inside_temp=inside_temp, outside_temp=outside_temp, cd_b=0.6,
|
||||
window_height=self.window_height,
|
||||
opening_length=self.opening_distance,
|
||||
number_of_windows=self.windows_number,
|
||||
)
|
||||
elif self.ventilation_type == "no-ventilation":
|
||||
ventilation = models.AirChange(active=always_on, air_exch=0.)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
</div>
|
||||
|
||||
<div id="DIVnatural_ventilation" style="display:none">
|
||||
Number of windows: <input type="number" id="windows_number" name="windows_number" min="0"><br>
|
||||
Number of windows: <input type="number" id="windows_number" name="windows_number" min="1"><br>
|
||||
Height of window: <input type="number" step=0.01 id="window_height" name="window_height" placeholder="meters" min="0"><br>
|
||||
Width of window: <input type="number" step=0.01 id="window_width" name="window_width" placeholder="meters" min="0"><br>
|
||||
Opening distance: <input type="number" step=0.01 id="opening_distance" name="opening_distance" placeholder="meters" min="0"><br>
|
||||
|
|
|
|||
|
|
@ -208,14 +208,24 @@ class WindowOpening(Ventilation):
|
|||
#: The interval in which the window is open.
|
||||
active: Interval
|
||||
|
||||
inside_temp: PiecewiseConstant #: The temperature inside the room (Kelvin)
|
||||
outside_temp: PiecewiseConstant #: The temperature outside of the window (Kelvin)
|
||||
#: The temperature inside the room (Kelvin).
|
||||
inside_temp: PiecewiseConstant
|
||||
|
||||
window_height: float #: The height of the window
|
||||
#: The temperature outside of the window (Kelvin).
|
||||
outside_temp: PiecewiseConstant
|
||||
|
||||
opening_length: float #: The length of the opening-gap when the window is open
|
||||
#: The height of the window.
|
||||
window_height: float
|
||||
|
||||
cd_b: float = 0.6 #: Discharge coefficient: what portion effective area is used to exchange air (0 <= cd_b <= 1)
|
||||
#: The length of the opening-gap when the window is open
|
||||
opening_length: float
|
||||
|
||||
#: The number of windows of the given dimensions.
|
||||
number_of_windows: int = 1
|
||||
|
||||
#: Discharge coefficient: what portion effective area is
|
||||
#: used to exchange air (0 <= cd_b <= 1)
|
||||
cd_b: float = 0.6
|
||||
|
||||
def transition_times(self) -> typing.Set[float]:
|
||||
transitions = super().transition_times()
|
||||
|
|
@ -228,13 +238,14 @@ class WindowOpening(Ventilation):
|
|||
if not self.active.triggered(time):
|
||||
return 0.
|
||||
|
||||
inside_temp = self.inside_temp.value(time)
|
||||
outside_temp = self.outside_temp.value(time)
|
||||
|
||||
# Reminder, no dependence on time in the resulting calculation.
|
||||
|
||||
temp_delta = abs(self.inside_temp.value(time) -
|
||||
self.outside_temp.value(time)) / self.outside_temp.value(time)
|
||||
temp_delta = abs(inside_temp - outside_temp) / outside_temp
|
||||
root = np.sqrt(9.81 * self.window_height * temp_delta)
|
||||
|
||||
return (3600 / (3 * room.volume)) * self.cd_b * self.window_height * self.opening_length * root
|
||||
window_area = self.window_height * self.opening_length * self.number_of_windows
|
||||
return (3600 / (3 * room.volume)) * self.cd_b * window_area * root
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
|
|
|||
25
cara/tests/test_ventilation.py
Normal file
25
cara/tests/test_ventilation.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
||||
from cara import models
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def baseline_window():
|
||||
return models.WindowOpening(
|
||||
active=models.SpecificInterval(((0, 4), (5, 9))),
|
||||
inside_temp=models.PiecewiseConstant((0, 24), (293,)),
|
||||
outside_temp=models.PiecewiseConstant((0, 24), (283,)),
|
||||
cd_b=0.6, window_height=1.6, opening_length=0.6,
|
||||
)
|
||||
|
||||
|
||||
def test_number_of_windows(baseline_window):
|
||||
room = models.Room(75)
|
||||
two_windows = dataclasses.replace(baseline_window, number_of_windows=2)
|
||||
|
||||
one_window_exchange = baseline_window.air_exchange(room, 1)
|
||||
two_window_exchange = two_windows.air_exchange(room, 1)
|
||||
assert one_window_exchange != 0
|
||||
assert one_window_exchange * 2 == two_window_exchange
|
||||
Loading…
Reference in a new issue