No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
f696857
... +4 ...
2318581
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
1 | - | from pythermalcomfort.psychrometrics import * |
|
2 | - | from pythermalcomfort.utilities import * |
|
1 | + | import warnings |
|
2 | + | from pythermalcomfort.psychrometrics import ( |
|
3 | + | units_converter, |
|
4 | + | t_o, |
|
5 | + | p_sat_torr, |
|
6 | + | check_standard_compliance, |
|
7 | + | ) |
|
3 | 8 | import math |
|
4 | 9 | from scipy import optimize |
|
5 | 10 | from numba import jit |
93 | 98 | warnings.simplefilter("always") |
|
94 | 99 | ||
95 | 100 | if ce == 0: |
|
96 | - | warnings.warn("The cooling effect could not be calculated, assuming ce = 0", UserWarning) |
|
101 | + | warnings.warn( |
|
102 | + | "The cooling effect could not be calculated, assuming ce = 0", UserWarning |
|
103 | + | ) |
|
97 | 104 | ||
98 | 105 | if units.lower() == "ip": |
|
99 | 106 | ce = ce / 1.8 * 3.28 |
174 | 181 | .. code-block:: python |
|
175 | 182 | ||
176 | 183 | >>> from pythermalcomfort.models import pmv_ppd |
|
184 | + | >>> from pythermalcomfort.psychrometrics import v_relative |
|
177 | 185 | >>> # calculate relative air velocity |
|
178 | - | >>> vr = v_relative(v=0.1, met=1.2) |
|
186 | + | >>> v_r = v_relative(v=0.1, met=1.2) |
|
179 | 187 | >>> # as you can see the relative air velocity is 0.16 m/s which is |
|
180 | 188 | significantly higher than v |
|
181 | - | >>> results = pmv_ppd(tdb=25, tr=25, vr=vr, rh=50, met=1.2, clo=0.5, wme=0, |
|
189 | + | >>> results = pmv_ppd(tdb=25, tr=25, vr=v_r, rh=50, met=1.2, clo=0.5, wme=0, |
|
182 | 190 | standard="ISO") |
|
183 | 191 | >>> print(results) |
|
184 | 192 | {'pmv': -0.09, 'ppd': 5.2} |
365 | 373 | .. code-block:: python |
|
366 | 374 | ||
367 | 375 | >>> from pythermalcomfort.models import pmv |
|
376 | + | >>> from pythermalcomfort.psychrometrics import v_relative |
|
368 | 377 | >>> # calculate relative air velocity |
|
369 | - | >>> vr = v_relative(v=0.1, met=1.2) |
|
378 | + | >>> v_r = v_relative(v=0.1, met=1.2) |
|
370 | 379 | >>> # as you can see the relative air velocity is 0.16 m/s which is |
|
371 | 380 | significantly higher than v |
|
372 | - | >>> results = pmv(tdb=25, tr=25, vr=vr, rh=50, met=1.2, clo=0.5) |
|
381 | + | >>> results = pmv(tdb=25, tr=25, vr=v_r, rh=50, met=1.2, clo=0.5) |
|
373 | 382 | >>> print(results) |
|
374 | 383 | -0.09 |
|
375 | 384 | """ |
511 | 520 | h_cc = max(h_cc, h_fc) |
|
512 | 521 | ||
513 | 522 | c_hr = 4.7 # linearized radiative heat transfer coefficient |
|
514 | - | h_t = c_hr + h_cc # sum of convective and radiant heat transfer coefficient W/(m2*K) |
|
523 | + | h_t = ( |
|
524 | + | c_hr + h_cc |
|
525 | + | ) # sum of convective and radiant heat transfer coefficient W/(m2*K) |
|
515 | 526 | r_a = 1.0 / (f_a_cl * h_t) # resistance of air layer to dry heat |
|
516 | 527 | t_op = (c_hr * tr + h_cc * tdb) / h_t # operative temperature |
|
517 | 528 |
520 | 531 | p_wet = 0 |
|
521 | 532 | _set = 0 |
|
522 | 533 | ||
523 | - | for i in range(length_time_simulation): |
|
534 | + | n_simulation = 0 |
|
535 | + | ||
536 | + | while n_simulation < length_time_simulation: |
|
537 | + | ||
538 | + | n_simulation += 1 |
|
524 | 539 | ||
525 | 540 | iteration_limit = 150 |
|
526 | 541 | # t_cl temperature of the outer surface of clothing |
546 | 561 | dry = (temp_skin - t_op) / (r_a + r_clo) # total sensible heat loss, W |
|
547 | 562 | # h_fcs rate of energy transport between core and skin, W |
|
548 | 563 | h_fcs = (temp_core - temp_skin) * (5.28 + 1.163 * skin_blood_flow) |
|
549 | - | q_res = 0.0023 * m * (44.0 - vapor_pressure) # latent heat loss due to respiration |
|
550 | - | c_res = 0.0014 * m * (34.0 - tdb) # rate of convective heat loss from respiration, W/m2 |
|
564 | + | q_res = ( |
|
565 | + | 0.0023 * m * (44.0 - vapor_pressure) |
|
566 | + | ) # latent heat loss due to respiration |
|
567 | + | c_res = ( |
|
568 | + | 0.0014 * m * (34.0 - tdb) |
|
569 | + | ) # rate of convective heat loss from respiration, W/m2 |
|
551 | 570 | # todo maybe the iteration should stop when the following two terms are 0 |
|
552 | 571 | s_core = m - h_fcs - q_res - c_res - wme # rate of energy storage in the core |
|
553 | 572 | s_skin = h_fcs - dry - e_sk # rate of energy storage in the skin |
|
554 | 573 | TCSK = 0.97 * alfa * body_weight |
|
555 | 574 | TCCR = 0.97 * (1 - alfa) * body_weight |
|
556 | - | d_t_sk = (s_skin * body_surface_area) / (TCSK * 60.0) # rate of change skin temperature °C per minute |
|
557 | - | d_t_cr = s_core * body_surface_area / (TCCR * 60.0) # rate of change core temperature °C per minute |
|
575 | + | d_t_sk = (s_skin * body_surface_area) / ( |
|
576 | + | TCSK * 60.0 |
|
577 | + | ) # rate of change skin temperature °C per minute |
|
578 | + | d_t_cr = ( |
|
579 | + | s_core * body_surface_area / (TCCR * 60.0) |
|
580 | + | ) # rate of change core temperature °C per minute |
|
558 | 581 | temp_skin = temp_skin + d_t_sk |
|
559 | 582 | temp_core = temp_core + d_t_cr |
|
560 | 583 | t_body = alfa * temp_skin + (1 - alfa) * temp_core # mean body temperature, °C |
1621 | 1644 | ||
1622 | 1645 | def solar_gain( |
|
1623 | 1646 | sol_altitude, |
|
1624 | - | sol_azimuth, |
|
1647 | + | sharp, |
|
1625 | 1648 | sol_radiation_dir, |
|
1626 | 1649 | sol_transmittance, |
|
1627 | 1650 | f_svv, |
1642 | 1665 | ---------- |
|
1643 | 1666 | sol_altitude : float |
|
1644 | 1667 | Solar altitude, degrees from horizontal [deg]. Ranges between 0 and 90. |
|
1645 | - | sol_azimuth : float |
|
1646 | - | Solar azimuth, degrees clockwise from North [deg]. Ranges between 0 and 180. |
|
1668 | + | sharp : float |
|
1669 | + | Solar horizontal angle relative to the front of the person (SHARP) [deg]. |
|
1670 | + | Ranges between 0 and 180 and is symmetrical on either side. Zero (0) degrees |
|
1671 | + | represents direct-beam radiation from the front, 90 degrees represents |
|
1672 | + | direct-beam radiation from the side, and 180 degrees rep- resent direct-beam |
|
1673 | + | radiation from the back. SHARP is the angle between the sun and the person |
|
1674 | + | only. Orientation relative to compass or to room is not included in SHARP. |
|
1647 | 1675 | posture : str |
|
1648 | 1676 | Default 'seated' list of available options 'standing', 'supine' or 'seated' |
|
1649 | 1677 | sol_radiation_dir : float |
1660 | 1688 | shall be calculated using National Fenestration Rating Council approved |
|
1661 | 1689 | software or Lawrence Berkeley National Lab Complex Glazing Database. |
|
1662 | 1690 | f_svv : float |
|
1663 | - | Fraction of sky vault exposed to body, ranges from 0 to 1. |
|
1691 | + | Fraction of sky-vault view fraction exposed to body, ranges from 0 to 1. |
|
1692 | + | It can be calculate using the function |
|
1693 | + | :py:meth:`pythermalcomfort.psychrometrics.f_svv`. |
|
1664 | 1694 | f_bes : float |
|
1665 | 1695 | Fraction of the possible body surface exposed to sun, ranges from 0 to 1. |
|
1666 | 1696 | See Table C2-2 and equation C-7 ASHRAE 55 2017 [1]_. |
1692 | 1722 | .. code-block:: python |
|
1693 | 1723 | ||
1694 | 1724 | >>> from pythermalcomfort.models import solar_gain |
|
1695 | - | >>> results = solar_gain(sol_altitude=0, sol_azimuth=120, |
|
1725 | + | >>> results = solar_gain(sol_altitude=0, sharp=120, |
|
1696 | 1726 | sol_radiation_dir=800, sol_transmittance=0.5, f_svv=0.5, f_bes=0.5, |
|
1697 | 1727 | asw=0.7, posture='seated') |
|
1698 | 1728 | >>> print(results) |
1748 | 1778 | ||
1749 | 1779 | if posture == "supine": |
|
1750 | 1780 | alt_temp = sol_altitude |
|
1751 | - | sol_altitude = abs(90 - sol_azimuth) |
|
1752 | - | sol_azimuth = alt_temp |
|
1781 | + | sol_altitude = abs(90 - sharp) |
|
1782 | + | sharp = alt_temp |
|
1753 | 1783 | ||
1754 | 1784 | alt_range = [0, 15, 30, 45, 60, 75, 90] |
|
1755 | 1785 | az_range = [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180] |
|
1756 | 1786 | alt_i = find_span(alt_range, sol_altitude) |
|
1757 | - | az_i = find_span(az_range, sol_azimuth) |
|
1787 | + | az_i = find_span(az_range, sharp) |
|
1758 | 1788 | fp11 = fp_table[az_i][alt_i] |
|
1759 | 1789 | fp12 = fp_table[az_i][alt_i + 1] |
|
1760 | 1790 | fp21 = fp_table[az_i + 1][alt_i] |
1763 | 1793 | az2 = az_range[az_i + 1] |
|
1764 | 1794 | alt1 = alt_range[alt_i] |
|
1765 | 1795 | alt2 = alt_range[alt_i + 1] |
|
1766 | - | fp = fp11 * (az2 - sol_azimuth) * (alt2 - sol_altitude) |
|
1767 | - | fp += fp21 * (sol_azimuth - az1) * (alt2 - sol_altitude) |
|
1768 | - | fp += fp12 * (az2 - sol_azimuth) * (sol_altitude - alt1) |
|
1769 | - | fp += fp22 * (sol_azimuth - az1) * (sol_altitude - alt1) |
|
1796 | + | fp = fp11 * (az2 - sharp) * (alt2 - sol_altitude) |
|
1797 | + | fp += fp21 * (sharp - az1) * (alt2 - sol_altitude) |
|
1798 | + | fp += fp12 * (az2 - sharp) * (sol_altitude - alt1) |
|
1799 | + | fp += fp22 * (sharp - az1) * (sol_altitude - alt1) |
|
1770 | 1800 | fp /= (az2 - az1) * (alt2 - alt1) |
|
1771 | 1801 | ||
1772 | 1802 | f_eff = 0.725 |
9 | 9 | r_air = 287.055 |
|
10 | 10 | ||
11 | 11 | ||
12 | + | def f_svv(w, h, d): |
|
13 | + | """ Calculates the sky-vault view fraction |
|
14 | + | ||
15 | + | Parameters |
|
16 | + | ---------- |
|
17 | + | w : float |
|
18 | + | width of the window, [m] |
|
19 | + | h : float |
|
20 | + | height of the window, [m] |
|
21 | + | d : float |
|
22 | + | distance between the occupant and the window, [m] |
|
23 | + | ||
24 | + | Returns |
|
25 | + | ------- |
|
26 | + | f_svv : float |
|
27 | + | sky-vault view fraction ranges between 0 and 1 |
|
28 | + | """ |
|
29 | + | ||
30 | + | return ( |
|
31 | + | math.degrees(math.atan(h / (2 * d))) |
|
32 | + | * math.degrees(math.atan(w / (2 * d))) |
|
33 | + | / 16200 |
|
34 | + | ) |
|
35 | + | ||
36 | + | ||
12 | 37 | def p_sat_torr(tdb): |
|
13 | 38 | """ Estimates the saturation vapor pressure in [torr] |
|
14 | 39 |
74 | 99 | raise ValueError( |
|
75 | 100 | "PMV calculations can only be performed in compliance with ISO or ASHRAE " |
|
76 | 101 | "Standards" |
|
77 | - | ) |
|
102 | + | ) |
|
78 | 103 | ||
79 | 104 | if 1.2 < met < 2: |
|
80 | 105 | return round(clo * (0.6 + 0.4 / met), 3) |
240 | 265 | + c2 |
|
241 | 266 | + ta_k * (c3 + ta_k * (c4 + ta_k * (c5 + c6 * ta_k))) |
|
242 | 267 | + c7 * math.log(ta_k) |
|
243 | - | ) |
|
268 | + | ) |
|
244 | 269 | else: |
|
245 | 270 | pascals = math.exp( |
|
246 | 271 | c8 / ta_k |
|
247 | 272 | + c9 |
|
248 | 273 | + ta_k * (c10 + ta_k * (c11 + ta_k * c12)) |
|
249 | 274 | + c13 * math.log(ta_k) |
|
250 | - | ) |
|
275 | + | ) |
|
251 | 276 | ||
252 | 277 | return round(pascals, 1) |
|
253 | 278 |
314 | 339 | + 0.00391838 * rh ** (3 / 2) * math.atan(0.023101 * rh) |
|
315 | 340 | - 4.686035, |
|
316 | 341 | 1, |
|
317 | - | ) |
|
342 | + | ) |
|
318 | 343 | return twb |
|
319 | 344 | ||
320 | 345 |
336 | 361 | ||
337 | 362 | c = 257.14 |
|
338 | 363 | b = 18.678 |
|
339 | - | a = 6.1121 |
|
340 | 364 | d = 234.5 |
|
341 | 365 | ||
342 | 366 | gamma_m = math.log(rh / 100 * math.exp((b - tdb / d) * (tdb / (c + tdb)))) |
2 | 2 | from pythermalcomfort.models import solar_gain, pmv_ppd, set_tmp, cooling_effect, \ |
|
3 | 3 | adaptive_ashrae, clo_tout, vertical_tmp_grad_ppd, utci, pmv, ankle_draft |
|
4 | 4 | from pythermalcomfort.psychrometrics import t_dp, t_wb, enthalpy, psy_ta_rh, \ |
|
5 | - | running_mean_outdoor_temperature, units_converter, p_sat, clo_dynamic, t_mrt |
|
5 | + | running_mean_outdoor_temperature, units_converter, p_sat, clo_dynamic, t_mrt, f_svv |
|
6 | 6 | ||
7 | 7 | data_test_set = [ |
|
8 | 8 | {'tdb': 25, 'tr': 25, 'v': 0.15, 'rh': 10, 'met': 1, 'clo': 0.5, 'set': 23.3}, |
107 | 107 | } |
|
108 | 108 | ||
109 | 109 | ||
110 | + | def test_f_svv(): |
|
111 | + | assert round(f_svv(30, 10, 3.3), 2) == 0.27 |
|
112 | + | assert round(f_svv(150, 10, 3.3), 2) == 0.31 |
|
113 | + | assert round(f_svv(30, 6, 3.3), 2) == 0.20 |
|
114 | + | assert round(f_svv(150, 6, 3.3), 2) == 0.23 |
|
115 | + | assert round(f_svv(30, 10, 6), 2) == 0.17 |
|
116 | + | assert round(f_svv(150, 10, 6), 2) == 0.21 |
|
117 | + | assert round(f_svv(30, 6, 6), 2) == 0.11 |
|
118 | + | assert round(f_svv(150, 6, 6), 2) == 0.14 |
|
119 | + | assert round(f_svv(6, 9, 3.3), 2) == 0.14 |
|
120 | + | assert round(f_svv(6, 6, 3.3), 2) == 0.11 |
|
121 | + | assert round(f_svv(6, 6, 6), 2) == 0.04 |
|
122 | + | assert round(f_svv(4, 4, 3.3), 2) == 0.06 |
|
123 | + | assert round(f_svv(4, 4, 6), 2) == 0.02 |
|
124 | + | ||
125 | + | ||
110 | 126 | def test_t_dp(): |
|
111 | 127 | assert t_dp(31.6, 59.6) == 22.6 |
|
112 | 128 | assert t_dp(29.3, 75.4) == 24.3 |
129 | 145 | ||
130 | 146 | def test_solar_gain(): |
|
131 | 147 | for ix in range(0, len(data_test_erf['alt'])): |
|
132 | - | assert (solar_gain(sol_altitude=data_test_erf['alt'][ix], sol_azimuth=data_test_erf['sharp'][ix], sol_radiation_dir=data_test_erf['I_dir'][ix], sol_transmittance= data_test_erf['t_sol'][ix], |
|
148 | + | assert (solar_gain(sol_altitude=data_test_erf['alt'][ix], sharp=data_test_erf['sharp'][ix], sol_radiation_dir=data_test_erf['I_dir'][ix], sol_transmittance= data_test_erf['t_sol'][ix], |
|
133 | 149 | f_svv=data_test_erf['f_svv'][ix], f_bes=data_test_erf['f_bes'][ix], asw=data_test_erf['asa'][ix], posture=data_test_erf['posture'][ix])['erf']) == data_test_erf['ERF'][ix] |
|
134 | - | assert (solar_gain(sol_altitude=data_test_erf['alt'][ix], sol_azimuth=data_test_erf['sharp'][ix], sol_radiation_dir=data_test_erf['I_dir'][ix], sol_transmittance= data_test_erf['t_sol'][ix], |
|
150 | + | assert (solar_gain(sol_altitude=data_test_erf['alt'][ix], sharp=data_test_erf['sharp'][ix], sol_radiation_dir=data_test_erf['I_dir'][ix], sol_transmittance= data_test_erf['t_sol'][ix], |
|
135 | 151 | f_svv=data_test_erf['f_svv'][ix], f_bes=data_test_erf['f_bes'][ix], asw=data_test_erf['asa'][ix], posture=data_test_erf['posture'][ix])['delta_mrt']) == data_test_erf['t_rsw'][ix] |
|
136 | 152 | ||
137 | 153 |
Files | Coverage |
---|---|
src/pythermalcomfort | -0.07% 48.14% |
tests | 100.00% |
Project Totals (8 files) | 56.46% |
2318581
e311e87
3e8ed49
053bf5e
efb8670
f696857