climate/climate.cpp

Go to the documentation of this file.
00001 
00006 #include <stdlib.h>
00007 #include <stdio.h>
00008 #include <errno.h>
00009 #include <math.h>
00010 
00011 #include "climate.h"
00012 #include "solar_angles.h"
00013 
00014 #define RAD(x) (x*PI)/180
00015                          //ET,CT,MT ,PT ,AT, HT
00016 double std_meridians[] = {75,90,105,120,135,150};
00017 double surface_angles[8] = {0,45,-45,90,-90,135,-135,180};
00018 
00028 int tmy2_reader::open(const char *file){
00029     char *newname = gl_findfile((char *)file, NULL, 2);
00030     if (newname==NULL)
00031         return 0;
00032     fp = fopen(newname, "r");
00033 
00034     if(fp == NULL){
00035         return 0;
00036     }
00037     
00038     // read in the header (use the c code given in the manual)
00039     fgets(buf,500,fp);
00040     sscanf(buf,"%*s %s %s %d %*s %d %d %*s %d %d",data_city,data_state,&tz_offset,&lat_degrees,&lat_minutes,&long_degrees,&long_minutes);
00041     return 4;
00042 }
00043 
00044 int tmy2_reader::next(){
00045     // read the next line into the buffer using fgets.
00046     char *val;
00047     val = fgets(buf,500,fp);
00048     
00049     if(val != NULL)
00050         return 1;
00051     else
00052         return 0;
00053 }
00054 
00055 int tmy2_reader::header_info(char* city, char* state, int* degrees, int* minutes, int* long_deg, int* long_min){
00056     strcpy(city,data_city);
00057     strcpy(state,data_state);
00058     *degrees = lat_degrees;
00059     *minutes = lat_minutes;
00060     *long_deg = long_degrees;
00061     *long_min = long_minutes;
00062     return 1;
00063 }
00064 
00065 int tmy2_reader::read_data(double *dnr, double *dhr, double *tdb, double *rh, int* month, int* day, int* hour){
00066     int tmp_dnr, tmp_dhr, tmp_tdb, tmp_rh;
00067     //sscanf(buf, "%*2s%2d%2d%2d%*14s%4d%*2s%4d%*40s%4d%8*s%3d%*s",month,day,hour,&tmp_dnr,&tmp_dhr,&tmp_tdb,&tmp_rh);
00068     sscanf(buf, "%*2s%2d%2d%2d%*14s%4d%*2s%4d%*34s%4d%8*s%3d%*s",month,day,hour,&tmp_dnr,&tmp_dhr,&tmp_tdb,&tmp_rh);
00069                 /* 3__5__7__9___23_27__29_33___67_71_79__82 */
00070     *dnr = tmp_dnr;
00071     *dhr = tmp_dhr;
00072     *tdb = ((double)tmp_tdb)/10.0;
00073     /* *tdb = ((double)tmp_tdb)/10.0 * 9.0 / 5.0 + 32.0; */
00074     *rh = ((double)tmp_rh)/100.0;
00075     return 1;
00076 }
00077 
00078 double tmy2_reader::calc_solar(COMPASS_PTS cpt, short doy, double lat, double sol_time, double dnr, double dhr,double vert_angle = 90)
00079 {
00080     SolarAngles *sa = new SolarAngles();
00081     double surface_angle = surface_angles[cpt];
00082     double cos_incident = sa->cos_incident(lat,RAD(vert_angle),RAD(surface_angle),sol_time,doy);
00083 
00084     return (double)dnr * cos_incident + dhr;
00085 }
00086 
00087 void tmy2_reader::close(){
00088     fclose(fp);
00089 }
00090 
00099 CLASS *climate::oclass = NULL;
00100 climate *climate::defaults = NULL;
00101 
00102 climate::climate(MODULE *module)
00103 {
00104     if (oclass==NULL)
00105     {
00106         oclass = gl_register_class(module,"climate",PC_BOTTOMUP); 
00107         if (gl_publish_variable(oclass,
00108             PT_char32, "city", PADDR(city),
00109             PT_char1024,"tmyfile",PADDR(tmyfile),
00110             PT_double,"temperature[degF]",PADDR(temperature),
00111             PT_double,"humidity[%]",PADDR(humidity),
00112             PT_double,"solar_flux[W/sf]",PADDR(solar_flux),
00113                 PT_SIZE, 9,
00114             NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00115         strcpy(city,"");
00116         strcpy(tmyfile,"");
00117         temperature = 59.0;
00118         temperature_raw = 15.0;
00119         humidity = 0.75;
00120         //solar_flux = malloc(8 * sizeof(double));
00121         solar_flux[0] = solar_flux[1] = solar_flux[2] = solar_flux[3] = solar_flux[4] = solar_flux[5] = solar_flux[6] = solar_flux[7] = solar_flux[8] = 0.0; // W/sf normal
00122         //solar_flux_S = solar_flux_SE = solar_flux_SW = solar_flux_E = solar_flux_W = solar_flux_NE = solar_flux_NW = solar_flux_N = 0.0; // W/sf normal
00123         tmy = NULL;
00124         defaults = this;
00125     }
00126 }
00127 
00128 int climate::create(void) 
00129 {
00130     memcpy(this,defaults,sizeof(*this));
00131     return 1;
00132 }
00133 
00134 int climate::init(OBJECT *parent)
00135 {
00136     // ignore "" files
00137     if (strcmp(tmyfile,"")==0)
00138         return 1;
00139     
00140     // open access to the TMY file
00141     char *found_file = gl_findfile(tmyfile,getenv("GLPATH"),FF_READ);
00142     if (found_file==NULL || file.open(found_file)<3) // TODO: get proper values for solar
00143     {
00144         gl_error("weather file '%s' access failed", tmyfile);
00145         return 0;
00146     }
00147 
00148     // begin parsing the TMY file
00149     int line=0;
00150     tmy = (TMYDATA*)malloc(sizeof(TMYDATA)*8760);
00151     if (tmy==NULL)
00152     {
00153         gl_error("TMY buffer allocation failed");
00154         return 0;
00155     }
00156 
00157     int month,day, hour;
00158     double dnr,dhr;
00159     char cty[50];
00160     char st[3];
00161     int lat_deg,lat_min,long_deg,long_min;
00162     file.header_info(cty,st,&lat_deg,&lat_min,&long_deg,&long_min);
00163     double degrees = (double)lat_deg + ((double)lat_min) / 60;
00164     double long_degrees = (double)long_deg + ((double)long_min) / 60;
00165     SolarAngles *sa = new SolarAngles();
00166     double tz_meridian =  15 * abs(file.tz_offset);//std_meridians[-file.tz_offset-5];
00167     while (line<8760 && file.next())
00168     {
00169         
00170         file.read_data(&dnr,&dhr,&temperature,&humidity,&month,&day,&hour);
00171         int doy = sa->day_of_yr(month,day);
00172         int hoy = (doy - 1) * 24 + (hour-1); 
00173         if (hoy>=0 && hoy<8760){
00174             tmy[hoy].temp_raw = temperature;
00175             tmy[hoy].temp = temperature;
00176             if(0 == gl_convert("degC", "degF", &(tmy[hoy].temp))){
00177                 gl_error("climate::init unable to gl_convert() 'degC' to 'degF'!");
00178                 return 0;
00179             }
00180             tmy[hoy].rh = humidity;
00181             // calculate the solar radiation
00182             double sol_time = sa->solar_time((double)hour,doy,RAD(tz_meridian),RAD(long_degrees));
00183             double sol_rad = 0.0; 
00184             
00185             for(COMPASS_PTS c_point = CP_S; c_point < CP_LAST;c_point=COMPASS_PTS(c_point+1)){
00186                 if(c_point == CP_H)
00187                     sol_rad = file.calc_solar(CP_E,doy,RAD(degrees),sol_time,dnr,dhr,0.0);//(double)dnr * cos_incident + dhr;
00188                 else
00189                     sol_rad = file.calc_solar(c_point,doy,RAD(degrees),sol_time,dnr,dhr);//(double)dnr * cos_incident + dhr;
00190                 /* TMY2 solar radiation data is in Watt-hours per square meter. */
00191                 if(0 == gl_convert("W/m^2", "W/sf", &(sol_rad))){
00192                     gl_error("climate::init unable to gl_convert() 'W/m^2' to 'W/sf'!");
00193                     return 0;
00194                 }
00195                 tmy[hoy].solar[c_point] = sol_rad;
00196             }
00197             
00198         }
00199         else
00200             gl_error("%s(%d): day %d, hour %d is out of allowed range 0-8759 hours", tmyfile,line,day,hour);
00201         
00202         line++;
00203     }
00204     file.close();
00205     return 1;
00206 }
00207 
00208 TIMESTAMP climate::sync(TIMESTAMP t0) 
00209 {
00210     if (tmy!=NULL)
00211     {
00212         DATETIME ts;
00213         gl_localtime(t0,&ts);
00214         int hoy = ts.yearday*24 + ts.hour;
00215         temperature = tmy[hoy].temp;
00216         temperature_raw = tmy[hoy].temp_raw;
00217         humidity = tmy[hoy].rh;
00221         memcpy(solar_flux,tmy[hoy].solar,CP_LAST*sizeof(double));
00222         return -(t0+(3600*TS_SECOND-t0%(3600 *TS_SECOND))); 
00223     }
00224     return TS_NEVER;
00225 }
00226 
00228 // IMPLEMENTATION OF CORE LINKAGE: climate
00230 
00232 EXPORT int create_climate(OBJECT **obj, 
00233                           OBJECT *parent) 
00234 {
00235     *obj = gl_create_object(climate::oclass,sizeof(climate));
00236     if (*obj!=NULL)
00237     {
00238         climate *my = OBJECTDATA(*obj,climate);
00239         gl_set_parent(*obj,parent);
00240         my->create();
00241         return 1;
00242     }
00243     return 0;
00244 }
00245 
00247 EXPORT int init_climate(OBJECT *obj, 
00248                         OBJECT *parent) 
00249 {
00250     if (obj!=NULL)
00251     {
00252         climate *my = OBJECTDATA(obj,climate);
00253         return my->init(parent);
00254     }
00255     return 0;
00256 }
00257 
00259 EXPORT TIMESTAMP sync_climate(OBJECT *obj, 
00260                               TIMESTAMP t0) 
00261 {
00262     TIMESTAMP t1 = OBJECTDATA(obj,climate)->sync(t0);
00263     obj->clock = t0;
00264     return t1;
00265 }
00266 
00278 csv::csv()
00279 {
00280     fp=NULL;
00281     hdr=NULL;
00282     data=NULL;
00283     cols=0;
00284 }
00285 
00286 csv::~csv()
00287 {
00288     if (fp) fclose(fp);
00289     if (hdr) delete [] hdr;
00290     if (data) delete [] data;
00291 }
00292 
00293 int csv::open(const char *file, const unsigned n, ...) // return the number of columns founds
00294 {
00295     char *ff = gl_findfile((char*)file,NULL,FF_READ);
00296     if (ff==NULL) return 0;
00297     fp = fopen(ff,"r");
00298     if (fp==NULL) return 0;
00299     if (fgets(buffer,sizeof(buffer),fp)==NULL) return 0;
00300     char temp[sizeof(buffer)];
00301     strcpy(temp,buffer);
00302     hdr = new int[cols=n];
00303     if (hdr==NULL) return 0;
00304 
00305     // process each requested column
00306     va_list ptr;
00307     va_start(ptr,n);
00308     unsigned ncol;
00309     for (ncol=0; ncol<n; ncol++)
00310     {
00311         const char *arg=va_arg(ptr,const char*);
00312         char *p;
00313         int i=0;
00314 
00315         // scan the header list
00316         strcpy(buffer,temp);
00317         for (p=strtok(buffer,","); p!=NULL; p=strtok(NULL,","),i++)
00318         {
00319             if (strcmp(p,arg)==0)
00320             {
00321                 hdr[ncol] = i;
00322                 break;
00323             }
00324         }
00325 
00326         // didn't find it
00327         if (p==NULL) 
00328             return ncol;
00329     }
00330     data = new char*[ncol];
00331     return ncol;
00332 }
00333 
00334 int csv::next(void)
00335 {
00336     if (fgets(buffer,sizeof(buffer),fp)==NULL) return 0;
00337     unsigned n, i=0;
00338     char *p;
00339     for (p=strtok(buffer,","); p!=NULL; p=strtok(NULL,","),i++)
00340     {
00341         for (n=0; n<cols; n++)
00342         {
00343             if (hdr[n]==i)
00344             {
00345                 data[n]=p;
00346                 break;
00347             }
00348         }
00349     }
00350     return cols;
00351 }
00352 
00353 char *csv::read(unsigned n)
00354 {
00355     if (n>=0 && n<cols)
00356         return data[n];
00357     else
00358         return NULL;
00359 }

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