OpenSimula 0.3.2__tar.gz → 0.4.1__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.
Potentially problematic release.
This version of OpenSimula might be problematic. Click here for more details.
- {opensimula-0.3.2 → opensimula-0.4.1}/LICENSE +1 -1
- {opensimula-0.3.2 → opensimula-0.4.1}/OpenSimula.egg-info/PKG-INFO +1 -1
- {opensimula-0.3.2 → opensimula-0.4.1}/OpenSimula.egg-info/SOURCES.txt +2 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/PKG-INFO +1 -1
- {opensimula-0.3.2 → opensimula-0.4.1}/pyproject.toml +1 -1
- opensimula-0.4.1/src/OpenSimula/Iterative_process.py +43 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Project.py +5 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/__init__.py +2 -1
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/File_met.py +8 -4
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/HVAC_DX_equipment.py +46 -6
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/HVAC_DX_system.py +133 -34
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Space.py +16 -25
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_HVAC_DX_Equipment.py +5 -5
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_HVAC_DX_system.py +1 -2
- opensimula-0.4.1/test/test_Iterative_process.py +13 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/OpenSimula.egg-info/dependency_links.txt +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/OpenSimula.egg-info/requires.txt +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/OpenSimula.egg-info/top_level.txt +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/README.md +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/docs/cinder/__init__.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/mkdocs/cinder/__init__.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/setup.cfg +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Child.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Component.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Parameter_container.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Parameters.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Simulation.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/Variable.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Building.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Calculator.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Construction.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Day_schedule.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Exterior_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/File_data.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Frame.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Glazing.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/HVAC_perfect_system.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Interior_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Material.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Opening.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Opening_type.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Real_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Shadow_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Space_type.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Test_component.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Underground_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Virtual_surface.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Week_schedule.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/Year_schedule.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/__init__.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/src/OpenSimula/components/utils/sun_shadows.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Calculator.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Case_600FF.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Case_610.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Construction.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_File_data.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_File_met.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Project.py +0 -0
- {opensimula-0.3.2 → opensimula-0.4.1}/test/test_Schedules.py +0 -0
|
@@ -10,6 +10,7 @@ docs/cinder/__init__.py
|
|
|
10
10
|
mkdocs/cinder/__init__.py
|
|
11
11
|
src/OpenSimula/Child.py
|
|
12
12
|
src/OpenSimula/Component.py
|
|
13
|
+
src/OpenSimula/Iterative_process.py
|
|
13
14
|
src/OpenSimula/Parameter_container.py
|
|
14
15
|
src/OpenSimula/Parameters.py
|
|
15
16
|
src/OpenSimula/Project.py
|
|
@@ -52,5 +53,6 @@ test/test_File_data.py
|
|
|
52
53
|
test/test_File_met.py
|
|
53
54
|
test/test_HVAC_DX_Equipment.py
|
|
54
55
|
test/test_HVAC_DX_system.py
|
|
56
|
+
test/test_Iterative_process.py
|
|
55
57
|
test/test_Project.py
|
|
56
58
|
test/test_Schedules.py
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
class Iterative_process:
|
|
4
|
+
def __init__(self, x_0, tol = 1e-5, lambda_min=0.1, lambda_max=1.0, n_ini_relax=2,rel_vel = 0.9):
|
|
5
|
+
"""
|
|
6
|
+
Iterative process using the fixed-point method with adaptive relaxation coefficient
|
|
7
|
+
|
|
8
|
+
Parameters:
|
|
9
|
+
x_0: Initial value
|
|
10
|
+
tol: convergence tolerance
|
|
11
|
+
lambda_min, lambda_max: relaxation coefficient range
|
|
12
|
+
n_ini_relax: Number of iterations in which adaptive relaxation is initiated, must be greater than 1
|
|
13
|
+
"""
|
|
14
|
+
self.x = [x_0]
|
|
15
|
+
self.tol = tol
|
|
16
|
+
self.lambda_min = lambda_min
|
|
17
|
+
self.lambda_max = lambda_max
|
|
18
|
+
self.lambda_i = lambda_max
|
|
19
|
+
self.n_ini_relax = n_ini_relax
|
|
20
|
+
self.rel_vel = rel_vel
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def converged(self):
|
|
24
|
+
if len(self.x) == 1:
|
|
25
|
+
return False
|
|
26
|
+
else:
|
|
27
|
+
if abs(self.x[-1]-self.x[-2]) < self.tol:
|
|
28
|
+
return True
|
|
29
|
+
else:
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
def x_next(self, proposed_x):
|
|
33
|
+
x_next = (1 - self.lambda_i) * self.x[-1] + self.lambda_i * proposed_x
|
|
34
|
+
|
|
35
|
+
# Ajuste dinámico de lambda (reduce si hay oscilaciones)
|
|
36
|
+
if len(self.x)>self.n_ini_relax:
|
|
37
|
+
#if abs(x_next - self.x[-1]) > abs(self.x[-1]- self.x[-2]):
|
|
38
|
+
self.lambda_i = max(self.lambda_min, self.lambda_i * self.rel_vel) # Reducimos lambda
|
|
39
|
+
#else:
|
|
40
|
+
#self.lambda_i = min(self.lambda_max, self.lambda_i * 1/self.rel_vel) # Aumentamos lambda
|
|
41
|
+
|
|
42
|
+
self.x.append(x_next)
|
|
43
|
+
return x_next
|
|
@@ -360,6 +360,7 @@ class Project(Parameter_container):
|
|
|
360
360
|
self._sim_df = pd.DataFrame({"dates":self.dates()})
|
|
361
361
|
self._sim_df["n_iterations"] = 0
|
|
362
362
|
self._sim_df["last_component"] = "None"
|
|
363
|
+
self._sim_df["converged"] = True
|
|
363
364
|
|
|
364
365
|
self._sim_.print(f"Simulating {self.parameter('name').value}: ...")
|
|
365
366
|
|
|
@@ -383,11 +384,15 @@ class Project(Parameter_container):
|
|
|
383
384
|
converge = True
|
|
384
385
|
n_iter += 1
|
|
385
386
|
self._sim_df.at[i, "n_iterations"] = n_iter
|
|
387
|
+
self._sim_df.at[i, "converged"] = converge
|
|
386
388
|
n_iter_acum += n_iter
|
|
387
389
|
self._post_iteration_(i, date, daylight_saving, converge)
|
|
388
390
|
date = date + dt.timedelta(0, delta_t)
|
|
389
391
|
|
|
390
392
|
self._sim_.print("Simulation completed.")
|
|
393
|
+
n_not_converged = len(self._sim_df["converged"]) - self._sim_df["converged"].sum()
|
|
394
|
+
if n_not_converged > 0:
|
|
395
|
+
self._sim_.print(f"Warning: {n_not_converged} time steps did not converge.")
|
|
391
396
|
self._post_simulation_()
|
|
392
397
|
|
|
393
398
|
def _pre_simulation_(self, n_time_steps, delta_t):
|
|
@@ -239,17 +239,21 @@ class File_met(Component):
|
|
|
239
239
|
variable).values[time_i] = array[i] * (1 - f) + array[j] * f
|
|
240
240
|
|
|
241
241
|
def _get_solar_interpolation_tuple_(self, datetime, solar_hour):
|
|
242
|
-
day = datetime.timetuple().tm_yday #
|
|
242
|
+
day = datetime.timetuple().tm_yday # Day of the year
|
|
243
|
+
if (solar_hour - datetime.hour > 10): # solar hour from previous day
|
|
244
|
+
day = day - 1
|
|
245
|
+
elif (solar_hour - datetime.hour < -10): # solar hour next day
|
|
246
|
+
day = day + 1
|
|
243
247
|
# El primer valor es a las 00:30
|
|
244
248
|
index = solar_hour + (day-1)*24
|
|
245
249
|
if index < 0:
|
|
246
|
-
index =
|
|
250
|
+
index = 0
|
|
247
251
|
elif index >= 8760:
|
|
248
|
-
index =
|
|
252
|
+
index = 8760
|
|
249
253
|
i = math.floor(index)
|
|
250
254
|
j = i + 1
|
|
251
255
|
if j >= 8760:
|
|
252
|
-
j =
|
|
256
|
+
j = 8760
|
|
253
257
|
f = index - i
|
|
254
258
|
return (i, j, f)
|
|
255
259
|
|
|
@@ -11,8 +11,7 @@ class HVAC_DX_equipment(Component):
|
|
|
11
11
|
self.add_parameter(Parameter_float("nominal_total_cooling_capacity", 0, "W", min=0))
|
|
12
12
|
self.add_parameter(Parameter_float("nominal_sensible_cooling_capacity", 0, "W", min=0))
|
|
13
13
|
self.add_parameter(Parameter_float("nominal_cooling_power", 0, "W", min=0))
|
|
14
|
-
self.add_parameter(Parameter_float("
|
|
15
|
-
self.add_parameter(Parameter_float("no_load_heat", 0, "W", min=0))
|
|
14
|
+
self.add_parameter(Parameter_float("indoor_fan_power", 0, "W", min=0))
|
|
16
15
|
self.add_parameter(Parameter_float_list("nominal_cooling_conditions", [27, 19, 35], "ºC"))
|
|
17
16
|
self.add_parameter(Parameter_math_exp("total_cooling_capacity_expression", "1", "frac"))
|
|
18
17
|
self.add_parameter(Parameter_math_exp("sensible_cooling_capacity_expression", "1", "frac"))
|
|
@@ -25,6 +24,7 @@ class HVAC_DX_equipment(Component):
|
|
|
25
24
|
self.add_parameter(Parameter_math_exp("heating_power_expression", "1", "frac"))
|
|
26
25
|
self.add_parameter(Parameter_math_exp("COP_expression", "1", "frac"))
|
|
27
26
|
self.add_parameter(Parameter_options("dry_coil_model", "SENSIBLE", ["TOTAL", "SENSIBLE"]))
|
|
27
|
+
self.add_parameter(Parameter_options("indoor_fan_operation", "CONTINUOUS", ["CONTINUOUS", "CICLING"]))
|
|
28
28
|
self.add_parameter(Parameter_boolean("power_dry_coil_correction", True))
|
|
29
29
|
self.add_parameter(Parameter_float_list("expression_max_values", [60,30,60,30,1.5,1], "-"))
|
|
30
30
|
self.add_parameter(Parameter_float_list("expression_min_values", [0,0,-30,-30,0,0], "-"))
|
|
@@ -39,6 +39,11 @@ class HVAC_DX_equipment(Component):
|
|
|
39
39
|
return errors
|
|
40
40
|
|
|
41
41
|
def get_cooling_capacity(self,T_idb,T_iwb,T_odb,T_owb,F_air):
|
|
42
|
+
"""
|
|
43
|
+
Returns (Q_tot,Q_sen) capacities.
|
|
44
|
+
If indoor_fan_operation is CONTINUOUS: It returns the values from the expressions (Gross capacity = Coil capacity)
|
|
45
|
+
If indoor_fan_operation is CICLING: It returns the expressions minus the indoor fan power (Net capacity = Gross capacity - indoor fan)
|
|
46
|
+
"""
|
|
42
47
|
total_capacity = self.parameter("nominal_total_cooling_capacity").value
|
|
43
48
|
if total_capacity > 0:
|
|
44
49
|
# variables dictonary
|
|
@@ -55,24 +60,39 @@ class HVAC_DX_equipment(Component):
|
|
|
55
60
|
total_capacity = sensible_capacity
|
|
56
61
|
elif self.parameter("dry_coil_model").value == "TOTAL":
|
|
57
62
|
sensible_capacity = total_capacity
|
|
63
|
+
if self.parameter("indoor_fan_operation").value == "CICLING":
|
|
64
|
+
sensible_capacity = sensible_capacity - self.parameter("indoor_fan_power").value
|
|
65
|
+
total_capacity = total_capacity - self.parameter("indoor_fan_power").value
|
|
58
66
|
return (total_capacity, sensible_capacity)
|
|
59
67
|
else:
|
|
60
68
|
return (0,0)
|
|
61
69
|
|
|
62
70
|
def get_heating_capacity(self,T_idb,T_iwb,T_odb,T_owb,F_air):
|
|
71
|
+
"""
|
|
72
|
+
Returns heat sensible capacity.
|
|
73
|
+
If indoor_fan_operation is CONTINUOUS: It returns the values from the expressions (Gross capacity = Coil capacity)
|
|
74
|
+
If indoor_fan_operation is CICLING: It returns the expressions plus the indoor fan power (Net capacity = Gross capacity + indoor fan) """
|
|
63
75
|
capacity = self.parameter("nominal_heating_capacity").value
|
|
64
76
|
if capacity > 0:
|
|
65
77
|
# variables dictonary
|
|
66
78
|
var_dic = self._var_state_dic([T_idb, T_iwb,T_odb,T_owb,F_air,0])
|
|
67
79
|
# Capacity
|
|
68
80
|
capacity = capacity * self.parameter("heating_capacity_expression").evaluate(var_dic)
|
|
81
|
+
if self.parameter("indoor_fan_operation").value == "CICLING":
|
|
82
|
+
capacity = capacity + self.parameter("indoor_fan_power").value
|
|
69
83
|
return capacity
|
|
70
84
|
else:
|
|
71
85
|
return 0
|
|
72
86
|
|
|
73
87
|
def get_cooling_state(self,T_idb,T_iwb,T_odb,T_owb,F_air,F_load):
|
|
88
|
+
"""
|
|
89
|
+
Returns (Q_tot,Q_sen,Power,F_EER).
|
|
90
|
+
"""
|
|
74
91
|
total_capacity, sensible_capacity = self.get_cooling_capacity(T_idb,T_iwb,T_odb,T_owb,F_air)
|
|
75
92
|
if total_capacity > 0:
|
|
93
|
+
if self.parameter("indoor_fan_operation").value == "CICLING": # Get gross capacities
|
|
94
|
+
total_capacity= total_capacity + self.parameter("indoor_fan_power").value
|
|
95
|
+
sensible_capacity= sensible_capacity + self.parameter("indoor_fan_power").value
|
|
76
96
|
if (F_load > 0):
|
|
77
97
|
# variables dictonary
|
|
78
98
|
var_dic = self._var_state_dic([T_idb, T_iwb,T_odb,T_owb,F_air,F_load])
|
|
@@ -82,10 +102,16 @@ class HVAC_DX_equipment(Component):
|
|
|
82
102
|
EER_full = total_capacity/power_full
|
|
83
103
|
F_EER = self.parameter("EER_expression").evaluate(var_dic)
|
|
84
104
|
EER = EER_full * F_EER
|
|
85
|
-
|
|
105
|
+
if self.parameter("indoor_fan_operation").value == "CONTINUOUS":
|
|
106
|
+
power = total_capacity*F_load/EER + self.parameter("indoor_fan_power").value
|
|
107
|
+
elif self.parameter("indoor_fan_operation").value == "CICLING":
|
|
108
|
+
power = total_capacity*F_load/EER + self.parameter("indoor_fan_power").value*F_load/F_EER
|
|
86
109
|
return (total_capacity*F_load, sensible_capacity*F_load, power, F_EER)
|
|
87
110
|
else:
|
|
88
|
-
|
|
111
|
+
if self.parameter("indoor_fan_operation").value == "CONTINUOUS":
|
|
112
|
+
return ( 0 , 0 , self.parameter("indoor_fan_power").value, 0 )
|
|
113
|
+
elif self.parameter("indoor_fan_operation").value == "CICLING":
|
|
114
|
+
return ( 0 , 0 , 0, 0 )
|
|
89
115
|
else:
|
|
90
116
|
return (0,0,0,0)
|
|
91
117
|
|
|
@@ -110,6 +136,8 @@ class HVAC_DX_equipment(Component):
|
|
|
110
136
|
def get_heating_state(self,T_idb, T_iwb,T_odb,T_owb,F_air,F_load):
|
|
111
137
|
capacity = self.get_heating_capacity(T_idb, T_iwb, T_odb,T_owb,F_air)
|
|
112
138
|
if capacity > 0:
|
|
139
|
+
if self.parameter("indoor_fan_operation").value == "CICLING": # Get gross capacities
|
|
140
|
+
capacity= capacity - self.parameter("indoor_fan_power").value
|
|
113
141
|
if (F_load > 0):
|
|
114
142
|
# variables dictonary
|
|
115
143
|
var_dic = self._var_state_dic([T_idb, T_iwb,T_odb,T_owb,F_air,F_load])
|
|
@@ -119,12 +147,24 @@ class HVAC_DX_equipment(Component):
|
|
|
119
147
|
COP_full = capacity/power_full
|
|
120
148
|
F_COP = self.parameter("COP_expression").evaluate(var_dic)
|
|
121
149
|
COP = COP_full * F_COP
|
|
122
|
-
|
|
150
|
+
if self.parameter("indoor_fan_operation").value == "CONTINUOUS":
|
|
151
|
+
power = capacity*F_load/COP + self.parameter("indoor_fan_power").value
|
|
152
|
+
elif self.parameter("indoor_fan_operation").value == "CICLING":
|
|
153
|
+
power = capacity*F_load/COP + self.parameter("indoor_fan_power").value*F_load/F_COP
|
|
123
154
|
return (capacity*F_load, power, F_COP)
|
|
124
155
|
else:
|
|
125
|
-
|
|
156
|
+
if self.parameter("indoor_fan_operation").value == "CONTINUOUS":
|
|
157
|
+
return ( 0 , 0 , self.parameter("indoor_fan_power").value, 0 )
|
|
158
|
+
elif self.parameter("indoor_fan_operation").value == "CICLING":
|
|
159
|
+
return ( 0 , 0 , 0, 0 )
|
|
126
160
|
else:
|
|
127
161
|
return (0,0,0)
|
|
162
|
+
|
|
163
|
+
def get_no_load_power(self):
|
|
164
|
+
if self.parameter("indoor_fan_operation").value == "CONTINUOUS":
|
|
165
|
+
return self.parameter("indoor_fan_power").value
|
|
166
|
+
elif self.parameter("indoor_fan_operation").value == "CICLING":
|
|
167
|
+
return 0
|
|
128
168
|
|
|
129
169
|
def _var_state_dic(self, values):
|
|
130
170
|
max = self.parameter("expression_max_values").value
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from OpenSimula.Parameters import Parameter_component, Parameter_float, Parameter_variable_list, Parameter_math_exp, Parameter_options
|
|
2
2
|
from OpenSimula.Component import Component
|
|
3
3
|
from OpenSimula.Variable import Variable
|
|
4
|
+
from OpenSimula.Iterative_process import Iterative_process
|
|
4
5
|
import psychrolib as sicro
|
|
5
6
|
|
|
6
7
|
|
|
@@ -21,8 +22,10 @@ class HVAC_DX_system(Component):
|
|
|
21
22
|
self.add_parameter(Parameter_options("control_type", "PERFECT", ["PERFECT", "TEMPERATURE"]))
|
|
22
23
|
self.add_parameter(Parameter_float("cooling_bandwidth", 1, "ºC", min=0))
|
|
23
24
|
self.add_parameter(Parameter_float("heating_bandwidth", 1, "ºC", min=0))
|
|
24
|
-
self.add_parameter(
|
|
25
|
-
|
|
25
|
+
self.add_parameter(Parameter_options("economizer", "NO", ["NO", "TEMPERATURE","TEMPERATURE_NOT_INTEGRATED","ENTHALPY","ENTHALPY_LIMITED"]))
|
|
26
|
+
self.add_parameter(Parameter_float("economizer_DT", 0, "ºC", min=0))
|
|
27
|
+
self.add_parameter(Parameter_float("economizer_enthalpy_limit", 0, "kJ/kg", min=0))
|
|
28
|
+
|
|
26
29
|
# Variables
|
|
27
30
|
self.add_variable(Variable("state", unit="flag")) # 0: 0ff, 1: Heating, 2: Heating max cap, -1:Cooling, -2:Cooling max cap, 3: Venting
|
|
28
31
|
self.add_variable(Variable("T_odb", unit="°C"))
|
|
@@ -63,6 +66,11 @@ class HVAC_DX_system(Component):
|
|
|
63
66
|
if self.parameter("file_met").value == "not_defined":
|
|
64
67
|
errors.append(
|
|
65
68
|
f"Error: {self.parameter('name').value}, file_met must be defined.")
|
|
69
|
+
# Test enthalpy economizer not compatible with temperature control type
|
|
70
|
+
if (self.parameter("economizer").value == "ENTHALPY" or self.parameter("economizer").value == "ENTHALPY_LIMITED") and self.parameter("control_type").value == "TEMPERATURE":
|
|
71
|
+
errors.append(
|
|
72
|
+
f"Error: {self.parameter('name').value}, enthalpy economizer not compatible with temperature control type. control typed changed to PERFECT.")
|
|
73
|
+
self.parameter("control_type").value = "PERFECT"
|
|
66
74
|
return errors
|
|
67
75
|
|
|
68
76
|
def pre_simulation(self, n_time_steps, delta_t):
|
|
@@ -88,10 +96,10 @@ class HVAC_DX_system(Component):
|
|
|
88
96
|
self.input_var_variable.append(
|
|
89
97
|
self.parameter("input_variables").variable[i])
|
|
90
98
|
self._f_load = 0
|
|
91
|
-
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
99
|
+
|
|
100
|
+
self._no_load_power = self._equipment.get_no_load_power()
|
|
101
|
+
self._economizer = self.parameter("economizer").value != "NO"
|
|
102
|
+
self._economizer_DT = self.parameter("economizer_DT").value
|
|
95
103
|
|
|
96
104
|
def pre_iteration(self, time_index, date, daylight_saving):
|
|
97
105
|
super().pre_iteration(time_index, date, daylight_saving)
|
|
@@ -125,7 +133,7 @@ class HVAC_DX_system(Component):
|
|
|
125
133
|
self._on_off = False
|
|
126
134
|
else:
|
|
127
135
|
self._on_off = True
|
|
128
|
-
self._f_load_pre = self._f_load
|
|
136
|
+
#self._f_load_pre = self._f_load
|
|
129
137
|
|
|
130
138
|
# Add uncontrolled ventilation to the space
|
|
131
139
|
if self._on_off:
|
|
@@ -133,12 +141,12 @@ class HVAC_DX_system(Component):
|
|
|
133
141
|
"V": self._outdoor_air_flow,
|
|
134
142
|
"T":self._T_odb,
|
|
135
143
|
"w": self._w_o,
|
|
136
|
-
"Q":self.
|
|
144
|
+
"Q":self._no_load_power,
|
|
137
145
|
"M": 0}
|
|
138
146
|
self._space.add_uncontrol_system(system_dic)
|
|
139
|
-
|
|
140
|
-
self.
|
|
141
|
-
|
|
147
|
+
# Iterative Process for outdoor air fraction with economizer
|
|
148
|
+
self.itera_Foa = Iterative_process(self._outdoor_air_flow/self._supply_air_flow,tol=0.01,n_ini_relax=3,rel_vel=0.8)
|
|
149
|
+
|
|
142
150
|
|
|
143
151
|
def iteration(self, time_index, date, daylight_saving, n_iter):
|
|
144
152
|
super().iteration(time_index, date, daylight_saving, n_iter)
|
|
@@ -146,14 +154,17 @@ class HVAC_DX_system(Component):
|
|
|
146
154
|
if self._on_off:
|
|
147
155
|
self._T_space = self._space.variable("temperature").values[time_index]
|
|
148
156
|
self._w_space = self._space.variable("abs_humidity").values[time_index]
|
|
149
|
-
# Mix air
|
|
150
|
-
self._T_idb, self._w_i, self._T_iwb = self._mix_air(self._f_oa, self._T_odb, self._w_o, self._T_space, self._w_space)
|
|
151
157
|
if self.parameter("control_type").value == "PERFECT":
|
|
152
158
|
control= self._perfect_control(n_iter)
|
|
153
159
|
elif self.parameter("control_type").value == "TEMPERATURE":
|
|
154
160
|
control = self._air_temperature_control(n_iter)
|
|
155
161
|
self._space.set_control_system(control)
|
|
156
|
-
|
|
162
|
+
|
|
163
|
+
# Test convergence
|
|
164
|
+
if self._on_off and self.parameter("control_type").value == "TEMPERATURE" and self._economizer:
|
|
165
|
+
return self.itera_Foa.converged()
|
|
166
|
+
else:
|
|
167
|
+
return True
|
|
157
168
|
|
|
158
169
|
def _mix_air(self, f, T1, w1, T2, w2):
|
|
159
170
|
T = f * T1 + (1-f)*T2
|
|
@@ -165,12 +176,18 @@ class HVAC_DX_system(Component):
|
|
|
165
176
|
return (T,w,T_wb)
|
|
166
177
|
|
|
167
178
|
def _perfect_control(self, n_iter):
|
|
168
|
-
Q_required = self._space.get_Q_required(self._T_cool_sp, self._T_heat_sp)
|
|
169
179
|
# Venting
|
|
170
180
|
state = 3
|
|
171
181
|
f_load = 0
|
|
172
182
|
Q_sen = 0
|
|
173
183
|
M_w = 0
|
|
184
|
+
|
|
185
|
+
# Economizer
|
|
186
|
+
Q_required = self._economizer_perfect()
|
|
187
|
+
|
|
188
|
+
# Mix air
|
|
189
|
+
self._T_idb, self._w_i, self._T_iwb = self._mix_air(self._f_oa, self._T_odb, self._w_o, self._T_space, self._w_space)
|
|
190
|
+
|
|
174
191
|
if Q_required > 0: # Heating
|
|
175
192
|
heat_cap = self._equipment.get_heating_capacity(self._T_idb, self._T_iwb, self._T_odb, self._T_owb,self._f_air)
|
|
176
193
|
if heat_cap > 0:
|
|
@@ -197,27 +214,72 @@ class HVAC_DX_system(Component):
|
|
|
197
214
|
Q_tot = tot_cool_cap*f_load
|
|
198
215
|
M_w = (Q_tot - Q_sen) / self.DH_W
|
|
199
216
|
# relaxing coef
|
|
200
|
-
r_coef = (0.01-self._r_coef)/self._n_max_iter * n_iter + self._r_coef
|
|
201
|
-
self._M_w = r_coef * M_w + (1-r_coef)*self._M_w_pre # Always relaxing
|
|
202
|
-
self._Q_sen = r_coef * Q_sen + (1-r_coef)*self._Q_sen_pre
|
|
203
|
-
self._f_load = r_coef * f_load + (1-r_coef)*self._f_load_pre
|
|
217
|
+
#r_coef = (0.01-self._r_coef)/self._n_max_iter * n_iter + self._r_coef
|
|
218
|
+
#self._M_w = r_coef * M_w + (1-r_coef)*self._M_w_pre # Always relaxing
|
|
219
|
+
#self._Q_sen = r_coef * Q_sen + (1-r_coef)*self._Q_sen_pre
|
|
220
|
+
#self._f_load = r_coef * f_load + (1-r_coef)*self._f_load_pre
|
|
221
|
+
#self._state = state
|
|
222
|
+
#self._M_w_pre = self._M_w
|
|
223
|
+
#self._Q_sen_pre = self._Q_sen
|
|
224
|
+
#self._f_load_pre = self._f_load
|
|
225
|
+
|
|
204
226
|
self._state = state
|
|
205
|
-
self.
|
|
206
|
-
self.
|
|
207
|
-
self.
|
|
227
|
+
self._Q_sen = Q_sen
|
|
228
|
+
self._M_w = M_w
|
|
229
|
+
self._f_load = f_load
|
|
208
230
|
|
|
209
231
|
control = {"V": 0, "T": 0, "w":0, "Q":self._Q_sen, "M":self._M_w }
|
|
210
232
|
return control
|
|
211
|
-
|
|
233
|
+
|
|
234
|
+
def _economizer_perfect(self):
|
|
235
|
+
Q_required = self._space.get_Q_required(self._T_cool_sp, self._T_heat_sp)
|
|
236
|
+
if (self._economizer):
|
|
237
|
+
if (self.parameter("economizer").value == "TEMPERATURE" or self.parameter("economizer").value == "TEMPERATURE_NOT_INTEGRATED"):
|
|
238
|
+
use_economizer = self._T_odb < self._T_space-self._economizer_DT
|
|
239
|
+
elif (self.parameter("economizer").value == "ENTHALPY"):
|
|
240
|
+
h_odb = sicro.GetMoistAirEnthalpy(self._T_odb,self._w_o/1000)
|
|
241
|
+
h_space = sicro.GetMoistAirEnthalpy(self._T_space,self._w_space/1000)
|
|
242
|
+
use_economizer = h_odb < h_space
|
|
243
|
+
elif (self.parameter("economizer").value == "ENTHALPY_LIMITED"):
|
|
244
|
+
h_odb = sicro.GetMoistAirEnthalpy(self._T_odb,self._w_o/1000)
|
|
245
|
+
use_economizer = h_odb < self.parameter("economizer_enthalpy_limit").value * 1000
|
|
246
|
+
if (Q_required < 0 and use_economizer):
|
|
247
|
+
Q_rest_ae = self._mrcp * (1-self._f_oa)*(self._T_odb - self._T_space)
|
|
248
|
+
if Q_rest_ae < Q_required:
|
|
249
|
+
self._f_oa += Q_required/(self._mrcp*(self._T_odb-self._T_space))
|
|
250
|
+
Q_required = 0
|
|
251
|
+
else:
|
|
252
|
+
if (self.parameter("economizer").value == "TEMPERATURE_NOT_INTEGRATED"):
|
|
253
|
+
self._f_oa = self._outdoor_air_flow/self._supply_air_flow
|
|
254
|
+
elif (self.parameter("economizer").value == "TEMPERATURE"):
|
|
255
|
+
self._f_oa = 1
|
|
256
|
+
else:
|
|
257
|
+
self._f_oa = self._outdoor_air_flow/self._supply_air_flow
|
|
258
|
+
system_dic = {"name": self.parameter("name").value,
|
|
259
|
+
"V": self._supply_air_flow*self._f_oa,
|
|
260
|
+
"T":self._T_odb,
|
|
261
|
+
"w": self._w_o,
|
|
262
|
+
"Q":self._no_load_power,
|
|
263
|
+
"M": 0}
|
|
264
|
+
self._space.add_uncontrol_system(system_dic)
|
|
265
|
+
Q_required = self._space.get_Q_required(self._T_cool_sp, self._T_heat_sp)
|
|
266
|
+
return Q_required
|
|
267
|
+
|
|
268
|
+
|
|
212
269
|
def _air_temperature_control(self, n_iter):
|
|
213
|
-
|
|
214
|
-
T_flo = F_tot/K_tot
|
|
270
|
+
|
|
215
271
|
# Venting
|
|
216
272
|
state = 3
|
|
217
273
|
f_load = 0
|
|
218
274
|
Q_sen = 0
|
|
219
275
|
M_w = 0
|
|
220
276
|
|
|
277
|
+
# Economizer
|
|
278
|
+
T_flo, K_tot, F_tot = self._economizer_temperature()
|
|
279
|
+
|
|
280
|
+
# Mix air
|
|
281
|
+
self._T_idb, self._w_i, self._T_iwb = self._mix_air(self._f_oa, self._T_odb, self._w_o, self._T_space, self._w_space)
|
|
282
|
+
|
|
221
283
|
if (T_flo >= self._T_cool_sp - self._cool_band/2):
|
|
222
284
|
tot_cool_cap, sen_cool_cap = self._equipment.get_cooling_capacity(self._T_idb, self._T_iwb, self._T_odb,self._T_owb, self._f_air)
|
|
223
285
|
if sen_cool_cap > 0:
|
|
@@ -225,7 +287,7 @@ class HVAC_DX_system(Component):
|
|
|
225
287
|
if T_max_cap > self._T_cool_sp + self._cool_band/2:
|
|
226
288
|
state = -2
|
|
227
289
|
f_load = -1
|
|
228
|
-
Q_sen = sen_cool_cap
|
|
290
|
+
Q_sen = -sen_cool_cap
|
|
229
291
|
else:
|
|
230
292
|
state = -1
|
|
231
293
|
T_c = (F_tot+sen_cool_cap*(self._T_cool_sp - self._cool_band/2)/self._cool_band)/(K_tot + sen_cool_cap /self._cool_band)
|
|
@@ -249,18 +311,54 @@ class HVAC_DX_system(Component):
|
|
|
249
311
|
state = 1
|
|
250
312
|
|
|
251
313
|
# relaxing coef
|
|
252
|
-
r_coef = (0.01-self._r_coef)/self._n_max_iter * n_iter + self._r_coef
|
|
253
|
-
self._M_w = r_coef * M_w + (1-r_coef)*self._M_w_pre
|
|
254
|
-
self._Q_sen = r_coef * Q_sen + (1-r_coef)*self._Q_sen_pre
|
|
255
|
-
self._f_load = r_coef * f_load + (1-r_coef)*self._f_load_pre
|
|
256
|
-
self._state = state
|
|
257
|
-
self._M_w_pre = self._M_w
|
|
258
|
-
self._Q_sen_pre = self._Q_sen
|
|
259
|
-
self._f_load_pre = self._f_load
|
|
314
|
+
#r_coef = (0.01-self._r_coef)/self._n_max_iter * n_iter + self._r_coef
|
|
315
|
+
#self._M_w = r_coef * M_w + (1-r_coef)*self._M_w_pre
|
|
316
|
+
#self._Q_sen = r_coef * Q_sen + (1-r_coef)*self._Q_sen_pre
|
|
317
|
+
#self._f_load = r_coef * f_load + (1-r_coef)*self._f_load_pre
|
|
318
|
+
#self._state = state
|
|
319
|
+
#self._M_w_pre = self._M_w
|
|
320
|
+
#self._Q_sen_pre = self._Q_sen
|
|
321
|
+
#self._f_load_pre = self._f_load
|
|
260
322
|
|
|
323
|
+
self._state = state
|
|
324
|
+
self._Q_sen = Q_sen
|
|
325
|
+
self._M_w = M_w
|
|
326
|
+
self._f_load = f_load
|
|
327
|
+
|
|
261
328
|
control = {"V": 0, "T": 0, "w":0, "Q":self._Q_sen, "M":self._M_w }
|
|
262
329
|
return control
|
|
263
330
|
|
|
331
|
+
def _economizer_temperature(self):
|
|
332
|
+
K_tot, F_tot = self._space._calculate_K_F_tot(False) # Space Equation
|
|
333
|
+
T_flo = F_tot/K_tot
|
|
334
|
+
if (self._economizer):
|
|
335
|
+
if (self._T_odb < self._T_space - self._economizer_DT):
|
|
336
|
+
if (T_flo >= self._T_cool_sp - 1.5*self._cool_band and T_flo < self._T_cool_sp - 0.5*self._cool_band ):
|
|
337
|
+
f_oa_min = self._outdoor_air_flow/self._supply_air_flow
|
|
338
|
+
T_min = self._T_cool_sp - 1.5*self._cool_band
|
|
339
|
+
f_oa = (T_flo - T_min)/self._cool_band*(1-f_oa_min) + f_oa_min
|
|
340
|
+
elif (T_flo >= self._T_cool_sp - 0.5*self._cool_band):
|
|
341
|
+
if (self.parameter("economizer").value == "TEMPERATURE_NOT_INTEGRATED"):
|
|
342
|
+
f_oa = self._outdoor_air_flow/self._supply_air_flow
|
|
343
|
+
elif (self.parameter("economizer").value == "TEMPERATURE"):
|
|
344
|
+
f_oa = 1
|
|
345
|
+
else:
|
|
346
|
+
f_oa = self._outdoor_air_flow/self._supply_air_flow
|
|
347
|
+
else:
|
|
348
|
+
f_oa = self._outdoor_air_flow/self._supply_air_flow
|
|
349
|
+
|
|
350
|
+
self._f_oa = self.itera_Foa.x_next(f_oa)
|
|
351
|
+
system_dic = {"name": self.parameter("name").value,
|
|
352
|
+
"V": self._supply_air_flow*self._f_oa,
|
|
353
|
+
"T":self._T_odb,
|
|
354
|
+
"w": self._w_o,
|
|
355
|
+
"Q":self._no_load_power,
|
|
356
|
+
"M": 0}
|
|
357
|
+
self._space.add_uncontrol_system(system_dic)
|
|
358
|
+
K_tot, F_tot = self._space._calculate_K_F_tot(False) # Space Equation
|
|
359
|
+
T_flo = F_tot/K_tot
|
|
360
|
+
return T_flo, K_tot, F_tot
|
|
361
|
+
|
|
264
362
|
def post_iteration(self, time_index, date, daylight_saving, converged):
|
|
265
363
|
super().post_iteration(time_index, date, daylight_saving, converged)
|
|
266
364
|
self.variable("state").values[time_index] = self._state
|
|
@@ -274,6 +372,7 @@ class HVAC_DX_system(Component):
|
|
|
274
372
|
self.variable("F_air").values[time_index] = self._f_air
|
|
275
373
|
self.variable("F_load").values[time_index] = self._f_load
|
|
276
374
|
self.variable("power").values[time_index] = self._no_load_power
|
|
375
|
+
self.variable("outdoor_air_flow").values[time_index] = self._supply_air_flow * self._f_oa
|
|
277
376
|
|
|
278
377
|
if self._state == 1 or self._state == 2: # Heating
|
|
279
378
|
Q,power,F_COP = self._equipment.get_heating_state(self._T_idb,self._T_iwb,self._T_odb,self._T_owb,self._f_air,self._f_load)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from OpenSimula.Component import Component
|
|
2
|
-
from OpenSimula.Parameters import Parameter_component, Parameter_float
|
|
2
|
+
from OpenSimula.Parameters import Parameter_component, Parameter_float
|
|
3
3
|
from OpenSimula.Variable import Variable
|
|
4
|
+
from OpenSimula.Iterative_process import Iterative_process
|
|
4
5
|
import numpy as np
|
|
5
6
|
import psychrolib as sicro
|
|
6
7
|
import math
|
|
@@ -18,7 +19,7 @@ class Space(Component):
|
|
|
18
19
|
self.add_parameter(Parameter_float("volume", 1, "m³", min=0.0))
|
|
19
20
|
self.add_parameter(Parameter_float("furniture_weight", 10, "kg/m²", min=0.0))
|
|
20
21
|
self.add_parameter(Parameter_float("convergence_DT", 0.01, "°C", min=0.0))
|
|
21
|
-
self.add_parameter(Parameter_float("convergence_Dw", 0.
|
|
22
|
+
self.add_parameter(Parameter_float("convergence_Dw", 0.01, "g/kg", min=0.0))
|
|
22
23
|
|
|
23
24
|
# Variables
|
|
24
25
|
self.add_variable(Variable("temperature", unit="°C"))
|
|
@@ -226,12 +227,17 @@ class Space(Component):
|
|
|
226
227
|
self.control_system = {"V": 0, "T": 0, "w":0, "Q": 0, "M": 0} # V (m^3/s), T (°C), w (g/kg), Q (W), M (gr H2O)
|
|
227
228
|
# Initial values
|
|
228
229
|
self._estimate_T_w(time_index)
|
|
230
|
+
# Iterative Process
|
|
231
|
+
self.itera_T = Iterative_process(self._T,tol=self.parameter("convergence_DT").value,n_ini_relax=3,rel_vel=0.8)
|
|
232
|
+
self.itera_w = Iterative_process(self._w,tol=self.parameter("convergence_Dw").value,n_ini_relax=3,rel_vel=0.8)
|
|
233
|
+
|
|
229
234
|
# Humidity balance
|
|
230
235
|
rho = self.building().RHO
|
|
231
236
|
lam = self.building().LAMBDA
|
|
232
237
|
self._K_hum = rho * (self._volume / self._Dt + V_inf)
|
|
233
238
|
self._F_hum = (self.variable("people_latent").values[time_index] + self.variable("other_gains_latent").values[time_index])/lam
|
|
234
239
|
self._F_hum += rho * self._volume / self._Dt * self._w_pre + rho * V_inf * self._file_met.variable("abs_humidity").values[time_index]
|
|
240
|
+
|
|
235
241
|
|
|
236
242
|
def _estimate_T_w(self, time_i):
|
|
237
243
|
if time_i == 0:
|
|
@@ -247,12 +253,12 @@ class Space(Component):
|
|
|
247
253
|
|
|
248
254
|
def iteration(self, time_index, date, daylight_saving, n_iter):
|
|
249
255
|
super().iteration(time_index, date, daylight_saving, n_iter)
|
|
250
|
-
force_iteration = False
|
|
251
256
|
|
|
252
257
|
# Calculate temperature
|
|
253
258
|
K_tot,F_tot = self._calculate_K_F_tot(True)
|
|
254
259
|
T = F_tot/K_tot
|
|
255
|
-
self.variable("temperature").values[time_index] = T
|
|
260
|
+
self.variable("temperature").values[time_index] = self.itera_T.x_next(T)
|
|
261
|
+
|
|
256
262
|
# Calculate humidity
|
|
257
263
|
K_hum, F_hum = self._calculate_K_F_hum(True)
|
|
258
264
|
w = F_hum/K_hum
|
|
@@ -261,18 +267,13 @@ class Space(Component):
|
|
|
261
267
|
if (T< 100): # Sicro limits
|
|
262
268
|
max_hum = sicro.GetHumRatioFromRelHum(T, 1, self.building().ATM_PRESSURE)*1000
|
|
263
269
|
if (w > max_hum):
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
else:
|
|
269
|
-
self.variable("abs_humidity").values[time_index] = w
|
|
270
|
+
w = max_hum
|
|
271
|
+
|
|
272
|
+
self.variable("abs_humidity").values[time_index] = self.itera_w.x_next(w)
|
|
273
|
+
|
|
270
274
|
# Test convergence
|
|
271
|
-
converged = self.
|
|
272
|
-
|
|
273
|
-
return False
|
|
274
|
-
else:
|
|
275
|
-
return converged
|
|
275
|
+
converged = self.itera_T.converged() and self.itera_w.converged()
|
|
276
|
+
return converged
|
|
276
277
|
|
|
277
278
|
def _calculate_solar_direct(self, time_i):
|
|
278
279
|
solar_gain = 0
|
|
@@ -319,16 +320,6 @@ class Space(Component):
|
|
|
319
320
|
F_hum += self.control_system["V"]*rho*self.control_system["w"] + self.control_system["M"]
|
|
320
321
|
return (K_hum, F_hum)
|
|
321
322
|
|
|
322
|
-
def _converged(self, time_i):
|
|
323
|
-
converged = True
|
|
324
|
-
if abs(self._T -self.variable("temperature").values[time_i]) > self.parameter("convergence_DT").value:
|
|
325
|
-
converged = False
|
|
326
|
-
if abs(self._w -self.variable("abs_humidity").values[time_i]) > self.parameter("convergence_Dw").value:
|
|
327
|
-
converged = False
|
|
328
|
-
self._T = self.variable("temperature").values[time_i]
|
|
329
|
-
self._w = self.variable("abs_humidity").values[time_i]
|
|
330
|
-
return converged
|
|
331
|
-
|
|
332
323
|
def get_Q_required(self, T_cool_sp, T_heat_sp):
|
|
333
324
|
K_tot, F_tot = self._calculate_K_F_tot(False)
|
|
334
325
|
T = F_tot/K_tot
|
|
@@ -11,7 +11,7 @@ case_dict = {
|
|
|
11
11
|
"nominal_total_cooling_capacity": 7951,
|
|
12
12
|
"nominal_sensible_cooling_capacity": 6136,
|
|
13
13
|
"nominal_cooling_power": 2198,
|
|
14
|
-
"
|
|
14
|
+
"indoor_fan_power": 230,
|
|
15
15
|
"nominal_cooling_conditions": [26.7,19.4,35],
|
|
16
16
|
"total_cooling_capacity_expression": "9.099e-04 * T_odb + 4.351e-02 * T_iwb -3.475e-05 * T_odb**2 + 1.512e-04 * T_iwb**2 -4.703e-04 * T_odb * T_iwb + 4.281e-01",
|
|
17
17
|
"sensible_cooling_capacity_expression": "1.148e-03 * T_odb - 7.886e-02 * T_iwb + 1.044e-01 * T_idb - 4.117e-05 * T_odb**2 - 3.917e-03 * T_iwb**2 - 2.450e-03 * T_idb**2 + 4.042e-04 * T_odb * T_iwb - 4.762e-04 * T_odb * T_idb + 5.503e-03 * T_iwb * T_idb + 2.903e-01",
|
|
@@ -35,17 +35,17 @@ def test_points():
|
|
|
35
35
|
|
|
36
36
|
assert nominal[0] == pytest.approx(7951,rel=1e-2)
|
|
37
37
|
assert nominal[1] == pytest.approx(6136,rel=1e-2)
|
|
38
|
-
assert nominal[2] == pytest.approx(2198,rel=1e-2)
|
|
38
|
+
assert nominal[2] == pytest.approx(2198+230,rel=1e-2)
|
|
39
39
|
|
|
40
40
|
assert wet_coil[0] == pytest.approx(7570,rel=1e-2)
|
|
41
41
|
assert wet_coil[1] == pytest.approx(6280,rel=1e-2)
|
|
42
|
-
assert wet_coil[2] == pytest.approx(2078,rel=1e-2)
|
|
42
|
+
assert wet_coil[2] == pytest.approx(2078+230,rel=1e-2)
|
|
43
43
|
|
|
44
44
|
assert dry_coil[0] == pytest.approx(6900,rel=1e-2)
|
|
45
45
|
assert dry_coil[1] == pytest.approx(6900,rel=1e-2)
|
|
46
|
-
assert dry_coil[2] == pytest.approx(2480,rel=1e-2)
|
|
46
|
+
assert dry_coil[2] == pytest.approx(2480+230,rel=1e-2)
|
|
47
47
|
|
|
48
48
|
assert wet_coil_part_load[0] == pytest.approx( wet_coil[0]*.3)
|
|
49
49
|
assert wet_coil_part_load[1] == pytest.approx( wet_coil[1]*.3)
|
|
50
|
-
assert wet_coil_part_load[2] == pytest.approx( wet_coil[2]*0.3/(1 - 0.229*0.7))
|
|
50
|
+
assert wet_coil_part_load[2] == pytest.approx( (wet_coil[2]-230)*0.3/(1 - 0.229*0.7) +230)
|
|
51
51
|
|
|
@@ -331,8 +331,7 @@ case610_dict = {
|
|
|
331
331
|
"nominal_total_cooling_capacity": 6900,
|
|
332
332
|
"nominal_sensible_cooling_capacity": 4800,
|
|
333
333
|
"nominal_cooling_power": 2400,
|
|
334
|
-
"
|
|
335
|
-
"no_load_heat": 240,
|
|
334
|
+
"indoor_fan_power": 240,
|
|
336
335
|
"total_cooling_capacity_expression": "0.88078 + 0.014248 * T_iwb + 0.00055436 * T_iwb**2 - 0.0075581 * T_odb + 3.2983E-05 * T_odb**2 - 0.00019171 * T_odb * T_iwb",
|
|
337
336
|
"sensible_cooling_capacity_expression": "0.50060 - 0.046438 * T_iwb - 0.00032472 * T_iwb**2 - 0.013202 * T_odb + 7.9307E-05 * T_odb**2 + 0.069958 * T_idb - 3.4276E-05 * T_idb**2",
|
|
338
337
|
"cooling_power_expression": "0.11178 + 0.028493 * T_iwb - 0.00041116 * T_iwb**2 + 0.021414 * T_odb + 0.00016113 * T_odb**2 - 0.00067910 * T_odb * T_iwb",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import OpenSimula as osm
|
|
2
|
+
import math
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
def test_Iterative_process():
|
|
6
|
+
def y(x):
|
|
7
|
+
return math.cos(x)
|
|
8
|
+
x_i = 0.5
|
|
9
|
+
itera = osm.Iterative_process(x_i)
|
|
10
|
+
while not itera.converged():
|
|
11
|
+
x_i = itera.x_next(y(x_i))
|
|
12
|
+
|
|
13
|
+
assert x_i == pytest.approx(0.73908,abs=1e-4)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|