00001
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <errno.h>
00020 #include <math.h>
00021 #include "residential.h"
00022 #include "lights.h"
00023
00025
00027 CLASS* lights::oclass = NULL;
00028 CLASS* lights::pclass = NULL;
00029
00030 double lights::power_factor[_MAXTYPES] = {
00031 1.00,
00032 0.95,
00033 0.92,
00034 0.90,
00035 0.97,
00036 };
00037
00038 double lights::power_fraction[_MAXTYPES][3] = {
00039
00040 1, 0, 0,
00041 0.4, 0, 0.6,
00042 0.4, 0, 0.6,
00043 0.80, 0.1, 0.1,
00044 0.80, 0.1, 0.1,
00045 };
00046
00047
00048 lights::lights(MODULE *mod)
00049 : residential_enduse(mod)
00050 {
00051
00052 if (oclass==NULL)
00053 {
00054 pclass = residential_enduse::oclass;
00055
00056
00057 oclass = gl_register_class(mod,"lights",sizeof(lights),PC_BOTTOMUP|PC_AUTOLOCK);
00058 if (oclass==NULL)
00059 throw "unable to register class lights";
00060
00061
00062
00063
00064 else
00065 oclass->trl = TRL_QUALIFIED;
00066
00067
00068 if (gl_publish_variable(oclass,
00069 PT_INHERIT, "residential_enduse",
00070 PT_enumeration,"type",PADDR(type), PT_DESCRIPTION, "lighting type (affects power_factor)",
00071 PT_KEYWORD,"INCANDESCENT",(enumeration)INCANDESCENT,
00072 PT_KEYWORD,"FLUORESCENT",(enumeration)FLUORESCENT,
00073 PT_KEYWORD,"CFL",(enumeration)CFL,
00074 PT_KEYWORD,"SSL",(enumeration)SSL,
00075 PT_KEYWORD,"HID",(enumeration)HID,
00076 PT_enumeration,"placement",PADDR(placement), PT_DESCRIPTION, "lighting location (affects where heatgains go)",
00077 PT_KEYWORD,"INDOOR",(enumeration)INDOOR,
00078 PT_KEYWORD,"OUTDOOR",(enumeration)OUTDOOR,
00079 PT_double,"installed_power[kW]",PADDR(shape.params.analog.power), PT_DESCRIPTION, "installed lighting capacity",
00080 PT_double,"power_density[W/sf]",PADDR(power_density), PT_DESCRIPTION, "installed power density",
00081 PT_double,"curtailment[pu]", PADDR(curtailment), PT_DESCRIPTION, "lighting curtailment factor",
00082 PT_double,"demand[pu]", PADDR(shape.load), PT_DESCRIPTION, "the current lighting demand",
00083 PT_complex,"actual_power[kVA]", PADDR(lights_actual_power), PT_DESCRIPTION, "actual power demand of lights object",
00084 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00085
00086
00087
00088
00089 }
00090 }
00091
00092
00093 int lights::create(void)
00094 {
00095 int res = residential_enduse::create();
00096
00097
00098 load.name = oclass->name;
00099 load.power_fraction = load.current_fraction = load.impedance_fraction = 0;
00100 load.power = load.admittance = load.current = load.total = complex(0,0,J);
00101 load.voltage_factor = 1.0;
00102
00103 load.breaker_amps = 0;
00104
00105 return res;
00106 }
00107
00108 int lights::init(OBJECT *parent)
00109 {
00110 if(parent != NULL){
00111 if((parent->flags & OF_INIT) != OF_INIT){
00112 char objname[256];
00113 gl_verbose("lights::init(): deferring initialization on %s", gl_name(parent, objname, 255));
00114 return 2;
00115 }
00116 }
00117 OBJECT *hdr = OBJECTHDR(this);
00118 hdr->flags |= OF_SKIPSAFE;
00119
00120
00121 if(shape.load > 1.0)
00122 gl_warning("lighting load %f exceeds installed capacity", shape.load);
00123
00124
00125
00126
00127 else if (shape.load < 0.0)
00128 gl_warning("lights load %f is negative", shape.load);
00129
00130
00131
00132
00133
00134 if (load.power_factor==0)
00135 {
00136 load.power_factor = power_factor[type];
00137 gl_warning("No value was given for power factor. Defaulting to power factor 1.00 and incandescent light type.");
00138 }
00139 if (load.voltage_factor==0)
00140 {
00141 load.voltage_factor = 1.0;
00142 gl_warning("No value was given for voltage factor. Defaulting to voltage factor 1.00");
00143 }
00144 if ( (load.power_fraction + load.current_fraction + load.impedance_fraction) == 0.0)
00145 {
00146 load.power_fraction = power_fraction[type][2];
00147 load.current_fraction = power_fraction[type][1];
00148 load.impedance_fraction = power_fraction[type][0];
00149 gl_warning("No value was given for power fraction. Defaulting to incandescent light type and corresponding power fraction 1,0,0.");
00150 }
00151
00152 if (shape.type!=MT_ANALOG && shape.type != MT_UNKNOWN)
00153 throw("residential lighting only supports analog loadshapes");
00154
00155
00156
00157
00158 if (shape.params.analog.energy>0)
00159 throw("residential lighting does not support fixed energy");
00160
00161
00162
00163
00164
00165
00166 double *floor_area = parent?gl_get_double_by_name(parent, "floor_area"):NULL;
00167 if (shape.params.analog.power==0 && shape.schedule==NULL)
00168 {
00169
00170 if (power_density==0) power_density = gl_random_triangle(RNGSTATE,0.75, 1.25);
00171
00172 if(floor_area == NULL)
00173 {
00174 gl_error("lights parent must publish \'floor_area\' to work properly if no installed_power is given ~ default 2500 sf");
00175
00176
00177
00178
00179 shape.params.analog.power = power_density * 2500 / 1000;
00180 } else {
00181 shape.params.analog.power = power_density * *floor_area / 1000;
00182 }
00183 }
00184 else if (power_density==0 && shape.params.analog.power>0)
00185 {
00186 if (floor_area!=NULL)
00187 power_density = shape.params.analog.power / *floor_area ;
00188 else
00189 power_density = shape.params.analog.power / 2500;
00190 }
00191
00192
00193 if(load.breaker_amps == 0)
00194 load.breaker_amps = 40;
00195
00196 if(placement == INDOOR){
00197 load.heatgain_fraction = 0.90;
00198 } else if (placement == OUTDOOR){
00199 load.heatgain_fraction = 0.0;
00200 }
00201
00202
00203
00204
00205 return residential_enduse::init(parent);
00206 }
00207
00208 int lights::isa(char *classname)
00209 {
00210 return (strcmp(classname,"lights")==0 || residential_enduse::isa(classname));
00211 }
00212
00213 TIMESTAMP lights::sync(TIMESTAMP t0, TIMESTAMP t1)
00214 {
00215 double temp_voltage_magnitude;
00216 double val = 0.0;
00217 TIMESTAMP t2 = TS_NEVER;
00218
00219 if (pCircuit!=NULL)
00220 {
00221
00222 temp_voltage_magnitude = (pCircuit->pV->get_complex()).Mag();
00223
00224 load.voltage_factor = temp_voltage_magnitude / default_line_voltage;
00225 }
00226
00227 t2 = residential_enduse::sync(t0,t1);
00228
00229 if(shape.type == MT_UNKNOWN){
00230 double frac = shape.load * (1-curtailment);
00231 if(shape.load < 0){
00232 gl_warning("lights shape demand is negative, capping to 0");
00233 shape.load = 0.0;
00234 } else if (shape.load > 1.0){
00235 gl_warning("lights shape demand exceeds installed lighting power, capping to 100%%");
00236 shape.load = 1.0;
00237 }
00238 load.power = shape.params.analog.power * shape.load;
00239 if(fabs(load.power_factor) < 1){
00240 val = (load.power_factor<0?-1.0:1.0) * load.power.Re() * sqrt(1/(load.power_factor * load.power_factor) - 1);
00241 } else {
00242 val = 0;
00243 }
00244 load.power.SetRect(load.power.Re(), val);
00245 }
00246
00247 gl_enduse_sync(&(residential_enduse::load),t1);
00248 lights_actual_power = load.power + (load.current + load.admittance * load.voltage_factor) * load.voltage_factor;
00249
00250 return t2;
00251 }
00252
00254
00256
00257 EXPORT int create_lights(OBJECT **obj, OBJECT *parent)
00258 {
00259 try
00260 {
00261 *obj = gl_create_object(lights::oclass);
00262 if (*obj!=NULL)
00263 {
00264 lights *my = OBJECTDATA(*obj,lights);
00265 gl_set_parent(*obj,parent);
00266 return my->create();
00267 }
00268 else
00269 return 0;
00270 }
00271 CREATE_CATCHALL(lights);
00272 }
00273
00274 EXPORT int init_lights(OBJECT *obj)
00275 {
00276 try {
00277 lights *my = OBJECTDATA(obj,lights);
00278 return my->init(obj->parent);
00279 }
00280 INIT_CATCHALL(lights);
00281 }
00282
00283 EXPORT int isa_lights(OBJECT *obj, char *classname)
00284 {
00285 if(obj != 0 && classname != 0){
00286 return OBJECTDATA(obj,lights)->isa(classname);
00287 } else {
00288 return 0;
00289 }
00290 }
00291
00292 EXPORT TIMESTAMP sync_lights(OBJECT *obj, TIMESTAMP t1)
00293 {
00294 try {
00295 lights *my = OBJECTDATA(obj,lights);
00296 TIMESTAMP t2 = my->sync(obj->clock, t1);
00297 obj->clock = t1;
00298 return t2;
00299 }
00300 SYNC_CATCHALL(lights);
00301 }
00302