residential/refrigerator.cpp

Go to the documentation of this file.
00001 
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <errno.h>
00054 #include <math.h>
00055 
00056 #include "house.h"
00057 #include "refrigerator.h"
00058 
00060 // underground_line_conductor CLASS FUNCTIONS
00062 CLASS* refrigerator::oclass = NULL;
00063 refrigerator *refrigerator::defaults = NULL;
00064 
00065 
00066 
00067 refrigerator::refrigerator(MODULE *module) 
00068 {
00069     // first time init
00070     if (oclass == NULL)
00071     {
00072         oclass = gl_register_class(module,"refrigerator",PC_BOTTOMUP);
00073         if (oclass==NULL)
00074             GL_THROW("unable to register object class implemented by %s",__FILE__);
00075 
00076         // publish the class properties
00077         if (gl_publish_variable(oclass,
00078             PT_double, "size [cf]", PADDR(size),
00079             PT_double, "rated_capacity [Btu/h]", PADDR(rated_capacity),
00080             NULL) < 1)
00081             GL_THROW("unable to publish properties in %s", __FILE__);
00082 
00083         //setup default values
00084         defaults = this;
00085         size = gl_random_uniform(20,40); // cf
00086 
00087         // basic random properties
00088         thermostat_deadband = gl_random_uniform(2,3);
00089         Tset = gl_random_uniform(35,39);
00090         UAr = 1.5+size/40*gl_random_uniform(0.9,1.1);
00091         UAf = gl_random_uniform(0.9,1.1);
00092         COPcoef = gl_random_uniform(0.9,1.1);
00093         
00094         // size is used to couple Cw and Qrated
00095         Cf = 8.43 * size/10; // BTU equivalent gallons of water for only 10% of the size of the refigerator
00096         rated_capacity = BTUPHPW * size*10; // BTU/h
00097 
00098         // duty cycle estimate
00099         if (gl_random_uniform(0,1)<0.04)
00100             Qr = rated_capacity;
00101         else
00102             Qr = 0;
00103 
00104         // derived properties and other initial conditions
00105         Tair = gl_random_uniform(Tset-thermostat_deadband,Tset+thermostat_deadband);
00106 
00107         Tout = 59.0;
00108         power_factor = 0.95;
00109 
00110     }
00111 }
00112 
00113 refrigerator::~refrigerator()
00114 {
00115 }
00116 
00117 int refrigerator::init(OBJECT *parent)
00118 {
00119     if (parent==NULL)
00120     {
00121         gl_error("refrigerator must have a parent house");
00122         return 0;
00123     }
00124     pHouse = OBJECTDATA(parent,house);
00125 
00126     // attach object to house panel
00127     pVoltage = (pHouse->attach(OBJECTHDR(this),20,false))->pV;
00128 
00129     // initial demand
00130     power_kw = rated_capacity*KWPBTUPH;  //stubbed-in default
00131 
00132     return 1;
00133 }
00134 
00135 int refrigerator::create() 
00136 {
00137     memcpy(this, defaults, sizeof(*this));
00138     return 1;
00139 }
00140 
00141 
00142 TIMESTAMP refrigerator::sync(TIMESTAMP t0, TIMESTAMP t1) 
00143 {
00144     double nHours = (gl_tohours(t1)- gl_tohours(t0))/TS_SECOND;
00145 
00146     // sync to house
00147     Tout = pHouse->get_Tair();
00148 
00149     // compute control event temperatures
00150     const double Ton = Tset+thermostat_deadband;
00151     const double Toff = Tset-thermostat_deadband;
00152 
00153     // compute constants
00154     const double C1 = Cf/(UAr*UAf);
00155     const double COP = COPcoef*((-3.5/45)*(Tout-70)+4.5);
00156 
00157     // accumulate energy
00158     kwh_meter = Qr*KWPBTUPH*COP*nHours;
00159     power_kw = kwh_meter/nHours;
00160 
00161     // process all events
00162     // change control mode if appropriate
00163     if (ANE(Qr,0,0.1) && ALT(Tair,Toff,0.1))
00164         Qr = 0;
00165     else if (AEQ(Qr,0,0.1) && AGT(Tair,Ton,0.1))
00166         Qr = rated_capacity;
00167 
00168     // compute constants for this time increment
00169     const double C2 = Tout - Qr/UAf;
00170 
00171     // determine next internal event temperature
00172     double Tevent;
00173     if (AEQ(Qr,0,0.1))
00174         Tevent = Ton;
00175     else
00176         Tevent = Toff;
00177 
00178     // compute time to next internal event
00179     double t = -log((Tevent - C2)/(Tair-C2))*C1;
00180     double dt = t;
00181     if (t==0)
00182         throw "refrigerator control logic error";
00183 
00184     // if fridge is undersized or time exceeds balance of time or external event pending
00185     if (t<0 || t>=nHours)
00186     {
00187         dt = ((t<0||t>=nHours)?nHours:t);
00188 
00189         // update temperature of air
00190         Tair = (Tair-C2)*exp(-dt/C1)+C2;
00191         if (Tair < 32 || Tair > 55)
00192             throw "refrigerator air temperature out of control";
00193 
00194         return (TIMESTAMP)(t1+dt*3600.0/TS_SECOND);
00195     }
00196     // internal event
00197     else
00198     {
00199         Tair = Tevent;
00200         return TS_NEVER; 
00201     }
00202 }
00203 
00204 
00206 // IMPLEMENTATION OF CORE LINKAGE
00208 EXPORT int create_refrigerator(OBJECT **obj, OBJECT *parent)
00209 {
00210     *obj = gl_create_object(refrigerator::oclass,sizeof(refrigerator));
00211     if (*obj!=NULL)
00212     {
00213         refrigerator *my = OBJECTDATA(*obj,refrigerator);;
00214         gl_set_parent(*obj,parent);
00215         my->create();
00216         return 1;
00217     }
00218     return 0;
00219 }
00220 
00221 EXPORT int init_refrigerator(OBJECT *obj)
00222 {
00223     refrigerator *my = OBJECTDATA(obj,refrigerator);
00224     return my->init(obj->parent);
00225 }
00226 
00227 EXPORT TIMESTAMP sync_refrigerator(OBJECT *obj, TIMESTAMP t0)
00228 {
00229     TIMESTAMP t1 = ((refrigerator*)(obj+1))->sync(obj->clock, t0);
00230     obj->clock = t0;
00231     return t1;
00232 }
00233 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy