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
00039 lights::lights(MODULE *mod)
00040 : residential_enduse(mod)
00041 {
00042
00043 if (oclass==NULL)
00044 {
00045 pclass = residential_enduse::oclass;
00046
00047
00048 oclass = gl_register_class(mod,"lights",sizeof(lights),PC_BOTTOMUP);
00049 if (oclass==NULL)
00050 GL_THROW("unable to register object class implemented by %s",__FILE__);
00051
00052
00053
00054
00055
00056
00057 if (gl_publish_variable(oclass,
00058 PT_INHERIT, "residential_enduse",
00059 PT_enumeration,"type",PADDR(type), PT_DESCRIPTION, "lighting type (affects power_factor)",
00060 PT_KEYWORD,"INCANDESCENT",INCANDESCENT,
00061 PT_KEYWORD,"FLUORESCENT",FLUORESCENT,
00062 PT_KEYWORD,"CFL",CFL,
00063 PT_KEYWORD,"SSL",SSL,
00064 PT_KEYWORD,"HID",HID,
00065 PT_enumeration,"placement",PADDR(placement), PT_DESCRIPTION, "lighting location (affects where heatgains go)",
00066 PT_KEYWORD,"INDOOR",INDOOR,
00067 PT_KEYWORD,"OUTDOOR",OUTDOOR,
00068 PT_double,"installed_power[kW]",PADDR(shape.params.analog.power), PT_DESCRIPTION, "installed lighting capacity",
00069 PT_double,"power_density[W/sf]",PADDR(power_density), PT_DESCRIPTION, "installed power density",
00070 PT_double,"curtailment[pu]", PADDR(curtailment), PT_DESCRIPTION, "lighting curtailment factor",
00071 PT_double,"demand[pu]", PADDR(shape.load), PT_DESCRIPTION, "the current lighting demand",
00072 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00073
00074
00075
00076
00077 }
00078 }
00079
00080
00081 int lights::create(void)
00082 {
00083 int res = residential_enduse::create();
00084
00085
00086 load.name = oclass->name;
00087
00088 load.power = load.admittance = load.current = load.total = complex(0,0,J);
00089 load.voltage_factor = 1.0;
00090 load.power_factor = 0.95;
00091
00092 return res;
00093 }
00094
00095 int lights::init(OBJECT *parent)
00096 {
00097 OBJECT *hdr = OBJECTHDR(this);
00098 hdr->flags |= OF_SKIPSAFE;
00099
00100
00101 if(shape.load > 1.0)
00102 gl_warning("lighting load %f exceeds installed capacity", shape.load);
00103
00104
00105
00106
00107 else if (shape.load < 0.0)
00108 gl_warning("lights load %f is negative", shape.load);
00109
00110
00111
00112
00113
00114 if (load.power_factor==0) load.power_factor = power_factor[type];
00115 if (load.voltage_factor==0) load.voltage_factor = 1.0;
00116
00117
00118 if (shape.type!=MT_ANALOG && shape.type != MT_UNKNOWN)
00119 throw("residential lighting only supports analog loadshapes");
00120
00121
00122
00123
00124 if (shape.params.analog.energy>0)
00125 throw("residential lighting does not support fixed energy");
00126
00127
00128
00129
00130
00131
00132 double *floor_area = parent?gl_get_double_by_name(parent, "floor_area"):NULL;
00133 if (shape.params.analog.power==0 && shape.schedule==NULL)
00134 {
00135
00136 if (power_density==0) power_density = gl_random_triangle(0.75, 1.25);
00137
00138 if(floor_area == NULL)
00139 {
00140 gl_error("lights parent must publish \'floor_area\' to work properly if no installed_power is given ~ default 2500 sf");
00141
00142
00143
00144
00145 shape.params.analog.power = power_density * 2500 / 1000;
00146 } else {
00147 shape.params.analog.power = power_density * *floor_area / 1000;
00148 }
00149 }
00150 else if (power_density==0 && shape.params.analog.power>0)
00151 {
00152 if (floor_area!=NULL)
00153 power_density = shape.params.analog.power / *floor_area ;
00154 else
00155 power_density = shape.params.analog.power / 2500;
00156 }
00157
00158
00159 load.breaker_amps = 40;
00160
00161 if(placement == INDOOR){
00162 load.heatgain_fraction = 0.90;
00163 } else if (placement == OUTDOOR){
00164 load.heatgain_fraction = 0.0;
00165 }
00166
00167
00168
00169
00170 return residential_enduse::init(parent);
00171 }
00172
00173 int lights::isa(char *classname)
00174 {
00175 return (strcmp(classname,"lights")==0 || residential_enduse::isa(classname));
00176 }
00177
00178 TIMESTAMP lights::sync(TIMESTAMP t0, TIMESTAMP t1)
00179 {
00180 double val = 0.0;
00181 TIMESTAMP t2 = TS_NEVER;
00182
00183 if (pCircuit!=NULL)
00184 load.voltage_factor = pCircuit->pV->Mag() / 120;
00185
00186 t2 = residential_enduse::sync(t0,t1);
00187
00188 if(shape.type == MT_UNKNOWN){
00189 double frac = shape.load * (1-curtailment);
00190 if(shape.load < 0){
00191 gl_warning("lights shape demand is negative, capping to 0");
00192 shape.load = 0.0;
00193 } else if (shape.load > 1.0){
00194 gl_warning("lights shape demand exceeds installed lighting power, capping to 100%%");
00195 shape.load = 1.0;
00196 }
00197 load.power = shape.params.analog.power * shape.load;
00198 if(fabs(load.power_factor) < 1){
00199 val = (load.power_factor<0?-1.0:1.0) * load.power.Re() * sqrt(1/(load.power_factor * load.power_factor) - 1);
00200 } else {
00201 val = 0;
00202 }
00203 load.power.SetRect(load.power.Re(), val);
00204 }
00205
00206 gl_enduse_sync(&(residential_enduse::load),t1);
00207 return t2;
00208 }
00209
00211
00213
00214 EXPORT int create_lights(OBJECT **obj, OBJECT *parent)
00215 {
00216 *obj = gl_create_object(lights::oclass);
00217 if (*obj!=NULL)
00218 {
00219 lights *my = OBJECTDATA(*obj,lights);
00220 gl_set_parent(*obj,parent);
00221 try {
00222 my->create();
00223 }
00224 catch (char *msg)
00225 {
00226 gl_error("%s::%s.create(OBJECT **obj={name='%s', id=%d},...): %s", (*obj)->oclass->module->name, (*obj)->oclass->name, (*obj)->name, (*obj)->id, msg);
00227
00228
00229
00230
00231 return 0;
00232 }
00233 return 1;
00234 }
00235 return 0;
00236 }
00237
00238 EXPORT int init_lights(OBJECT *obj)
00239 {
00240 lights *my = OBJECTDATA(obj,lights);
00241 try {
00242 return my->init(obj->parent);
00243 }
00244 catch (char *msg)
00245 {
00246 gl_error("%s::%s.init(OBJECT *obj={name='%s', id=%d}): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, msg);
00247
00248
00249
00250
00251 return 0;
00252 }
00253 }
00254
00255 EXPORT int isa_lights(OBJECT *obj, char *classname)
00256 {
00257 if(obj != 0 && classname != 0){
00258 return OBJECTDATA(obj,lights)->isa(classname);
00259 } else {
00260 return 0;
00261 }
00262 }
00263
00264 EXPORT TIMESTAMP sync_lights(OBJECT *obj, TIMESTAMP t1)
00265 {
00266 lights *my = OBJECTDATA(obj,lights);
00267 try {
00268 TIMESTAMP t2 = my->sync(obj->clock, t1);
00269 obj->clock = t1;
00270 return t2;
00271 }
00272 catch (char *msg)
00273 {
00274 DATETIME dt;
00275 char ts[64];
00276 gl_localtime(t1,&dt);
00277 gl_strtime(&dt,ts,sizeof(ts));
00278 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);
00279
00280
00281
00282
00283 return 0;
00284 }
00285 }
00286