00001
00013 #include <stdlib.h>
00014 #include <stdio.h>
00015 #include <errno.h>
00016 #include <math.h>
00017
00018 #include "microwave.h"
00019
00021
00023 CLASS* microwave::oclass = NULL;
00024 CLASS* microwave::pclass = NULL;
00025
00026 microwave::microwave(MODULE *module) : residential_enduse(module)
00027 {
00028
00029 if (oclass==NULL)
00030 {
00031
00032 oclass = gl_register_class(module,"microwave",sizeof(microwave),PC_BOTTOMUP|PC_AUTOLOCK);
00033 if (oclass==NULL)
00034 throw "unable to register class microwave";
00035 else
00036 oclass->trl = TRL_DEMONSTRATED;
00037
00038
00039 if (gl_publish_variable(oclass,
00040 PT_INHERIT, "residential_enduse",
00041 PT_double,"installed_power[kW]",PADDR(shape.params.analog.power),PT_DESCRIPTION,"rated microwave power level",
00042 PT_double,"standby_power[kW]",PADDR(standby_power),PT_DESCRIPTION,"standby microwave power draw (unshaped only)",
00043 PT_double,"circuit_split",PADDR(circuit_split),
00044 PT_enumeration,"state",PADDR(state),PT_DESCRIPTION,"on/off state of the microwave",
00045 PT_KEYWORD,"OFF",OFF,
00046 PT_KEYWORD,"ON",ON,
00047
00048 PT_double,"cycle_length[s]",PADDR(cycle_time),PT_DESCRIPTION,"length of the combined on/off cycle between uses",
00049 PT_double,"runtime[s]",PADDR(runtime),PT_DESCRIPTION,"",
00050 PT_double,"state_time[s]",PADDR(state_time),PT_DESCRIPTION,"",
00051 NULL)<1)
00052 GL_THROW("unable to publish properties in %s",__FILE__);
00053 }
00054 }
00055
00056 microwave::~microwave()
00057 {
00058 }
00059
00060 int microwave::create()
00061 {
00062 int res = residential_enduse::create();
00063
00064
00065 load.name = oclass->name;
00066 load.power = load.admittance = load.current = load.total = complex(0,0,J);
00067
00068 load.heatgain_fraction = 0.25;
00069 load.power_factor = 0.95;
00070
00071 standby_power = 0.01;
00072 shape.load = gl_random_uniform(RNGSTATE,0, 0.1);
00073
00074 gl_warning("explicit %s model is experimental", OBJECTHDR(this)->oclass->name);
00075
00076 return res;
00077 }
00078
00079
00080 void microwave::init_noshape(){
00081 if(shape.params.analog.power < 0){
00082 GL_THROW("microwave power must be positive (read as %f)", shape.params.analog.power);
00083 } else if (shape.params.analog.power > 4.000){
00084 GL_THROW("microwave power can not exceed 4 kW (and most don't exceed 2 kW)");
00085 }
00086 if(shape.params.analog.power < 0.700){
00087 gl_warning("microwave installed power is smaller than traditional microwave ovens");
00088 } else if(shape.params.analog.power > 1.800){
00089 gl_warning("microwave installed power is greater than traditional microwave ovens");
00090 }
00091 if(standby_power < 0){
00092 gl_warning("negative standby power, resetting to 1%% of installed power");
00093 standby_power = shape.params.analog.power * 0.01;
00094 } else if(standby_power > shape.params.analog.power){
00095 gl_warning("standby power exceeds installed power, resetting to 1%% of installed power");
00096 standby_power = shape.params.analog.power * 0.01;
00097 }
00098 if(cycle_time < 0){
00099 GL_THROW("negative cycle_length is an invalid value");
00100 }
00101 if(cycle_time > 14400){
00102 gl_warning("cycle_length is abnormally long and may give unusual results");
00103 }
00104 }
00105
00106 int microwave::init(OBJECT *parent)
00107 {
00108 if(parent != NULL){
00109 if((parent->flags & OF_INIT) != OF_INIT){
00110 char objname[256];
00111 gl_verbose("microwave::init(): deferring initialization on %s", gl_name(parent, objname, 255));
00112 return 2;
00113 }
00114 }
00115 OBJECT *hdr = OBJECTHDR(this);
00116 hdr->flags |= OF_SKIPSAFE;
00117
00118 if (load.voltage_factor==0) load.voltage_factor = 1.0;
00119
00120 if(shape.type == MT_UNKNOWN){
00121 init_noshape();
00122 gl_warning("This device, %s, is considered very experimental and has not been validated.", get_name());
00123
00124 update_state(0.0);
00125 } else if(shape.type == MT_ANALOG){
00126 if(1){
00127 ;
00128 }
00129 } else if(shape.type == MT_PULSED){
00130 if(1){
00131 ;
00132 }
00133 } else if(shape.type == MT_MODULATED){
00134 if(1){
00135 ;
00136 }
00137 } else if(shape.type == MT_QUEUED){
00138 gl_error("queued loadshapes not supported ~ will attempt to run as an unshaped load");
00139 shape.type = MT_UNKNOWN;
00140 init_noshape();
00141
00142 update_state(0.0);
00143 } else {
00144 gl_error("unrecognized loadshape");
00145 return 0;
00146 }
00147 load.total = load.power = standby_power;
00148
00149
00150 return residential_enduse::init(parent);
00151 }
00152
00153 int microwave::isa(char *classname)
00154 {
00155 return (strcmp(classname,"microwave")==0 || residential_enduse::isa(classname));
00156 }
00157
00158
00159
00160
00161 TIMESTAMP microwave::update_state_cycle(TIMESTAMP t0, TIMESTAMP t1){
00162 double ti0 = (double)t0, ti1 = (double)t1;
00163
00164 if(shape.load == 0){
00165 state = OFF;
00166 cycle_start = 0;
00167 return TS_NEVER;
00168 }
00169
00170 if(shape.load == 1){
00171 state = ON;
00172 cycle_start = 0;
00173 return TS_NEVER;
00174 }
00175
00176 if(cycle_start == 0){
00177 double off = gl_random_uniform(RNGSTATE,0, this->cycle_time);
00178 cycle_start = (TIMESTAMP)(ti1 + off);
00179 cycle_on = (TIMESTAMP)((1 - shape.load) * cycle_time) + cycle_start;
00180 cycle_off = (TIMESTAMP)cycle_time + cycle_start;
00181 state = OFF;
00182 return (TIMESTAMP)cycle_on;
00183 }
00184
00185 if(t0 == cycle_on){
00186 state = ON;
00187 }
00188 if(t0 == cycle_off){
00189 state = OFF;
00190 cycle_start = cycle_off;
00191 }
00192 if(t0 == cycle_start){
00193 cycle_on = (TIMESTAMP)((1 - shape.load) * cycle_time) + cycle_start;
00194 state = OFF;
00195 cycle_off = (TIMESTAMP)cycle_time + cycle_start;
00196 }
00197
00198 if(state == ON)
00199 return (TIMESTAMP)cycle_off;
00200 if(state == OFF)
00201 return (TIMESTAMP)cycle_on;
00202 return TS_NEVER;
00203 }
00204
00205 double microwave::update_state(double dt)
00206 {
00207 double temp_voltage_magnitude;
00208
00209 static double rt[] = {30,30,30,30,30,30,30,30,30,30,60,60,60,60,90,90,120,150,180,450,600};
00210 static double sumrt = 2520;
00211 static double avgrt = sumrt/sizeof(rt);
00212
00213 if(shape.load < 0.0){
00214 gl_error("microwave demand less than 0, reseting to zero");
00215 shape.load = 0.0;
00216 }
00217 if(shape.load > 1.0){
00218 gl_error("microwave demand greater than 1, reseting to one");
00219 shape.load = 1.0;
00220 }
00221 switch (state) {
00222 case OFF:
00223
00224 if (state_time == 0 || prev_demand != shape.load)
00225 {
00226 if(shape.load != 0.0){
00227 runtime = avgrt * (1 - shape.load) / shape.load;
00228 }
00229 else {
00230 runtime = 0.0;
00231 return 0;
00232 }
00233 prev_demand = shape.load;
00234 state_time = 0;
00235 }
00236
00237
00238 if (state_time>runtime)
00239 {
00240 state = ON;
00241 runtime = gl_random_sampled(RNGSTATE,sizeof(rt)/sizeof(rt[0]),rt);
00242 state_time = 0;
00243 }
00244 else
00245 state_time += dt;
00246 break;
00247 case ON:
00248
00249 runtime = floor(runtime);
00250
00251
00252 temp_voltage_magnitude = (pCircuit->pV->get_complex()).Mag();
00253
00254 if (temp_voltage_magnitude < 0.25 || state_time>runtime)
00255 {
00256 state = OFF;
00257 state_time = 0;
00258 }
00259 else
00260 state_time += dt;
00261 break;
00262 default:
00263 throw "unknown microwave state";
00264
00265
00266
00267
00268 }
00269
00270 return runtime;
00271 }
00272
00273 TIMESTAMP microwave::sync(TIMESTAMP t0, TIMESTAMP t1)
00274 {
00275 TIMESTAMP ct = 0;
00276 double temp_voltage_magnitude;
00277 double dt = 0;
00278 double val = 0.0;
00279 TIMESTAMP t2 = TS_NEVER;
00280
00281 if (t0 <= 0)
00282 return TS_NEVER;
00283
00284 if (pCircuit!=NULL)
00285 {
00286
00287 temp_voltage_magnitude = (pCircuit->pV->get_complex()).Mag();
00288
00289 load.voltage_factor = temp_voltage_magnitude / default_line_voltage;
00290 }
00291
00292 t2 = residential_enduse::sync(t0,t1);
00293
00294 if(shape.type == MT_UNKNOWN){
00295 if(cycle_time > 0){
00296 ct = update_state_cycle(t0, t1);
00297 } else {
00298 dt = update_state(gl_toseconds(t1-t0));
00299 }
00300 load.power.SetPowerFactor( (state==ON ? shape.params.analog.power : standby_power), load.power_factor);
00301 }
00302
00303 gl_enduse_sync(&(residential_enduse::load),t1);
00304
00305 if(shape.type == MT_UNKNOWN){
00306 if(cycle_time == 0)
00307 return dt>0?-(TIMESTAMP)(t1 + dt*TS_SECOND) : TS_NEVER;
00308 else
00309 return ct == TS_NEVER ? TS_NEVER : -ct;
00310 } else {
00311 return t2;
00312 }
00313 }
00314
00316
00318
00319 EXPORT int create_microwave(OBJECT **obj, OBJECT *parent)
00320 {
00321 try
00322 {
00323 *obj = gl_create_object(microwave::oclass);
00324 if (*obj!=NULL)
00325 {
00326 microwave *my = OBJECTDATA(*obj,microwave);;
00327 gl_set_parent(*obj,parent);
00328 my->create();
00329 return 1;
00330 }
00331 else
00332 return 0;
00333 }
00334 CREATE_CATCHALL(microwave);
00335
00336 }
00337
00338 EXPORT int init_microwave(OBJECT *obj)
00339 {
00340 try {
00341 microwave *my = OBJECTDATA(obj,microwave);
00342 return my->init(obj->parent);
00343 }
00344 INIT_CATCHALL(microwave);
00345 }
00346
00347 EXPORT int isa_microwave(OBJECT *obj, char *classname)
00348 {
00349 if(obj != 0 && classname != 0){
00350 return OBJECTDATA(obj,microwave)->isa(classname);
00351 } else {
00352 return 0;
00353 }
00354 }
00355
00356 EXPORT TIMESTAMP sync_microwave(OBJECT *obj, TIMESTAMP t0)
00357 {
00358 try {
00359 microwave *my = OBJECTDATA(obj, microwave);
00360 TIMESTAMP t2 = my->sync(obj->clock, t0);
00361 obj->clock = t0;
00362 return t2;
00363 }
00364 SYNC_CATCHALL(microwave);
00365 }
00366