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