plan2eplus 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. plan2eplus/__init__.py +2 -0
  2. plan2eplus/airflow_network/airboundary.py +106 -0
  3. plan2eplus/airflow_network/creator.py +21 -0
  4. plan2eplus/airflow_network/logic.py +14 -0
  5. plan2eplus/airflow_network/modifiers.py +42 -0
  6. plan2eplus/analysis/analysis_air_boundary.py +75 -0
  7. plan2eplus/analysis/cp_eq.py +22 -0
  8. plan2eplus/analysis/dataframes.py +99 -0
  9. plan2eplus/analysis/dataframes2.py +49 -0
  10. plan2eplus/analysis/ep_wind_cp.cpp +41 -0
  11. plan2eplus/analysis/helpers.py +80 -0
  12. plan2eplus/analysis/materials_compare.py +47 -0
  13. plan2eplus/analysis/plan_details.py +31 -0
  14. plan2eplus/analysis/plot_helpers.py +89 -0
  15. plan2eplus/analysis/plot_subsurfaces.py +193 -0
  16. plan2eplus/analysis/pressure_on_network.py +85 -0
  17. plan2eplus/analysis/result_names.json +25 -0
  18. plan2eplus/analysis/time_plots.py +33 -0
  19. plan2eplus/analysis/volumes.py +70 -0
  20. plan2eplus/analysis2/all_cases_v_time.py +170 -0
  21. plan2eplus/case_edits/__init__.py +0 -0
  22. plan2eplus/case_edits/defaults.py +6 -0
  23. plan2eplus/case_edits/epcase.py +106 -0
  24. plan2eplus/case_edits/ezcase.py +104 -0
  25. plan2eplus/constructions/constructions.py +47 -0
  26. plan2eplus/constructions/materials.py +24 -0
  27. plan2eplus/constructions/organize.py +92 -0
  28. plan2eplus/constructions/unified_constructions.py +49 -0
  29. plan2eplus/experiments/comparisons.py +126 -0
  30. plan2eplus/experiments/dynamic_door_sched.py +141 -0
  31. plan2eplus/experiments/name_splits.py +58 -0
  32. plan2eplus/experiments/retrieve.py +53 -0
  33. plan2eplus/experiments/scatter.py +71 -0
  34. plan2eplus/helpers/dates.py +15 -0
  35. plan2eplus/helpers/ep_geom_helpers.py +69 -0
  36. plan2eplus/helpers/ep_helpers.py +149 -0
  37. plan2eplus/helpers/geometry_interfaces.py +103 -0
  38. plan2eplus/helpers/helpers.py +66 -0
  39. plan2eplus/helpers/output_requests.py +63 -0
  40. plan2eplus/helpers/plot_colors.py +39 -0
  41. plan2eplus/helpers/plots.py +92 -0
  42. plan2eplus/helpers/read_sql.py +34 -0
  43. plan2eplus/helpers/save_details +0 -0
  44. plan2eplus/helpers/variable_interfaces.py +78 -0
  45. plan2eplus/helpers/variables.py +96 -0
  46. plan2eplus/main.py +4 -0
  47. plan2eplus/network/cardinal_positions.py +33 -0
  48. plan2eplus/network/network.py +184 -0
  49. plan2eplus/network/visuals.py +71 -0
  50. plan2eplus/plan/graph_to_subsurfaces.py +111 -0
  51. plan2eplus/plan/helpers.py +23 -0
  52. plan2eplus/plan/interfaces.py +78 -0
  53. plan2eplus/plan/plan_to_eppy.py +30 -0
  54. plan2eplus/setup/data_wrangle.py +163 -0
  55. plan2eplus/setup/data_wrangle2.py +59 -0
  56. plan2eplus/setup/interfaces.py +28 -0
  57. plan2eplus/setup/materials_setup.py +37 -0
  58. plan2eplus/setup/plots.py +36 -0
  59. plan2eplus/setup/setup.py +77 -0
  60. plan2eplus/subsurfaces/constructions.py +20 -0
  61. plan2eplus/subsurfaces/creator.py +86 -0
  62. plan2eplus/subsurfaces/interfaces.py +82 -0
  63. plan2eplus/subsurfaces/logic.py +125 -0
  64. plan2eplus/subsurfaces/placement.py +67 -0
  65. plan2eplus/subsurfaces/visuals.py +26 -0
  66. plan2eplus-0.1.0.dist-info/METADATA +16 -0
  67. plan2eplus-0.1.0.dist-info/RECORD +69 -0
  68. plan2eplus-0.1.0.dist-info/WHEEL +4 -0
  69. plan2eplus-0.1.0.dist-info/entry_points.txt +2 -0
plan2eplus/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ def main() -> None:
2
+ print("Hello from geomeppy!")
@@ -0,0 +1,106 @@
1
+ from pathlib import Path
2
+ from eppy.bunch_subclass import EpBunch
3
+ from geomeppy import IDF
4
+ from helpers.helpers import key_from_value
5
+ from helpers.ep_helpers import find_zone_subsurfaces, get_partner_of_surface, get_surface_by_name, PARTNER
6
+ from plan.helpers import create_room_map, load_data_from_json
7
+ from plan.interfaces import GRAPH, GraphEdgeJSON
8
+ from subsurfaces.logic import PairOnly, find_surface_connecting_two_zones
9
+ from airflow_network.modifiers import add_zone, add_subsurface
10
+
11
+ # TODO see notes on how to make this better..
12
+
13
+ def get_airboundary_wall(airboundary: EpBunch):
14
+ n = airboundary.Name
15
+ remain = n.split(" ")[1:]
16
+ return " ".join(remain)
17
+
18
+ def handle_edge_airboundary(
19
+ e: GraphEdgeJSON,
20
+ room_map: dict[int, str],
21
+ ):
22
+ source, target = e["source"], e["target"]
23
+ return PairOnly(key_from_value(room_map, source), key_from_value(room_map, target))
24
+
25
+
26
+ def get_airboundary_pairs_from_case(path_to_inputs: Path):
27
+ room_map = create_room_map(path_to_inputs)
28
+ graph_data = load_data_from_json(path_to_inputs, GRAPH)
29
+ edges: list[GraphEdgeJSON] = graph_data["links"]
30
+ return [
31
+ handle_edge_airboundary(e, room_map) for e in edges if e["details"]["id"] == 0
32
+ ]
33
+
34
+ def update_air_boundary_constructions(idf: IDF, path_to_inputs: Path):
35
+ ab_pairs = get_airboundary_pairs_from_case(path_to_inputs)
36
+ for pair in ab_pairs:
37
+ surf = find_surface_connecting_two_zones(idf, pair)
38
+ assert surf
39
+
40
+ o = idf.newidfobject("CONSTRUCTION:AIRBOUNDARY")
41
+ o.Name = f"AirBoundary {surf.Name}"
42
+ idf = add_subsurface(idf, surf.Name)
43
+ surf.Construction_Name = o.Name
44
+ partner_surf = get_partner_of_surface(idf, surf)
45
+ assert partner_surf
46
+ partner_surf.Construction_Name = o.Name
47
+
48
+ return idf
49
+
50
+ def get_afn_zones(idf: IDF):
51
+ afn_zones = idf.idfobjects["AIRFLOWNETWORK:MULTIZONE:ZONE"]
52
+ assert afn_zones, "Subsurface AFN zones have not been added"
53
+ return [i.Zone_Name for i in afn_zones]
54
+
55
+
56
+
57
+ def update_afn_for_airboundary_zones(idf: IDF):
58
+ airboundaries =idf.idfobjects["CONSTRUCTION:AIRBOUNDARY"]
59
+ for ab in airboundaries:
60
+ wall = get_surface_by_name(idf, get_airboundary_wall(ab))
61
+ assert wall
62
+ partner_wall = get_partner_of_surface(idf, wall)
63
+ assert partner_wall
64
+
65
+ afn_zone_names = get_afn_zones(idf)
66
+ if wall.Zone_Name not in afn_zone_names:
67
+ print(f"{wall.Zone_Name} not in original AFN. Adding now.. " )
68
+ idf = add_zone(idf, wall.Zone_Name)
69
+
70
+
71
+ afn_zone_names = get_afn_zones(idf)
72
+ if partner_wall.Zone_Name not in afn_zone_names:
73
+ print(f"Partner {partner_wall.Zone_Name} not in original AFN. Adding now.. " )
74
+ idf = add_zone(idf, partner_wall.Zone_Name)
75
+
76
+ return idf
77
+
78
+ def add_missing_zone_surfaces(idf: IDF, zone: str):
79
+ zone_subsurfs = find_zone_subsurfaces(zone, idf.getsubsurfaces())
80
+ afn_surfaces = [i.Surface_Name for i in idf.idfobjects["AIRFLOWNETWORK:MULTIZONE:SURFACE"]]
81
+ for subsurf in zone_subsurfs:
82
+ if subsurf not in afn_surfaces and PARTNER not in subsurf and "Window" in subsurf:
83
+ print(f"Subsurf {subsurf} not in original AFN. Adding now.. " )
84
+ idf = add_subsurface(idf, subsurf)
85
+ return idf
86
+
87
+
88
+ def update_afn_for_missing_zone_subsurfaces(idf: IDF):
89
+ afn_zones = get_afn_zones(idf)
90
+ for zone in afn_zones:
91
+ idf = add_missing_zone_surfaces(idf, zone)
92
+
93
+ return idf
94
+
95
+
96
+ # TODO now have added zones, need to update create zone map based on airboundaries.. and look for
97
+
98
+ def add_air_boundaries(idf: IDF, path_to_inputs: Path):
99
+ idf = update_air_boundary_constructions(idf, path_to_inputs)
100
+ idf = update_afn_for_airboundary_zones(idf)
101
+ idf = update_afn_for_missing_zone_subsurfaces(idf)
102
+
103
+ return idf
104
+
105
+
106
+
@@ -0,0 +1,21 @@
1
+ from airflow_network.logic import get_afn_zones_and_subsurfaces
2
+ from airflow_network.modifiers import add_simulation_control, add_subsurface, add_zone
3
+
4
+
5
+ from geomeppy import IDF
6
+ from copy import deepcopy
7
+
8
+
9
+ def add_airflownetwork_to_case(_idf: IDF):
10
+ idf = deepcopy(_idf)
11
+ zones, subsurfaces = get_afn_zones_and_subsurfaces(idf)
12
+
13
+ idf = add_simulation_control(idf)
14
+
15
+ for zone in zones:
16
+ idf = add_zone(idf, zone)
17
+
18
+ for subsurface in subsurfaces:
19
+ idf = add_subsurface(idf, subsurface)
20
+
21
+ return idf
@@ -0,0 +1,14 @@
1
+ from geomeppy import IDF
2
+ from helpers.helpers import set_difference, list_all_dict_values
3
+ from helpers.ep_helpers import create_zone_map_without_partners
4
+
5
+
6
+ def get_afn_zones_and_subsurfaces(idf: IDF):
7
+ # TODO make this more expressive, so know from function name it is mapping subsurfaces to zones..
8
+ zone_map = create_zone_map_without_partners(idf)
9
+ filtered_zone_map = {k: v for k, v in zone_map.items() if len(v) < 2}
10
+ afn_zones = set_difference(zone_map.keys(), filtered_zone_map.keys())
11
+ afn_subsurfaces = set_difference(
12
+ list_all_dict_values(zone_map), list_all_dict_values(filtered_zone_map)
13
+ )
14
+ return afn_zones, afn_subsurfaces
@@ -0,0 +1,42 @@
1
+ from copy import deepcopy
2
+ from geomeppy import IDF
3
+
4
+ def add_simulation_control(idf: IDF):
5
+ sim_control = idf.newidfobject(
6
+ "AirflowNetwork:SimulationControl".upper()
7
+ )
8
+ sim_control.Name = "AFN_SIM_CONTROL"
9
+ sim_control.AirflowNetwork_Control = "MultizoneWithoutDistribution"
10
+ return idf
11
+
12
+
13
+ def add_zone(idf: IDF, zone_name:str):
14
+ zone = idf.newidfobject(
15
+ "AirflowNetwork:MultiZone:Zone".upper()
16
+ )
17
+ zone.Ventilation_Control_Mode = "Constant"
18
+ zone.Zone_Name = zone_name
19
+ return idf
20
+
21
+ def create_simple_opening(idf: IDF, subsurface_name:str):
22
+ opening = idf.newidfobject(
23
+ "AirflowNetwork:MultiZone:Component:SimpleOpening".upper()
24
+ )
25
+ opening.Name = f"{subsurface_name} SimpleOpening"
26
+ # taken from defaults
27
+ opening.Discharge_Coefficient = 1
28
+ opening.Air_Mass_Flow_Coefficient_When_Opening_is_Closed = 0.001
29
+ opening.Minimum_Density_Difference_for_TwoWay_Flow = 0.0001
30
+ return idf, opening
31
+
32
+ def add_subsurface(idf: IDF, subsurface_name:str):
33
+ afn_surface = idf.newidfobject(
34
+ "AirflowNetwork:MultiZone:Surface".upper()
35
+ )
36
+ afn_surface.Surface_Name = subsurface_name
37
+
38
+ idf, opening = create_simple_opening(idf, subsurface_name)
39
+ afn_surface.Leakage_Component_Name = opening.Name
40
+ return idf
41
+
42
+
@@ -0,0 +1,75 @@
1
+ from helpers.variable_interfaces import all_variables
2
+ from setup.data_wrangle import create_dataframe_for_many_cases, join_any_data
3
+ from setup.interfaces import CaseData
4
+ from setup.setup import retrieve_case_data
5
+ import polars as pl
6
+
7
+
8
+ def get_qois():
9
+ qoi1 = all_variables.afn.linkage["flow12"]
10
+ qoi12 = all_variables.afn.linkage["flow21"]
11
+ qoi2 = all_variables.afn.zone["ach"]
12
+ qoi3 = all_variables.afn.zone["vent_vol"]
13
+ qoi4 = all_variables.zone.temp["zone_mean_air_temp"]
14
+
15
+ return qoi1, qoi12, qoi2, qoi3, qoi4
16
+
17
+
18
+ def get_df(case_data: CaseData):
19
+ qois = get_qois()
20
+ df = create_dataframe_for_many_cases([case_data], qois[0])
21
+ return join_any_data(df, [case_data], qois[1])
22
+
23
+
24
+ def get_zone_df(case_data: CaseData):
25
+ _, _, ach, vent_vol , *_= get_qois()
26
+ df = create_dataframe_for_many_cases([case_data], ach)
27
+ return join_any_data(df, [case_data], vent_vol)
28
+
29
+
30
+ def get_airboundary_case():
31
+ inputs_dir = "case_bol_5"
32
+ outputs_dir = "tests/test23_airwall"
33
+ return retrieve_case_data(inputs_dir, outputs_dir, "airwall")
34
+
35
+
36
+ def get_airboundary_with_surf_case():
37
+ inputs_dir = "case_bol_5"
38
+ outputs_dir = "tests/test25_airwall"
39
+ return retrieve_case_data(inputs_dir, outputs_dir, "airwall_surf")
40
+
41
+
42
+ def get_no_door_case():
43
+ inputs_dir = "case_bol_5"
44
+ outputs_dir = "tests/test24_no_door"
45
+ return retrieve_case_data(inputs_dir, outputs_dir, "no_door")
46
+
47
+
48
+ def get_normal_door_case():
49
+ inputs_dir = "case_bol_5"
50
+ outputs_dir = "oct_h4h_plans/case_bol_5"
51
+ return retrieve_case_data(inputs_dir, outputs_dir, "just_door")
52
+
53
+
54
+ def create_data(df_select):
55
+ dfs = [
56
+ df_select(i)
57
+ for i in [
58
+ get_no_door_case(),
59
+ get_airboundary_case(),
60
+ get_airboundary_with_surf_case(),
61
+ get_normal_door_case(),
62
+ ]
63
+ ]
64
+ return pl.concat(dfs, how="vertical")
65
+
66
+
67
+ def get_df_many(case_data: list[CaseData]):
68
+ qois = get_qois()
69
+ df = create_dataframe_for_many_cases(case_data, qois[0])
70
+ return join_any_data(df, case_data, qois[1])
71
+
72
+ def get_zone_df_many(case_data: list[CaseData]):
73
+ _, _, ach, vent_vol , temp = get_qois()
74
+ df = create_dataframe_for_many_cases(case_data, temp)
75
+ return join_any_data(df, case_data, ach)
@@ -0,0 +1,22 @@
1
+ from math import log, sin, cos, pow, radians
2
+
3
+ # TO DO, read this paper, how did they fit this?
4
+ # inc_rad => indident angle in radians, ~ angle between wind direction and and outward normal of wall under consideration..
5
+ # side_ratio_fac => log(width of facade / width of adjacent facade)
6
+ def calc_cp(inc_angle, side_ratio_fac=log(1)):
7
+ # TODO check that side_ratio_fac falls within bounds..
8
+ inc_rad = radians(inc_angle)
9
+ cos_inc_rad_over_2 = cos(inc_rad / 2)
10
+ val = 0.6 * log(
11
+ 1.248
12
+ - 0.703 * sin(inc_rad / 2.0)
13
+ - 1.175 * pow(sin(inc_rad), 2)
14
+ + 0.131 * pow(sin(2.0 * inc_rad * side_ratio_fac), 3)
15
+ + 0.769 * cos_inc_rad_over_2
16
+ + 0.07 * pow((side_ratio_fac * sin(inc_rad / 2.0)), 2)
17
+ + 0.717 * pow(cos_inc_rad_over_2, 2)
18
+ )
19
+ return val
20
+
21
+ # side ratios are capped at a certain value..
22
+ # how does Cp become pressure?
@@ -0,0 +1,99 @@
1
+ import polars as pl
2
+ from analysis.helpers import (
3
+ extract_times,
4
+ link_dfs_for_qois,
5
+ map_linkage_names_to_G,
6
+ map_zone_names,
7
+ )
8
+ from setup.interfaces import CaseData
9
+ from helpers.variable_interfaces import all_variables
10
+ from setup.data_wrangle import (
11
+ create_dataframe_for_many_cases,
12
+ join_any_data,
13
+ create_dataframe_for_case,
14
+ )
15
+
16
+
17
+ def create_zone_vol_df_many(case_data: list[CaseData]):
18
+ vent_vol = all_variables.afn.zone["vent_vol"]
19
+ mix_vol = all_variables.afn.zone["mix_vol"]
20
+ temp = all_variables.zone.temp["zone_mean_air_temp"]
21
+
22
+ df = create_dataframe_for_many_cases(case_data, vent_vol)
23
+ df2 = join_any_data(df, case_data, mix_vol)
24
+ return join_any_data(df2, case_data, temp, 1)
25
+
26
+
27
+ def create_zone_rate_df(case: CaseData):
28
+ zq = all_variables.afn.zone
29
+ qois = [
30
+ zq["vent_heat_gain"],
31
+ zq["vent_heat_loss"],
32
+ zq["mix_heat_gain"],
33
+ zq["mix_heat_loss"],
34
+ ]
35
+
36
+ dfs = [create_dataframe_for_case(case.case_name, case.sql, qoi) for qoi in qois]
37
+ return pl.concat(dfs, how="vertical")
38
+
39
+
40
+ def create_site_df(case: CaseData):
41
+ sq = all_variables.site
42
+ qois = [
43
+ sq.temp["db"],
44
+ sq.solar["direct_rad"],
45
+ sq.wind["speed"],
46
+ sq.wind["direction"],
47
+ ]
48
+
49
+ dfs = [create_dataframe_for_case(case.case_name, case.sql, qoi) for qoi in qois]
50
+ return pl.concat(dfs, how="vertical")
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+ ### above are df helpers.. ^
61
+
62
+
63
+ def create_pressure_df(case: CaseData):
64
+ av = all_variables.afn
65
+ qois = [av.node["total_pressure"], av.node["wind_pressure"], av.node["temp"]]
66
+
67
+ df = link_dfs_for_qois(case, qois)
68
+ df = extract_times(df)
69
+ df = map_zone_names(case.path_to_input, df)
70
+ df = df.with_columns(
71
+ is_ext=pl.when(pl.col("room_names").str.contains("ExtNode"))
72
+ .then(True)
73
+ .otherwise(False)
74
+ )
75
+ return df
76
+
77
+
78
+ def create_linkage_df(case: CaseData) -> pl.DataFrame:
79
+ av = all_variables.afn
80
+ qois = [
81
+ av.linkage["flow12"],
82
+ av.linkage["flow21"],
83
+ ]
84
+ df = create_dataframe_for_case(case.case_name, case.sql, qois[0])
85
+ df = join_any_data(df, [case], qois[1])
86
+ df = df.with_columns(net_linkage=pl.col("values") - pl.col("values_0"))
87
+
88
+ df = map_linkage_names_to_G(case.idf, case.path_to_input, df)
89
+
90
+ def flip_edge(e):
91
+ return [e[1], e[0]]
92
+
93
+ flipped_edges = [
94
+ flip_edge(e) if v < 0 else e
95
+ for e, v in zip(df["room_pairs"], df["net_linkage"])
96
+ ]
97
+ df = df.hstack([pl.Series("directed_pairs", flipped_edges)])
98
+ # )
99
+ return df
@@ -0,0 +1,49 @@
1
+ import polars as pl
2
+ import polars.selectors as cs
3
+ from setup.interfaces import CaseData
4
+ from setup.materials_setup import retrieve_cases
5
+ from setup.data_wrangle2 import create_wide_dataframe_for_many_qois, add_site_qois_wide
6
+ from analysis.helpers import map_zone_names, extract_times, map_linkage_names_to_G
7
+ from helpers.variable_interfaces import all_variables as vars
8
+
9
+
10
+ def get_redwood_case():
11
+ cases = retrieve_cases()
12
+ medium_cases = [i for i in cases if "Medium" in i.case_name]
13
+ [case] = [i for i in medium_cases if "red" in i.case_name]
14
+ return case
15
+
16
+
17
+ # # TODO zone temp data..
18
+ # def get_col_regex(name):
19
+ # return pl.col(f"^{name}.*$")
20
+
21
+
22
+ def create_linkage_df(case: CaseData) -> pl.DataFrame:
23
+ av = vars.afn
24
+ qois = [
25
+ av.linkage["flow12"],
26
+ av.linkage["flow21"],
27
+ ]
28
+ df = create_wide_dataframe_for_many_qois(case, qois)
29
+ df = df.with_columns(net_linkage=(cs.contains(qois[0]) - cs.contains(qois[1]))) # TODO check this calculation may be wrong
30
+
31
+ df = map_linkage_names_to_G(case.idf, case.path_to_input, df)
32
+
33
+ def flip_edge(e):
34
+ return [e[1], e[0]]
35
+
36
+ directed_pairs = [
37
+ flip_edge(e) if v < 0 else e
38
+ for e, v in zip(df["room_pairs"], df["net_linkage"])
39
+ ]
40
+ df = df.hstack([pl.Series("directed_pairs", directed_pairs)])
41
+ return df
42
+
43
+
44
+ def get_external_node_df(case: CaseData):
45
+ df = create_wide_dataframe_for_many_qois(case, [vars.afn.node["wind_pressure"]])
46
+ return add_site_qois_wide(df, case, [vars.site.wind["speed"], vars.site.wind["direction"]])
47
+
48
+
49
+ # def create_vol_df_for_many_cases():
@@ -0,0 +1,41 @@
1
+ // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2
+ int FacadeNum; // Facade number
3
+ int ExtNum; // External number
4
+ int AFNZnNum; // Zone number
5
+ Real64 SideRatio; // For vertical facades, width of facade / width of adjacent facade
6
+ Real64 SR; // SideRatio restricted to 0.25 to 4.0 range
7
+ Real64 SideRatioFac; // LOG(SideRatio)
8
+ Real64 IncRad; // IncAng in radians
9
+ int IAng; // Incidence angle index; used in interpolation
10
+ Real64 DelAng; // Incidence angle difference; used in interpolation
11
+ Real64 WtAng; // Incidence angle weighting factor; used in interpolation
12
+ int ISR; // Side ratio index, for interpolation
13
+ Real64 WtSR; // Side ratio weighting factor; used in interpolation
14
+ int SurfNum; // Surface number
15
+ int SurfDatNum; // Surface data number
16
+ Real64 SurfAng; // Azimuth angle of surface normal (degrees clockwise from North)
17
+ int FacadeNumThisSurf; // Facade number for a particular surface
18
+ Real64 AngDiff; // Angle difference between wind and surface direction (deg)
19
+ Real64 AngDiffMin; // Minimum angle difference between wind and surface direction (deg)
20
+ std::vector<int> curveIndex = {0, 0, 0, 0, 0};
21
+
22
+
23
+
24
+ std::vector<Real64> vals(13);
25
+ for (int windDirNum = 1; windDirNum <= 12; ++windDirNum) {
26
+ Real64 WindAng = (windDirNum - 1) * 30.0;
27
+ IncAng = std::abs(WindAng - FacadeAng(FacadeNum));
28
+ if (IncAng > 180.0) IncAng = 360.0 - IncAng;
29
+ IAng = int(IncAng / 30.0) + 1;
30
+ DelAng = mod(IncAng, 30.0);
31
+ WtAng = 1.0 - DelAng / 30.0;
32
+
33
+ // Wind-pressure coefficients for vertical facades, low-rise building
34
+
35
+ if (Util::SameString(simulation_control.BldgType, "LowRise") && FacadeNum <= 4) {
36
+ IncRad = IncAng * Constant::DegToRadians;
37
+ Real64 const cos_IncRad_over_2(std::cos(IncRad / 2.0));
38
+ vals[windDirNum - 1] = 0.6 * std::log(1.248 - 0.703 * std::sin(IncRad / 2.0) - 1.175 * pow_2(std::sin(IncRad)) +
39
+ 0.131 * pow_3(std::sin(2.0 * IncRad * SideRatioFac)) + 0.769 * cos_IncRad_over_2 +
40
+ 0.07 * pow_2(SideRatioFac * std::sin(IncRad / 2.0)) + 0.717 * pow_2(cos_IncRad_over_2));
41
+ }
@@ -0,0 +1,80 @@
1
+ from pathlib import Path
2
+ from geomeppy import IDF
3
+ import polars as pl
4
+ from helpers.ep_helpers import get_zone_num
5
+ from sklearn.preprocessing import MinMaxScaler
6
+ import numpy as np
7
+ from helpers.geometry_interfaces import Domain
8
+ from network.network import create_base_graph, get_node_partners
9
+ from plan.helpers import create_room_map
10
+ from setup.data_wrangle import create_dataframe_for_case
11
+ from setup.interfaces import CaseData
12
+
13
+
14
+ def get_domains_lim(zone_domains: list[Domain], PAD_BASE = 1.4):
15
+ PAD = PAD_BASE * 1.1
16
+ min_x = min([i.width.min for i in zone_domains]) - PAD
17
+ max_x = max([i.width.max for i in zone_domains]) + PAD
18
+ min_y = min([i.height.min for i in zone_domains]) - PAD
19
+ max_y = max([i.height.max for i in zone_domains]) + PAD
20
+ return (min_x, max_x), (min_y, max_y)
21
+
22
+
23
+ def get_min_max(medians: pl.DataFrame, col=None):
24
+ if not col:
25
+ numeric_values = medians.select(pl.selectors.numeric())
26
+ min_val = numeric_values.min_horizontal().min()
27
+ max_val = numeric_values.max_horizontal().max()
28
+
29
+ else:
30
+ series = medians[col]
31
+ return series.min(), series.max()
32
+
33
+ return min_val, max_val
34
+
35
+
36
+ def true_min_max(min_max_pairs: list[tuple[float, float]]):
37
+ min_val = min([m[0] for m in min_max_pairs])
38
+ max_val = max([m[1] for m in min_max_pairs])
39
+ return min_val, max_val
40
+
41
+
42
+ def convert_zone_space_name(room_map: dict[int, str], name):
43
+ try:
44
+ ix = get_zone_num(name)
45
+ room_name = room_map[ix]
46
+ return f"{ix}-{room_name}"
47
+ except:
48
+ return name
49
+
50
+
51
+ def normalize_column(df: pl.DataFrame, col: str, range=(1, 3)):
52
+ vals = np.absolute(df[col].to_numpy().reshape(-1, 1))
53
+ scaler = MinMaxScaler(feature_range=range)
54
+ scaler.fit(vals)
55
+ return scaler.transform(vals).reshape(1, -1)[0]
56
+
57
+
58
+ def link_dfs_for_qois(case: CaseData, qois: list[str]):
59
+ df = [create_dataframe_for_case(case.case_name, case.sql, qoi) for qoi in qois]
60
+ return pl.concat(df, how="vertical")
61
+
62
+
63
+ def map_zone_names(path_to_input: Path, df: pl.DataFrame):
64
+ room_map = create_room_map(path_to_input)
65
+ fx = lambda name: convert_zone_space_name(room_map, name)
66
+ return df.with_columns(
67
+ room_names=pl.col("space_names").map_elements(fx, return_dtype=pl.String),
68
+ )
69
+
70
+
71
+ def map_linkage_names_to_G(idf: IDF, path_to_input: Path, df: pl.DataFrame):
72
+ G, _ = create_base_graph(idf, path_to_input)
73
+ fx = lambda surf_name: get_node_partners(idf, G, surf_name)
74
+ return df.with_columns(
75
+ room_pairs=pl.col("space_names").map_elements(fx, return_dtype=pl.Object)
76
+ )
77
+
78
+
79
+ def extract_times(df: pl.DataFrame):
80
+ return df.with_columns(time=pl.col("datetimes").dt.to_string("%H:%M"))
@@ -0,0 +1,47 @@
1
+ from pathlib import Path
2
+ import seaborn as sns
3
+ import seaborn.objects as so
4
+ import polars as pl
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ from analysis.volumes import aggregate_and_compare
9
+ from setup.data_wrangle import get_plot_labels
10
+
11
+ # from setup.materials_setup import *
12
+ from analysis.dataframes import create_zone_vol_df_many
13
+ from setup.interfaces import CaseData
14
+ from setup.materials_setup import retrieve_cases
15
+
16
+
17
+ def get_save_details():
18
+ FOLDER = "materials_compare"
19
+ return Path.cwd() / "figures" / FOLDER
20
+
21
+
22
+ def init_df():
23
+ cases = retrieve_cases()
24
+ df_vol = create_zone_vol_df_many(cases)
25
+ sc = cases[0]
26
+ return df_vol, sc
27
+
28
+
29
+ def aggregate_and_compare_materials(df_vol):
30
+ figures_root = get_save_details()
31
+ df_agg = aggregate_and_compare(df_vol)
32
+ df_agg2 = df_agg.with_columns(
33
+ material_type=pl.when(pl.col("case_names").str.contains("Light"))
34
+ .then(pl.lit("Light"))
35
+ .when(pl.col("case_names").str.contains("Medium"))
36
+ .then(pl.lit("Medium"))
37
+ .otherwise(pl.lit("Heavy")),
38
+ case_type = pl.when(pl.col("case_names").str.contains("amb"))
39
+ .then(pl.lit("amb"))
40
+ .when(pl.col("case_names").str.contains("bol"))
41
+ .then(pl.lit("bol"))
42
+ .otherwise(pl.lit("red")),
43
+ )
44
+ g = (so.Plot(df_agg2, x="temp", y="combined_vent", color="case_type", marker="material_type" ).add(so.Dot(pointsize=15)).scale(color="flare").plot().save(figures_root / f"vent_v_temp")) # type: ignore
45
+ g.show()
46
+ return df_agg2, g
47
+
@@ -0,0 +1,31 @@
1
+
2
+ from case_edits.epcase import EneryPlusCaseEditor
3
+ from case_edits.ezcase import get_path_to_inputs, get_path_to_outputs
4
+ from experiments.comparisons import get_input_dir
5
+ from helpers.ep_geom_helpers import get_zone_domains
6
+ from analysis.helpers import get_domains_lim
7
+ from helpers.geometry_interfaces import Range, Domain
8
+ from plan.plan_to_eppy import add_eppy_blocks_to_case
9
+ from setup.setup import get_case_names
10
+
11
+
12
+ output_path = get_path_to_outputs("test/plan_details")
13
+
14
+ def get_input_paths():
15
+ input_dirs = [get_input_dir(i) for i in get_case_names()]
16
+ return [get_path_to_inputs(i) for i in input_dirs]
17
+
18
+ def init_case(input_path):
19
+ case = EneryPlusCaseEditor(output_path)
20
+ case.idf = add_eppy_blocks_to_case(case.idf, input_path)
21
+ return get_zone_domains(case.idf)
22
+
23
+
24
+ def get_plan_area(zone_domains:list[Domain]):
25
+ return sum([z.area for z in zone_domains])
26
+
27
+ def get_plan_aspect_ratio(zone_domains:list[Domain]):
28
+ x_diff, y_diff = get_domains_lim(zone_domains, 0)
29
+ plan_domain = Domain(Range(*x_diff), Range(*y_diff))
30
+ return plan_domain.aspect_ratio
31
+