-
Notifications
You must be signed in to change notification settings - Fork 0
/
microwave.cpp
361 lines (317 loc) · 9.64 KB
/
microwave.cpp
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
/** $Id: microwave.cpp,v 1.14 2008/02/13 02:22:35 d3j168 Exp $
Copyright (C) 2008 Battelle Memorial Institute
@file microwave.cpp
@addtogroup microwave
@ingroup residential
The microwave simulation is based on a demand profile attached to the object.
The internal heat gain is calculated using a specified fraction of installed power.
@{
**/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
#include "house_a.h"
#include "microwave.h"
//////////////////////////////////////////////////////////////////////////
// microwave CLASS FUNCTIONS
//////////////////////////////////////////////////////////////////////////
CLASS* microwave::oclass = NULL;
CLASS* microwave::pclass = NULL;
microwave::microwave(MODULE *module) : residential_enduse(module)
{
// first time init
if (oclass==NULL)
{
// register the class definition
oclass = gl_register_class(module,"microwave",sizeof(microwave),PC_BOTTOMUP);
if (oclass==NULL)
GL_THROW("unable to register object class implemented by %s",__FILE__);
// publish the class properties
if (gl_publish_variable(oclass,
PT_INHERIT, "residential_enduse",
PT_double,"installed_power[kW]",PADDR(shape.params.analog.power),PT_DESCRIPTION,"rated microwave power level",
PT_double,"standby_power[kW]",PADDR(standby_power),PT_DESCRIPTION,"standby microwave power draw (unshaped only)",
PT_double,"circuit_split",PADDR(circuit_split),
PT_enumeration,"state",PADDR(state),PT_DESCRIPTION,"on/off state of the microwave",
PT_KEYWORD,"OFF",OFF,
PT_KEYWORD,"ON",ON,
PT_double,"cycle_length[s]",PADDR(cycle_time),PT_DESCRIPTION,"length of the combined on/off cycle between uses",
PT_double,"runtime[s]",PADDR(runtime),PT_DESCRIPTION,"",
PT_double,"state_time[s]",PADDR(state_time),PT_DESCRIPTION,"",
NULL)<1)
GL_THROW("unable to publish properties in %s",__FILE__);
}
}
microwave::~microwave()
{
}
int microwave::create()
{
int res = residential_enduse::create();
// name of enduse
load.name = oclass->name;
load.power = load.admittance = load.current = load.total = complex(0,0,J);
load.heatgain_fraction = 0.25;
load.power_factor = 0.95;
standby_power = 0.01;
shape.load = gl_random_uniform(0, 0.1); // assuming a default maximum 10% of the sync time
gl_warning("explicit %s model is experimental", OBJECTHDR(this)->oclass->name);
return res;
}
/* basic checks on unshaped microwaves. on failure, don't play games, just throw exceptions. */
void microwave::init_noshape(){
if(shape.params.analog.power < 0){
GL_THROW("microwave power must be positive (read as %f)", shape.params.analog.power);
} else if (shape.params.analog.power > 4.000){
GL_THROW("microwave power can not exceed 4 kW (and most don't exceed 2 kW)");
}
if(shape.params.analog.power < 0.700){
gl_warning("microwave installed power is smaller than traditional microwave ovens");
} else if(shape.params.analog.power > 1.800){
gl_warning("microwave installed power is greater than traditional microwave ovens");
}
if(standby_power < 0){
gl_warning("negative standby power, reseting to 1%% of installed power");
standby_power = shape.params.analog.power * 0.01;
} else if(standby_power > shape.params.analog.power){
gl_warning("standby power exceeds installed power, reseting to 1%% of installed power");
standby_power = shape.params.analog.power * 0.01;
}
if(cycle_time < 0){
GL_THROW("negative cycle_length is an invalid value");
}
if(cycle_time > 14400){
gl_warning("cycle_length is abnormally long and may give unusual results");
}
}
int microwave::init(OBJECT *parent)
{
OBJECT *hdr = OBJECTHDR(this);
hdr->flags |= OF_SKIPSAFE;
if (load.voltage_factor==0) load.voltage_factor = 1.0;
if(shape.type == MT_UNKNOWN){
init_noshape();
// initial demand
update_state(0.0);
} else if(shape.type == MT_ANALOG){
if(1){
;
}
} else if(shape.type == MT_PULSED){
if(1){
;
}
} else if(shape.type == MT_MODULATED){
if(1){
;
}
} else if(shape.type == MT_QUEUED){
gl_warning("queued loadshapes not supported ~ will attempt to run as an unshaped load");
shape.type = MT_UNKNOWN;
init_noshape();
// initial demand
update_state(0.0);
} else {
gl_error("unrecognized loadshape");
return 0;
}
load.total = load.power = standby_power;
// waiting this long to initialize the parent class is normal
return residential_enduse::init(parent);
}
int microwave::isa(char *classname)
{
return (strcmp(classname,"microwave")==0 || residential_enduse::isa(classname));
}
// periodically activates for the tail demand % of a cycle_time period. Has a random offset to prevent
// lock-step behavior across uniform devices
// start ....... on .. off
TIMESTAMP microwave::update_state_cycle(TIMESTAMP t0, TIMESTAMP t1){
double ti0 = (double)t0, ti1 = (double)t1;
if(shape.load == 0){
state = OFF;
cycle_start = 0;
return TS_NEVER;
}
if(shape.load == 1){
state = ON;
cycle_start = 0;
return TS_NEVER;
}
if(cycle_start == 0){
double off = gl_random_uniform(0, this->cycle_time);
cycle_start = ti1 + off;
cycle_on = (1 - shape.load) * cycle_time + cycle_start;
cycle_off = cycle_time + cycle_start;
state = OFF;
return (TIMESTAMP)cycle_on;
}
if(t0 == cycle_on){
state = ON;
}
if(t0 == cycle_off){
state = OFF;
cycle_start = cycle_off;
}
if(t0 == cycle_start){
cycle_on = (1 - shape.load) * cycle_time + cycle_start;
state = OFF;
cycle_off = cycle_time + cycle_start;
}
if(state == ON)
return (TIMESTAMP)cycle_off;
if(state == OFF)
return (TIMESTAMP)cycle_on;
return TS_NEVER; // from ambiguous state
}
double microwave::update_state(double dt)
{
// run times (used for gl_random_sample()) - DPC: this is an educated guess, the true PDF needs to be researched
static double rt[] = {30,30,30,30,30,30,30,30,30,30,60,60,60,60,90,90,120,150,180,450,600};
static double sumrt = 2520; // sum(pdf) -- you do the math
static double avgrt = sumrt/sizeof(rt);
if(shape.load < 0.0){
gl_warning("microwave demand less than 0, reseting to zero");
shape.load = 0.0;
}
if(shape.load > 1.0){
gl_warning("microwave demand greater than 1, reseting to one");
shape.load = 1.0;
}
switch (state) {
case OFF:
// new OFF state or demand changed
if (state_time == 0 || prev_demand != shape.load)
{
if(shape.load != 0.0){
runtime = avgrt * (1 - shape.load) / shape.load;
}
else {
runtime = 0.0;
return 0; /* don't run the microwave */
}
prev_demand = shape.load;
state_time = 0; // important that state time be reset to prevent increase in demand from causing immediate state change
}
// time for state change
if (state_time>runtime)
{
state = ON;
runtime = gl_random_sampled(sizeof(rt)/sizeof(rt[0]),rt);
state_time = 0;
}
else
state_time += dt;
break;
case ON:
// power outage or runtime expired
runtime = floor(runtime);
if (pCircuit->pV->Mag() < 0.25 || state_time>runtime)
{
state = OFF;
state_time = 0;
}
else
state_time += dt;
break;
default:
throw "unknown microwave state";
/* TROUBLESHOOT
The microwave is neither on nor off. Please initialize the "state" variable
to either "ON" or "OFF".
*/
}
return runtime;
}
TIMESTAMP microwave::sync(TIMESTAMP t0, TIMESTAMP t1)
{
TIMESTAMP ct = 0;
double dt = 0;
double val = 0.0;
TIMESTAMP t2 = TS_NEVER;
if (t0 <= 0)
return TS_NEVER;
if (pCircuit!=NULL)
load.voltage_factor = pCircuit->pV->Mag() / 120; // update voltage factor
t2 = residential_enduse::sync(t0,t1);
if(shape.type == MT_UNKNOWN){
if(cycle_time > 0){
ct = update_state_cycle(t0, t1);
} else {
dt = update_state(gl_toseconds(t1-t0));
}
load.power.SetPowerFactor( (state==ON ? shape.params.analog.power : standby_power), load.power_factor);
}
gl_enduse_sync(&(residential_enduse::load),t1);
if(shape.type == MT_UNKNOWN){
if(cycle_time == 0)
return dt>0?-(TIMESTAMP)(t1 + dt*TS_SECOND) : TS_NEVER; // negative time means soft transition
else
return ct == TS_NEVER ? TS_NEVER : -ct;
} else {
return t2;
}
}
//////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION OF CORE LINKAGE
//////////////////////////////////////////////////////////////////////////
EXPORT int create_microwave(OBJECT **obj, OBJECT *parent)
{
*obj = gl_create_object(microwave::oclass);
if (*obj!=NULL)
{
microwave *my = OBJECTDATA(*obj,microwave);;
gl_set_parent(*obj,parent);
my->create();
return 1;
}
return 0;
}
EXPORT int init_microwave(OBJECT *obj)
{
microwave *my = OBJECTDATA(obj,microwave);
try {
return my->init(obj->parent);
}
catch (const char *msg)
{
gl_error("%s::%s.init(OBJECT *obj={name='%s', id=%d}): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, msg);
/* TROUBLESHOOT
The initialization operation of the specified object failed.
The message given provide additional details and can be looked up under the Exceptions section.
*/
return 0;
}
}
EXPORT int isa_microwave(OBJECT *obj, char *classname)
{
if(obj != 0 && classname != 0){
return OBJECTDATA(obj,microwave)->isa(classname);
} else {
return 0;
}
}
EXPORT TIMESTAMP sync_microwave(OBJECT *obj, TIMESTAMP t0)
{
microwave *my = OBJECTDATA(obj, microwave);
try {
TIMESTAMP t2 = my->sync(obj->clock, t0);
obj->clock = t0;
return t2;
}
catch (char *msg)
{
DATETIME dt;
char ts[64];
gl_localtime(t0,&dt);
gl_strtime(&dt,ts,sizeof(ts));
gl_error("%s::%s.init(OBJECT **obj={name='%s', id=%d},TIMESTAMP t1='%s'): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, ts, msg);
/* TROUBLESHOOT
The synchronization operation of the specified object failed.
The message given provide additional details and can be looked up under the Exceptions section.
*/
return 0;
}
}
/**@}**/