-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwaterheater.h
More file actions
459 lines (416 loc) · 13.5 KB
/
Copy pathwaterheater.h
File metadata and controls
459 lines (416 loc) · 13.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
/** $Id: waterheater.h 4738 2014-07-03 00:55:39Z dchassin $
Copyright (C) 2008 Battelle Memorial Institute
@file waterheater.h
@addtogroup waterheater
@ingroup residential
@{
**/
#ifndef _WATERHEATER_H
#define _WATERHEATER_H
#include "residential.h"
#include "residential_enduse.h"
#include <vector>
using std::vector;
/*
class w_vector;
class w_matrix;
//custom vector class
class w_vector {
public:
int dimension;
double *data;
public:
w_vector() {
dimension = 0;
data = NULL;
};
w_vector(int dim) {
dimension = dim;
data = new double[dimension];
for(int i=0; i<dimension; i++) {
data[i] = 0.0;
}
};
w_vector(const w_vector& v) {
dimension = v.Dimension();
data = new double[dimension];
for(int i=0; i<dimension; i++) {
data[i] = v.data[i];
}
};
w_vector(int col, const w_matrix &A){
dimension = A.Rows();
data = new double[dimension];
for(int i=0; i<A.Rows(); i++) {
data[i] = A(i,col);
}
};
~w_vector() {
dimension = 0;
delete[] data;
data = NULL;
};
void Initialize(int dim) {
if(dimension!=0)
delete[] data;
dimension = dim;
data = new double[dimension];
for(int i=0;i<dimension;i++)
data[i] = 0.0;
};
int Dimension() const { return dimension; };
void Initialize(double a) {
for(int i=0; i<dimension; i++) {
data[i] = a;
}
};
void Initialize(double *v) {
for(int i=0; i<dimension; i++) {
data[i] = v[i];
}
};
};
//custom matrix class
class w_matrix {
public:
int rows, columns;
double **data;
public:
w_matrix(int dim) {
rows = dim;
columns = dim;
data = new double* [rows];
for(int i=0; i<rows; i++) {
data[i] = new double[columns];
for(int j=0; i<columns; j++) {
data[i][j] = 0.0;
}
}
};
w_matrix(int rows1, int columns1) {
rows = rows1;
columns = columns1;
data = new double* [rows];
for(int i=0; i<rows; i++) {
data[i] = new double[columns];
for(int j=0; i<columns; j++) {
data[i][j] = 0.0;
}
}
};
w_matrix(const w_matrix& m) {
rows = m.rows;
columns = m.columns;
data = new double* [rows];
for(int i=0; i<rows; i++) {
data[i] = new double[columns];
for(int j=0; i<columns; j++) {
data[i][j] = m.data[i][j];
}
}
};
w_matrix(int num_vectors, const w_vector *q) {
rows = q[0].Dimension();
columns = num_vectors;
data = new double* [rows];
for(int i=0; i<rows; i++) {
data[i] = new double[columns];
for(int j=0; i<columns; j++) {
data[i][j] = q->data[i][j];
}
}
};
w_matrix(int rows1, int columns1, double **rowptrs){
rows = rows1;
columns = columns1;
data = new double*[rows];
for(int i=0;i<rows;i++)
data[i] = rowptrs[i];
};
~w_matrix() {
for(int i=0;i<rows;i++)
delete[] data[i];
rows = 0;
columns = 0;
delete[] data;
};
int Rows() const{ return rows; };
int Columns() const{ return columns; };
double **GetPointer() { return data; };
void GetColumn(int col, w_vector &x) {
x.Initialize(0.0);
for(int i=0; i<rows; i++) {
x[i] = data[i][col];
}
};
void GetColumn(int col, w_vector &x, int rowoffset) {
x.Initialize(0.0);
for(int i=0;i<rows-rowoffset;i++) {
x[i] = data[i+rowoffset][col];
}
};
void PutColumn(int col, const w_vector &x) {
for(int i=0;i<rows;i++) {
data[i][col] = x[i];
}
}
};
*/
class waterheater : public residential_enduse {
private:
double standby_load; ///< typical power loss through thermal jacket losses (UA 2, 60 to 140 degF, 160 BTU/hr, 47W, 411kWh/year, ~10% energy star guesstimate)
public:
typedef enum {
ONENODE=1, ///< tank model uses a single zone
TWONODE=2, ///< tank model uses two zones
FORTRAN=3, ///< uses the fortran tank model.
MULTILAYER=4, ///< tank model uses the multi-layer model
NONE=0, ///< tank model zoning isn't defined
} WHMODEL; ///< tank model currently in use
typedef enum {
DEPLETING, ///< tank heat is dropping fast
RECOVERING, ///< tank heat is rising fast
STABLE, ///< tank heat is relatively stable
} WHQFLOW; ///< tank heat flow
typedef enum {
INSIDE, ///< tank located in conditioned space
GARAGE, ///< tank located in unconditioned space
} WHLOCATION;
typedef enum {
FULL, ///< tank heat is full
PARTIAL, ///< tank heat is partial
EMPTY, ///< tank heat is empty
} WHQSTATE; ///<
typedef enum {
ELECTRIC, ///< tank heats with an electric resistance element
GASHEAT, ///< tank heats with natural gas
HEAT_PUMP ///< tank heats with a heat pump (currently ignores all electric coil usage)
} HEATMODE; ///<
// One of our main return values...
double time_to_transition; ///< time until next transition [in seconds]
// Basic characteristics defined at creation...
double Tset_curtail; ///< lower limit before we cancel curtailment [F]
double Tinlet; ///< default will be set to 60 degF
enumeration location; ///< location of tank (inside or garage) [enum]
enumeration heat_mode; ///< method of heating the water (gas or electric) [enum]
enumeration current_tank_state;
// Characteristics calculated from basics at creation...
double area; ///< tank cross-sectional area [ft^2]
double height; ///< tank height [ft]
double Ton; ///< cut-in temperature [F]
double Toff; ///< cut-out temperature [F]
double Cw; ///< thermal mass of water [Btu/F]
// The primary values we compute in our simultation...
double h; ///< boundary between hot and cold water layers [ft from top of tank]
double Tlower; ///< temperature in lower zone of tank (for 2-zone model) [F]
double Tlower_old;
double Tupper; ///< temperature in upper zone of tank (for 2-zone model) [F]
double Tupper_old;
double Twater; ///< temperature of whole tank (for 1-node model) [F]
double Tw; ///< water temperature [F]
double Tw_old; ///< previous water temperature, for internal_gains
double Tcontrol;
// Midrar's Variable start here
double Tw_hp; ///< water temperature of the heat pump water heater [F]
double energytake = 0.0; ///< The amount of energy available in the tank to heat the water to the setpoint temperaute.
double energytake_limit; ///< The amount of energy available in the tank to heat the water to the setpoint temperaute.
double energytake_old = 0.0;
double resistive_element_threshold = 0.0;
double compressor_max_threshold;
double compressor_min_threshold;
double heating_element_min_threshold;
bool heating_element_on;
double heating_ramp_rate;
double Tw_new;
double time_step = 0.0;
double compressor_power_hp = 0.0;
double hp_fan_power = 0.0;
double heating_element_power_hp = 0.0;
int interval;
int counter;
double time_step2 = 0.0;
bool turn_fan_on;
// Midrar's variables end here
// Convenience values (some pre-computed here and there for efficiency)...
bool heat_needed; ///< need to maintain this bit of state because of Tstat deadband...
double is_waterheater_on; ///< Simple logic for determining state of waterheater 1-on, 0-off
public:
double tank_volume; ///< tank size [gal]
double tank_UA; ///< tank UA [BTU/hr-F]
double tank_diameter; ///< tank diameter [ft]
double tank_height; ///< tank height [ft]
double water_demand; ///< water draw rate [gpm]
double water_demand_old; ///< previous water demand, needed for temperature change (reflects heat loss from hot water draw)
double heating_element_capacity; ///< rated Q of (each) heating element, input in W, converted to[Btu/hr]
double tank_setpoint; ///< setpoint T of heating element [F]
double thermostat_deadband; ///< deadband around Tset (half above, half below) [F]
double *pTair;
double *pTout;
double *pRH;
double HP_COP; ///< coefficient of performance for heat pump; currently calculated
double HP_COP_PSU; ///< coefficient of performance for heat pump; currently calculated
double gas_fan_power; ///< fan power draw when a gas waterheater is burning fuel
double gas_standby_power; ///< standby power draw when a gas waterheater is NOT burning fuel
double nominal_voltage;
double actual_load;
double actual_voltage;
double prev_load;
complex waterheater_actual_power; ///< the actual power draw of the object after accounting for voltage
// Fortran water heater parameters
public:
double dr_signal; //dr_signal
double simulation_time; //sim_time
double fwh_cop_current; //COP
double operating_mode; //op_mode
public:
// Tank physical parameters
double sensor_position[2]; //sensor_pos
double heater_element_power[2]; //heater_q
double heater_size[2]; //heater_size
double heater_element_position[2]; //heater_pos
double upper_element_activation_temp_offset; //upper_elem_off
double compressor_power_capacity; //comp_power
double compressor_activation_temp_offset; // comp_off
double tank_heat_loss_rate; //heat_loss_rate
double upper_fraction; //upperf
double lower_fraction; //lowerf
// Water_related_parameters
double thermal_conductivity; //water_k0
double convective_coefficient; //water_alpha
double water_heat_capacity; //water_cv
double water_density; //water_rho
// Simulation parameters
double lowest_ambient_temperature_limit; //low_amb_lim
double highest_ambient_temperature_limit; //up_amb_lim
double lowest_water_temperature_limit; //water_low_lim
double activation_temperature_offset; //mode_3_off
double ambient_air_dry_bulb_temp; //t_db
double ambient_air_wet_bulb_temp; //t_wb
double temp_set[2]; //temp_set
int coarse_tank_grid; //large_bins
int fine_tank_grid; //small_bins
int ncomp;
int nheat[2];
int heat_up;
double init_tank_temp[144];
// Time variable input parameters
double ambient_temp; //temp_amb
double inlet_water_flow; //v_flow
double inlet_water_flow_threshold; //v_flow_threshold
double ambient_rh; //hum_amb
// Output variables
double fwh_power; //power
double fwh_power_now;
double tank_water_temp[144]; //ca
double fwh_cop; //COP
double fwh_energy;
TIMESTAMP fwh_sim_time;
//Multi Layer Waterheater parameters.
private:
int number_of_mixing_zone_disks;
int total_mixing_zones;
int number_of_regular_disks;
int total_regular_zones;
int bottom_layer_disk;
int top_layer_disk;
int number_of_layers;
int number_of_states;
int number_of_inputs;
int number_of_outputs;
double H_layer;
double A_layer;
double A_bottom;
double A_top;
double V_layer;
// int Vdot_circ;
double U_val;
double Tmax_lower;
double Tmin_lower;
double Tmax_upper;
double Tmin_upper;
double a_diffusion_coefficient;
double a_loss_layer_coefficient;
double a_loss_bottom_coefficient;
double a_loss_top_coefficient;
double a_circular_const;
double b_matrix_coefficient;
vector<vector<double>> A_diffusion;
vector<vector<double>> A_loss;
vector<vector<double>> A_plug;
vector<vector<double>> A_circular_flow;
vector<double> control_upper;
vector<double> control_lower;
vector<vector<double>> T_layers;
vector<double> dT_dt;
vector<double> T_now;
vector<double> T_new;
vector<double> control_temp;
vector<double> product1;
vector<double> product2;
TIMESTAMP start_time;
TIMESTAMP next_transition_time;
TIMESTAMP last_time_calculate_state_change_called;
vector<vector<double>> A_matrix;
vector<vector<double>> B_control;
double last_water_demand;
double last_ambient_temperature;
double last_inlet_temperature;
double last_upper_thermostat_setpoint;
double last_lower_thermostat_setpoint;
enumeration last_override_value;
int last_transition_time;
bool conditions_changed;
public:
double tank_setpoint_1;
double tank_setpoint_2;
double deadband_1;
double deadband_2;
double Tw_1;
double Tw_2;
typedef enum {
OFF = 0,
ON = 1
} HEATELEMENTSTATE;
enumeration control_switch_1;
enumeration control_switch_2;
double discrete_step_size;
double Vdot_circ;
double T_mixing_valve;
public:
static CLASS *oclass, *pclass;
static waterheater *defaults;
waterheater(MODULE *mod);
~waterheater(void);
int create();
int init(OBJECT *parent);
int isa(char *classname);
void thermostat(TIMESTAMP t0, TIMESTAMP t1); // Thermostat plc control code - determines whether to heat...
TIMESTAMP presync(TIMESTAMP t0, TIMESTAMP t1);
TIMESTAMP sync(TIMESTAMP t0, TIMESTAMP t1);
TIMESTAMP postsync(TIMESTAMP t0, TIMESTAMP t1);
TIMESTAMP commit();
// Midrar's functions
void sync_energytake();
public:
enumeration current_model; ///< Discerns which water heater model we need to use
enumeration load_state; ///< Are we filling or draining the tank [enum]
enumeration tank_state(void); // Are we full, partial, or empty?
void set_time_to_transition(void); //< Sets timeToTransition...
enumeration set_current_model_and_load_state(void); // set the model and state for each cycle
void update_T_and_or_h(double); // Reset Tw and or h...
double dhdt(double h); // Calculates dh/dt...
double actual_kW(void); // Actual heat from heating element...
double new_time_1node(double T0, double T1); // Calcs time to transition...
double new_temp_1node(double T0, double delta_t); // Calcs temp after transition...
double new_time_2zone(double h0, double h1); // Calcs time to transition...
double new_h_2zone(double h0, double delta_t); // Calcs h after transition...
int multilayer_time_to_transition(void);
void calculate_waterheater_matrices(int time_now);
vector<double> multiply_waterheater_matrices(vector<vector<double>> &, vector<double> &);
void reinitialize_internals(int dt);
double get_Tambient(enumeration water_heater_location); // ambient T [F] -- either an indoor house temperature or a garage temperature, probably...
typedef enum {MODEL_NOT_1ZONE=0, MODEL_NOT_2ZONE=1} WRONGMODEL;
void wrong_model(WRONGMODEL msg);
};
#endif
/**@}**/