OpenSimula 0.7.0__tar.gz → 0.8.0__tar.gz

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 (65) hide show
  1. {opensimula-0.7.0 → opensimula-0.8.0}/LICENSE +1 -1
  2. {opensimula-0.7.0 → opensimula-0.8.0}/PKG-INFO +1 -3
  3. {opensimula-0.7.0 → opensimula-0.8.0}/README.md +0 -1
  4. {opensimula-0.7.0 → opensimula-0.8.0}/pyproject.toml +2 -3
  5. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Component.py +10 -5
  6. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Simulation.py +17 -9
  7. opensimula-0.8.0/src/OpenSimula/components/Chiller_heat_pump.py +155 -0
  8. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/File_data.py +7 -3
  9. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/HVAC_MZW_system.py +39 -18
  10. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/HVAC_SZW_system.py +129 -42
  11. opensimula-0.8.0/src/OpenSimula/components/HVAC_water_system.py +314 -0
  12. opensimula-0.8.0/src/OpenSimula/components/Pump.py +50 -0
  13. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Space.py +186 -91
  14. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Water_coil.py +11 -9
  15. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/__init__.py +4 -0
  16. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/visual_3D/Environment_3D.py +29 -4
  17. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/visual_3D/Polygon_3D.py +21 -26
  18. {opensimula-0.7.0/src/opensimula.egg-info → opensimula-0.8.0/src/OpenSimula.egg-info}/PKG-INFO +1 -3
  19. {opensimula-0.7.0/src/opensimula.egg-info → opensimula-0.8.0/src/OpenSimula.egg-info}/SOURCES.txt +46 -0
  20. {opensimula-0.7.0/src/opensimula.egg-info → opensimula-0.8.0/src/OpenSimula.egg-info}/requires.txt +0 -1
  21. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_HVAC_DX_system.py +7 -7
  22. opensimula-0.8.0/test/test_HVAC_FAN_COIL_water_system.py +400 -0
  23. opensimula-0.8.0/test/test_HVAC_water_system_process.py +250 -0
  24. {opensimula-0.7.0 → opensimula-0.8.0}/setup.cfg +0 -0
  25. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Child.py +0 -0
  26. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Iterative_process.py +0 -0
  27. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Message.py +0 -0
  28. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Parameter_container.py +0 -0
  29. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Parameters.py +0 -0
  30. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Project.py +0 -0
  31. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/Variable.py +0 -0
  32. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/__init__.py +0 -0
  33. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Building.py +0 -0
  34. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Building_surface.py +0 -0
  35. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Calculator.py +0 -0
  36. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Construction.py +0 -0
  37. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/DX_unit.py +0 -0
  38. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Day_schedule.py +0 -0
  39. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Fan.py +0 -0
  40. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/File_met.py +0 -0
  41. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Frame.py +0 -0
  42. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Glazing.py +0 -0
  43. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/HVAC_DX_system.py +0 -0
  44. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/HVAC_perfect_system.py +0 -0
  45. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Material.py +0 -0
  46. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Opening.py +0 -0
  47. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Opening_type.py +0 -0
  48. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Solar_surface.py +0 -0
  49. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Space_type.py +0 -0
  50. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Surface.py +0 -0
  51. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Test_component.py +0 -0
  52. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Week_schedule.py +0 -0
  53. {opensimula-0.7.0/src/opensimula → opensimula-0.8.0/src/OpenSimula}/components/Year_schedule.py +0 -0
  54. {opensimula-0.7.0/src/opensimula.egg-info → opensimula-0.8.0/src/OpenSimula.egg-info}/dependency_links.txt +0 -0
  55. {opensimula-0.7.0/src/opensimula.egg-info → opensimula-0.8.0/src/OpenSimula.egg-info}/top_level.txt +0 -0
  56. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Calculator.py +0 -0
  57. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Case_600FF.py +0 -0
  58. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Case_610.py +0 -0
  59. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Construction.py +0 -0
  60. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_File_data.py +0 -0
  61. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_File_met.py +0 -0
  62. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_HVAC_DX_Equipment.py +0 -0
  63. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Iterative_process.py +0 -0
  64. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Project.py +0 -0
  65. {opensimula-0.7.0 → opensimula-0.8.0}/test/test_Schedules.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Juan F. Coronel
3
+ Copyright (c) 2026 Juan F. Coronel
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensimula
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: Component-based time simulation environment in Python
5
5
  Author-email: "Juan F. Coronel" <jfc@us.es>
6
6
  Requires-Python: >=3.12
@@ -18,7 +18,6 @@ Requires-Dist: psychrolib>=2.5.0
18
18
  Requires-Dist: scipy>=1.16.2
19
19
  Requires-Dist: shapely>=2.1.1
20
20
  Requires-Dist: tqdm>=4.67.1
21
- Requires-Dist: triangle>=20250106
22
21
  Requires-Dist: vedo>=2025.5.4
23
22
  Dynamic: license-file
24
23
 
@@ -44,5 +43,4 @@ Component-based time simulation environment in Python
44
43
  - nbformat
45
44
  - openpyxl
46
45
  - tqdm
47
- - triangle
48
46
  - vedo
@@ -20,5 +20,4 @@ Component-based time simulation environment in Python
20
20
  - nbformat
21
21
  - openpyxl
22
22
  - tqdm
23
- - triangle
24
23
  - vedo
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "opensimula"
3
- version = "0.7.0"
3
+ version = "0.8.0"
4
4
  requires-python = ">=3.12"
5
5
  authors = [
6
6
  { name="Juan F. Coronel", email="jfc@us.es" },
@@ -20,8 +20,7 @@ dependencies = [
20
20
  "scipy>=1.16.2",
21
21
  "shapely>=2.1.1",
22
22
  "tqdm>=4.67.1",
23
- "triangle>=20250106",
24
- "vedo>=2025.5.4",
23
+ "vedo>=2025.5.4",
25
24
  ]
26
25
 
27
26
  [dependency-groups]
@@ -38,7 +38,7 @@ class Component(Parameter_container):
38
38
 
39
39
  Args:
40
40
  units (bool, optional): Includes unit in the name of the variable. Defaults to True.
41
- frequency (None or str, optional): frequency of the values: None, "H" Hour, "D" Day, "M" Month, "Y" Year . Defaults to None.
41
+ frequency (None or str, optional): frequency of the values: None, "hourly", "daily", "monthly", "yearly". Defaults to None.
42
42
  value (str, optional): "mean", "sum", "sum_pos", "sum_neg", "max" or "min". Defaults to "mean".
43
43
  interval (None or list of two dates): List with the start and end dates of the period to be included in the dataframe, if the value is None all values are included.
44
44
  pos_neg_columns (list of str, optional): List of variables that will be included in separate columns positive and negative values. Defaults to [].
@@ -62,14 +62,19 @@ class Component(Parameter_container):
62
62
  data[col + "_pos"] = data[col].apply(lambda x: x if x > 0 else 0)
63
63
  data[col + "_neg"] = data[col].apply(lambda x: x if x < 0 else 0)
64
64
  if frequency is not None:
65
+ freq={"hourly": "h", "daily": "D", "monthly": "ME", "yearly": "YE"}
65
66
  if value == "mean":
66
- data = data.resample(frequency, on='date').mean()
67
+ data = data.resample(freq[frequency], on='date').mean()
67
68
  elif value == "sum":
68
- data = data.resample(frequency, on='date').sum()
69
+ data = data.resample(freq[frequency], on='date').sum()
70
+ elif value == "sum_pos":
71
+ data = data.resample(freq[frequency], on='date').apply(lambda x: x.clip(lower=0).sum())
72
+ elif value == "sum_neg":
73
+ data = data.resample(freq[frequency], on='date').apply(lambda x: x.clip(upper=0).sum())
69
74
  elif value == "max":
70
- data = data.resample(frequency, on='date').max()
75
+ data = data.resample(freq[frequency], on='date').max()
71
76
  elif value == "min":
72
- data = data.resample(frequency, on='date').min()
77
+ data = data.resample(freq[frequency], on='date').min()
73
78
  if interval is not None:
74
79
  data = data[(data['date'] > interval[0]) &
75
80
  (data['date'] < interval[1])]
@@ -96,18 +96,17 @@ class Simulation:
96
96
  """Return the list of messages"""
97
97
  return self._messages_
98
98
 
99
- def plot(self, dates, variables, names=[], axis=[], frequency=None, value="mean"):
99
+ def plot(self, dates, variables, names=[], axis=[], frequency=None, value="mean",interval=None):
100
100
  """_summary_
101
101
  Draw variables graph (using plotly)
102
102
 
103
103
  Args:
104
104
  variables: List of hourly variables
105
105
  axis: list of axis y 1 or 2 to use for each variable, empty all in first axis
106
- frequency (None or str, optional): frequency of the values: None, "H" Hour, "D" Day, "M" Month, "Y" Year . Defaults to None.
107
- value (str, optional): "mean", "sum", "max" or "min". Defaults to "mean".
108
-
106
+ frequency (None or str, optional): frequency of the values: None, "hourly", "daily", "monthly", "yearly". Defaults to None.
107
+ value (str, optional): "mean", "sum", "sum_pos", "sum_neg", "max" or "min". Defaults to "mean".
108
+ interval (None or list of two dates): List with the start and end dates of the period to be included in the dataframe, if the value is None all values are included.
109
109
  """
110
-
111
110
  series = {}
112
111
  series["date"] = dates
113
112
  for i in range(len(variables)):
@@ -121,15 +120,24 @@ class Simulation:
121
120
  series[variables[i].key] = variables[i].values
122
121
  data = pd.DataFrame(series)
123
122
  if frequency is not None:
123
+ freq={"hourly": "h", "daily": "D", "monthly": "ME", "yearly": "YE"}
124
124
  if value == "mean":
125
- data = data.resample(frequency, on='date').mean()
125
+ data = data.resample(freq[frequency], on='date').mean()
126
126
  elif value == "sum":
127
- data = data.resample(frequency, on='date').sum()
127
+ data = data.resample(freq[frequency], on='date').sum()
128
+ elif value == "sum_pos":
129
+ data = data.resample(freq[frequency], on='date').apply(lambda x: x.clip(lower=0).sum())
130
+ elif value == "sum_neg":
131
+ data = data.resample(freq[frequency], on='date').apply(lambda x: x.clip(upper=0).sum())
128
132
  elif value == "max":
129
- data = data.resample(frequency, on='date').max()
133
+ data = data.resample(freq[frequency], on='date').max()
130
134
  elif value == "min":
131
- data = data.resample(frequency, on='date').min()
135
+ data = data.resample(freq[frequency], on='date').min()
132
136
  data["date"] = data.index
137
+ if interval is not None:
138
+ data = data[(data['date'] > interval[0]) &
139
+ (data['date'] < interval[1])]
140
+
133
141
 
134
142
  subfig = make_subplots(specs=[[{"secondary_y": True}]])
135
143
 
@@ -0,0 +1,155 @@
1
+ from opensimula.Message import Message
2
+ from opensimula.Parameters import Parameter_float, Parameter_float_list, Parameter_math_exp, Parameter_options
3
+ from opensimula.Component import Component
4
+
5
+ class Chiller_heat_pump(Component):
6
+ def __init__(self, name, project):
7
+ Component.__init__(self, name, project)
8
+ self.parameter("type").value = "Chiller"
9
+ self.parameter("description").value = "Chiller equipment manufacturer information"
10
+ self.add_parameter(Parameter_options("chiller_type", "CHILLER", ["CHILLER", "HEAT_PUMP", "CHILLER_HEAT_PUMP"]))
11
+ self.add_parameter(Parameter_options("condensation_type", "AIR_CONDENSED", ["AIR_CONDENSED", "WATER_CONDENSED"]))
12
+ self.add_parameter(Parameter_float("nominal_water_flow", 1, "dm³/s", min=0))
13
+ self.add_parameter(Parameter_float("nominal_cooling_capacity", 0, "W", min=0))
14
+ self.add_parameter(Parameter_float("nominal_cooling_power", 0, "W", min=0))
15
+ self.add_parameter(Parameter_float_list("nominal_cooling_conditions", [35, 12, 7], "ºC"))
16
+ default_cooling_capacity_expression = "1.1239+0.0316*T_wo-0.00986*T_ci"
17
+ self.add_parameter(Parameter_math_exp("cooling_capacity_expression", default_cooling_capacity_expression, "frac"))
18
+ default_cooling_power_expression = "(0.7336-0.00923*T_wo+0.00945*T_ci)*(0.0878+1.138*F_load-0.2258*F_load**2)"
19
+ self.add_parameter(Parameter_math_exp("cooling_power_expression", default_cooling_power_expression, "frac"))
20
+ self.add_parameter(Parameter_math_exp("EER_expression", "1", "frac"))
21
+ self.add_parameter(Parameter_float("nominal_heating_capacity", 0, "W", min=0))
22
+ self.add_parameter(Parameter_float("nominal_heating_power", 0, "W", min=0))
23
+ self.add_parameter(Parameter_float_list("nominal_heating_conditions", [7, 6, 40, 45], "ºC"))
24
+ default_heating_capacity_expression = "1.012+0.028*T_wbci-0.004*T_wo"
25
+ self.add_parameter(Parameter_math_exp("heating_capacity_expression", default_heating_capacity_expression, "frac"))
26
+ default_heating_power_expression = "(0.505-0.0375*T_wbci+0.016*T_wo)*(0.0878+1.138*F_load-0.2258*F_load**2)"
27
+ self.add_parameter(Parameter_math_exp("heating_power_expression", default_heating_power_expression, "frac"))
28
+ self.add_parameter(Parameter_math_exp("COP_expression", "1", "frac"))
29
+ self.add_parameter(Parameter_float_list("expression_max_values", [80,50,50,1.5,1], "-")) # T_wo, T_ci, T_wbci, F_water, F_load
30
+ self.add_parameter(Parameter_float_list("expression_min_values", [0,-30,-30,0,0], "-")) # T_wo, T_ci, T_wbci, F_water, F_load
31
+
32
+ def check(self):
33
+ errors = super().check()
34
+ # Test Cooling and Heating conditions 3 values
35
+ if len(self.parameter("nominal_cooling_conditions").value)!= 3:
36
+ msg = f"Error: {self.parameter('name').value}, nominal_cooling_conditions size must be 3"
37
+ errors.append(Message(msg, "ERROR"))
38
+ if len(self.parameter("nominal_heating_conditions").value)!= 4:
39
+ msg = f"Error: {self.parameter('name').value}, nominal_heating_conditions size must be 4"
40
+ errors.append(Message(msg, "ERROR"))
41
+ return errors
42
+
43
+ def get_heating_load(self,T_wo,T_ci,T_wbci,water_flow,Q_required):
44
+ """
45
+ Q_required: Required heating load
46
+ Returns (Q_eq,f_load).
47
+ Q_eq: Heating load given by the equipment
48
+ f_load: Fraction of load (0-1)
49
+ """
50
+ F_water = water_flow/self.parameter("nominal_water_flow").value
51
+ if self.parameter("chiller_type").value == "CHILLER":
52
+ return (0, 0)
53
+ else:
54
+ if Q_required == 0:
55
+ return (0,0)
56
+ # variables dictonary
57
+ var_dic = self._var_state_dic([T_wo, T_ci,T_wbci,F_water,1]) #Full load
58
+ # Capacity
59
+ nom_capacity = self.parameter("nominal_heating_capacity").value
60
+ capacity = nom_capacity * self.parameter("heating_capacity_expression").evaluate(var_dic)
61
+ if Q_required > capacity:
62
+ return (capacity,1)
63
+ else:
64
+ f_load = Q_required/capacity
65
+ return (Q_required, f_load)
66
+
67
+ def get_heating_power(self,T_wo, T_ci,T_wbci,water_flow,Q_required):
68
+ """
69
+ Returns (tot_power,COP).
70
+ """
71
+ if self.parameter("chiller_type").value == "CHILLER":
72
+ return (0,0)
73
+ else:
74
+ if Q_required == 0:
75
+ return (0,0)
76
+ Q, F_load = self.get_heating_load(T_wo, T_ci,T_wbci,water_flow,Q_required)
77
+ # variables dictonary
78
+ F_water = water_flow/self.parameter("nominal_water_flow").value
79
+ var_dic = self._var_state_dic([T_wo, T_ci,T_wbci,F_water,F_load])
80
+ # Total power
81
+ nom_power = self.parameter("nominal_heating_power").value
82
+ if (self.parameter("heating_power_expression").value == "1"): ## Use COP expression
83
+ nom_capacity= self.parameter("nominal_heating_capacity").value
84
+ nom_COP = nom_capacity/nom_power
85
+ power = Q/ (nom_COP * self.parameter("COP_expression").evaluate(var_dic))
86
+ else: ## Use heating power expressions
87
+ power = nom_power * self.parameter("heating_power_expression").evaluate(var_dic)
88
+ COP = Q/power
89
+ return (power, COP)
90
+
91
+ def get_cooling_load(self,T_wo,T_ci,T_wbci,water_flow,Q_required):
92
+ """
93
+ Q_required: Required cooling load
94
+ Returns (Q_eq,f_load).
95
+ Q_eq: Total cool given by the equipment
96
+ f_load: Fraction of load (0-1)
97
+ """
98
+ F_water = water_flow/self.parameter("nominal_water_flow").value
99
+ if self.parameter("chiller_type").value == "HEAT_PUMP":
100
+ return (0,0)
101
+ else:
102
+ if Q_required == 0:
103
+ return (0,0)
104
+ nom_capacity = self.parameter("nominal_cooling_capacity").value
105
+ # variables dictonary
106
+ var_dic = self._var_state_dic([T_wo,T_ci,T_wbci,F_water,1]) #Full load
107
+ capacity = nom_capacity * self.parameter("cooling_capacity_expression").evaluate(var_dic)
108
+ if Q_required > capacity:
109
+ return (capacity,1)
110
+ else:
111
+ f_load = Q_required/capacity
112
+ return (Q_required, f_load)
113
+
114
+ def get_cooling_power(self,T_wo, T_ci,T_wbci,water_flow,Q_required):
115
+ """
116
+ Returns (tot_power,EER).
117
+ """
118
+ if self.parameter("chiller_type").value == "HEAT_PUMP":
119
+ return (0,0)
120
+ else:
121
+ if Q_required == 0:
122
+ return (0,0)
123
+ Q, F_load = self.get_cooling_load(T_wo, T_ci,T_wbci,water_flow,Q_required)
124
+ # variables dictonary
125
+ F_water = water_flow/self.parameter("nominal_water_flow").value
126
+ var_dic = self._var_state_dic([T_wo, T_ci,T_wbci,F_water,F_load])
127
+ # Power
128
+ nom_power = self.parameter("nominal_cooling_power").value
129
+ if (self.parameter("cooling_power_expression").value == "1"): ## Use EER expression
130
+ nom_capacity= self.parameter("nominal_cooling_capacity").value
131
+ nom_EER = nom_capacity/nom_power
132
+ power = Q/ (nom_EER * self.parameter("EER_expression").evaluate(var_dic))
133
+ else: ## Use cooling power expressions
134
+ power = nom_power * self.parameter("cooling_power_expression").evaluate(var_dic)
135
+ COP = Q/power
136
+ return (power, COP)
137
+
138
+ def _var_state_dic(self, values):
139
+ max = self.parameter("expression_max_values").value
140
+ min = self.parameter("expression_min_values").value
141
+ for i in range(len(values)):
142
+ if (values[i] > max[i]):
143
+ values[i] = max[i]
144
+ elif (values[i] < min[i]):
145
+ values[i] = min[i]
146
+ return {"T_wo":values[0],
147
+ "T_ci":values[1],
148
+ "T_wbci":values[2],
149
+ "F_water":values[3],
150
+ "F_load":values[4]}
151
+
152
+
153
+
154
+
155
+
@@ -40,8 +40,9 @@ class File_data(Component):
40
40
  self._df_ = pd.read_excel(self.parameter("file_name").value)
41
41
  # Create Variable
42
42
  for col in self._df_.columns:
43
- self.add_variable(Variable(self._extract_name_(
44
- col), unit=self._extract_unit_(col)))
43
+ if self._is_numeric_(col):
44
+ self.add_variable(Variable(self._extract_name_(
45
+ col), unit=self._extract_unit_(col)))
45
46
 
46
47
  except Exception as ex:
47
48
  if type(ex).__name__ == "FileNotFoundError":
@@ -55,7 +56,7 @@ class File_data(Component):
55
56
  def pre_simulation(self, n_time_steps, delta_t):
56
57
  super().pre_simulation(n_time_steps, delta_t)
57
58
 
58
- self.data_array = self._df_.to_numpy()
59
+ self.data_array = self._df_.select_dtypes(include=np.number).to_numpy()
59
60
 
60
61
  if self.parameter("file_step").value == "SIMULATION":
61
62
  i = 0
@@ -100,6 +101,9 @@ class File_data(Component):
100
101
  return ""
101
102
  else:
102
103
  return name[name.rfind("[") + 1: name.rfind("]")].strip()
104
+
105
+ def _is_numeric_(self, name):
106
+ return pd.api.types.is_numeric_dtype(self._df_[name])
103
107
 
104
108
  def _get_interpolation_tuple_(self, date):
105
109
  seconds = (date-self._initial_date_).total_seconds()
@@ -76,10 +76,16 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
76
76
  Parameter_options("fan_operation", "CONTINUOUS", ["CONTINUOUS", "CYCLING"])
77
77
  )
78
78
  self.add_parameter(
79
- Parameter_options("water_source", "UNKNOWN", ["UNKNOWN", "WATER_LOOP"])
79
+ Parameter_options("water_source", "UNKNOWN", ["UNKNOWN", "WATER_SYSTEM"])
80
80
  )
81
- self.add_parameter(Parameter_float("cooling_water_flow", 1, "m³/s", min=0))
82
- self.add_parameter(Parameter_float("heating_water_flow", 1, "m³/s", min=0))
81
+ self.add_parameter(
82
+ Parameter_component("cooling_water_system", "not_defined", ["HVAC_water_system"])
83
+ )
84
+ self.add_parameter(
85
+ Parameter_component("heating_water_system", "not_defined", ["HVAC_water_system"])
86
+ )
87
+ self.add_parameter(Parameter_float("cooling_water_flow", 1, "dm³/s", min=0))
88
+ self.add_parameter(Parameter_float("heating_water_flow", 1, "dm³/s", min=0))
83
89
  self.add_parameter(Parameter_float("inlet_cooling_water_temp", 7, "ºC"))
84
90
  self.add_parameter(Parameter_float("inlet_heating_water_temp", 50, "ºC"))
85
91
  self.add_parameter(
@@ -111,6 +117,13 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
111
117
  "reheat_coils", ["not_defined", "not_defined"], ["Water_coil"]
112
118
  )
113
119
  )
120
+ self.add_parameter(
121
+ Parameter_options("reheat_water_source", "UNKNOWN", ["UNKNOWN", "WATER_SYSTEM"])
122
+ )
123
+ self.add_parameter(
124
+ Parameter_component("reheat_water_system", "not_defined", ["HVAC_water_system"])
125
+ )
126
+
114
127
 
115
128
  # Variables
116
129
  self.add_variable(
@@ -183,6 +196,24 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
183
196
  f"{self.parameter('name').value}, must define its supply fan equipment."
184
197
  )
185
198
  errors.append(Message(msg, "ERROR"))
199
+ # Test cooling water system defined
200
+ if self.parameter("water_source").value == "WATER_SYSTEM" and self.parameter("cooling_water_system").value == "not_defined":
201
+ msg = (
202
+ f"{self.parameter('name').value}, must define its cooling water system."
203
+ )
204
+ errors.append(Message(msg, "ERROR"))
205
+ # Test heating water system defined
206
+ if self.parameter("water_source").value == "WATER_SYSTEM" and self.parameter("heating_water_system").value == "not_defined":
207
+ msg = (
208
+ f"{self.parameter('name').value}, must define its heating water system."
209
+ )
210
+ errors.append(Message(msg, "ERROR"))
211
+ # Test reheat water system defined
212
+ if self.parameter("reheat_water_source").value == "WATER_SYSTEM" and self.parameter("reheat_water_system").value == "not_defined":
213
+ msg = (
214
+ f"{self.parameter('name').value}, must define its reheat water system."
215
+ )
216
+ errors.append(Message(msg, "ERROR"))
186
217
  # Test file_met defined
187
218
  if self.project().parameter("simulation_file_met").value == "not_defined":
188
219
  msg = f"{self.parameter('name').value}, file_met must be defined in the project 'simulation_file_met'."
@@ -221,18 +252,8 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
221
252
  self.reheat_coils = self.parameter("reheat_coils").component
222
253
 
223
254
  # Water flows and temperatures
224
- self.cooling_water_flow = self.parameter("cooling_water_flow").value
225
- self.heating_water_flow = self.parameter("heating_water_flow").value
226
- if self.c_coil:
227
- self._cooling_F_water = (
228
- self.cooling_water_flow
229
- / self.c_coil.parameter("nominal_cooling_water_flow").value
230
- )
231
- if self.h_coil:
232
- self._heating_F_water = (
233
- self.heating_water_flow
234
- / self.h_coil.parameter("nominal_heating_water_flow").value
235
- )
255
+ self.cooling_water_flow = self.parameter("cooling_water_flow").value/1000 # Convert to m³/s
256
+ self.heating_water_flow = self.parameter("heating_water_flow").value/1000 # Convert to m³/s
236
257
  self.cooling_water_temp = self.parameter("inlet_cooling_water_temp").value
237
258
  self.heating_water_temp = self.parameter("inlet_heating_water_temp").value
238
259
  self.rho_MA = self.props["RHO_A"]
@@ -575,7 +596,7 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
575
596
  # Reheat coil
576
597
  water_flow = reheat_coil.parameter(
577
598
  "nominal_heating_water_flow"
578
- ).value
599
+ ).value/1000 # Convert to m³/s
579
600
  capacity, epsilon = reheat_coil.get_heating_capacity(
580
601
  self.T_SA,
581
602
  self.T_SAwb,
@@ -681,11 +702,11 @@ class HVAC_MZW_system(Component): # HVAC Multizone Water system
681
702
  self.variable("T_ADP").values[time_index] = 0
682
703
  self.variable("epsilon").values[time_index] = self.epsilon
683
704
  elif self.state == -1 or self.state == -2: # Cooling
684
- Q_s = -self.Q_coil
705
+ Q_s = self.Q_coil
685
706
  Q_l = -self.M_w * self.props["LAMBDA"]
686
707
  self.variable("Q_sensible").values[time_index] = Q_s
687
708
  self.variable("Q_latent").values[time_index] = Q_l
688
- self.variable("Q_total").values[time_index] = Q_s
709
+ self.variable("Q_total").values[time_index] = -Q_s + Q_l
689
710
  self.variable("T_iw").values[time_index] = self.cooling_water_temp
690
711
  self.variable("T_ow").values[time_index] = self.cooling_water_temp + (
691
712
  Q_s + Q_l