/[ascend]/trunk/models/johnpye/datareader/ee.c
ViewVC logotype

Annotation of /trunk/models/johnpye/datareader/ee.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2505 - (hide annotations) (download) (as text)
Sat Oct 1 10:31:24 2011 UTC (12 years, 9 months ago) by jpye
File MIME type: text/x-csrc
File size: 10103 byte(s)
Support for E/E format. Still some checking/bug-fixings required, but basically appears to be working.
1 jpye 2504 /* ASCEND modelling environment
2     Copyright (C) 2011 Carnegie Mellon University
3    
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2, or (at your option)
7     any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place - Suite 330,
17     Boston, MA 02111-1307, USA.
18     *//**
19     @file
20     Data Reader implementation for the ESP-r/EnergyPlus weather data format.
21    
22     (WARNING: outdated, see newer file embedded in the latest EnergyPlus pkg)
23     http://apps1.eere.energy.gov/buildings/energyplus/weatherdata_format.cfm
24    
25     The data format for the main data rows is shown here (see 'Input Output' document
26     in EnergyPlus's Documentation folder (you need to install the software to get
27     these files, unfortunately, but it is free (gratis) to do so)
28    
29     N1, \field Year
30     N2, \field Month
31     N3, \field Day
32     N4, \field Hour
33     N5, \field Minute
34     A1, \field Data Source and Uncertainty Flags
35     \note Initial day of weather file is checked by EnergyPlus for validity (as shown below)
36     \note Each field is checked for "missing" as shown below. Reasonable values, calculated
37     \note values or the last "good" value is substituted.
38     N6, \field Dry Bulb Temperature
39     \units C
40     \minimum> -70
41     \maximum< 70
42     \missing 99.9
43     N7, \field Dew Point Temperature
44     \units C
45     \minimum> -70
46     \maximum< 70
47     \missing 99.9
48     N8, \field Relative Humidity
49     \missing 999.
50     \minimum 0
51     \maximum 110
52     N9, \field Atmospheric Station Pressure
53     \units Pa
54     \missing 999999.
55     \minimum> 31000
56     \maximum< 120000
57     N10, \field Extraterrestrial Horizontal Radiation
58     \units Wh/m2
59     \missing 9999.
60     \minimum 0
61     N11, \field Extraterrestrial Direct Normal Radiation
62     \units Wh/m2
63     \missing 9999.
64     \minimum 0
65     N12, \field Horizontal Infrared Radiation Intensity
66     \units Wh/m2
67     \missing 9999.
68     \minimum 0
69     N13, \field Global Horizontal Radiation
70     \units Wh/m2
71     \missing 9999.
72     \minimum 0
73     N14, \field Direct Normal Radiation
74     \units Wh/m2
75     \missing 9999.
76     \minimum 0
77     N15, \field Diffuse Horizontal Radiation
78     \units Wh/m2
79     \missing 9999.
80     \minimum 0
81     N16, \field Global Horizontal Illuminance
82     \units lux
83     \missing 999999.
84     \note will be missing if >= 999900
85     \minimum 0
86     N17, \field Direct Normal Illuminance
87     \units lux
88     \missing 999999.
89     \note will be missing if >= 999900
90     \minimum 0
91     N18, \field Diffuse Horizontal Illuminance
92     \units lux
93     \missing 999999.
94     \note will be missing if >= 999900
95     \minimum 0
96     N19, \field Zenith Luminance
97     \units Cd/m2
98     \missing 9999.
99     \note will be missing if >= 9999
100     \minimum 0
101     N20, \field Wind Direction
102     \units degrees
103     \missing 999.
104     \minimum 0
105     \maximum 360
106     N21, \field Wind Speed
107     \units m/s
108     \missing 999.
109     \minimum 0
110     \maximum 40
111     N22, \field Total Sky Cover
112     \missing 99
113     \minimum 0
114     \maximum 10
115     N23, \field Opaque Sky Cover (used if Horizontal IR Intensity missing)
116     \missing 99
117     \minimum 0
118     \maximum 10
119     N24, \field Visibility
120     \units km
121     \missing 9999
122     N25, \field Ceiling Height
123     \units m
124     \missing 99999
125     N26, \field Present Weather Observation
126     N27, \field Present Weather Codes
127     N28, \field Precipitable Water
128     \units mm
129     \missing 999
130     N29, \field Aerosol Optical Depth
131     \units thousandths
132     \missing .999
133     N30, \field Snow Depth
134     \units cm
135     \missing 999
136     N31, \field Days Since Last Snowfall
137     \missing 99
138     N32, \field Albedo
139     \missing 999
140     N33, \field Liquid Precipitation Depth
141     \units mm
142     \missing 999
143     N34; \field Liquid Precipitation Quantity
144     \units hr
145     \missing 99
146    
147     *//*
148     by John Pye, Oct 2011.
149     */
150    
151     #include "ee.h"
152     #include "sun.h"
153    
154     #include <stdio.h>
155    
156     #include <ascend/general/ascMalloc.h>
157     #include <ascend/utilities/error.h>
158    
159     #include "parse/parse.h"
160    
161 jpye 2505 #define EE_DEBUG 1
162 jpye 2504
163     /**
164     Data extracted from the E/E data file, doesn't have to included everything,
165     only the stuff we actually think we will want to use.
166     */
167     typedef struct EePoint_struct{
168     double t;
169     float T; ///< dry bulb temperature, K.
170     float p; ///< atmospheric pressure, Pa.
171     float rh; /// relative humidity, fraction 0<rh<1.
172     float DNI; ///< direct normal irradiance Wh/m��
173     float Gd; ///< diffuse horizontal irradiance Wh/m��
174     float d_wind; ///< wind direction, rad, N = 0, E = pi, W = 3pi, S = 2pi. Range 0<=d<2pi
175     float v_wind; ///< wind speed, m/s.
176     } EePoint;
177    
178     typedef struct EeData_struct{
179     EePoint *rows;
180     parse *p; /* parse object, non-null during file read */
181     } EeData;
182    
183     #define DATA(D) ((EeData *)(D->data))
184    
185     struct EeLocation{
186     char city[101];
187     char state[101];
188     char country[101];
189     char source[101];
190     int WMO;
191     double latitude; // in degrees, + is north
192     double longitude; // in degrees, + is east
193     double timezone; // in hours, rel to GMT
194     double elevation; // in metres, -1000.0 to 9999.9 m.
195     };
196    
197     int parseLOCATION(parse *p, struct EeLocation *loc){
198     return
199     (parseThisString(p,"LOCATION")
200     && parseThisString(p,",")
201     && parseStrExcept(p,",",loc->city,100)
202     && parseThisString(p,",")
203     && parseStrExcept(p,",",loc->state,100)
204     && parseThisString(p,",")
205     && parseStrExcept(p,",",loc->country,100)
206     && parseThisString(p,",")
207     && parseStrExcept(p,",",loc->source,100)
208     && parseThisString(p,",")
209     && parseSignedNumber(p,&(loc->WMO))
210     && parseThisString(p,",")
211     && parseDouble(p,&(loc->latitude))
212     && parseThisString(p,",")
213     && parseDouble(p,&(loc->longitude))
214     && parseThisString(p,",")
215     && parseDouble(p,&(loc->timezone))
216     && parseThisString(p,",")
217     && parseDouble(p,&(loc->elevation))
218     && parseEOL(p)
219     ) || parseError(p,"Error in LOCATION line")
220     ;
221     }
222    
223     int parseIgnoreLineWith(parse *p, const char *label){
224     char rubbish[1024];
225     return
226     parseThisString(p,label)
227     && parseStrExcept(p,"\r\n",rubbish,1023)
228     && parseEOL(p)
229     ;//&& assign(CONSOLE_DEBUG("Ignore: %s%s", label,rubbish));
230     }
231    
232     /**
233     @return 0 on success
234     */
235     int datareader_ee_header(DataReader *d){
236     struct EeLocation loc;
237     d->data = ASC_NEW(EeData);
238     DATA(d)->p = parseCreateFile(d->f);
239     parse *p = DATA(d)->p;
240    
241     if(!(
242     parseLOCATION(p,&loc)
243     && parseIgnoreLineWith(p,"DESIGN CONDITIONS")
244     && parseIgnoreLineWith(p,"TYPICAL/EXTREME PERIODS")
245     && parseIgnoreLineWith(p,"GROUND TEMPERATURES")
246     && parseIgnoreLineWith(p,"HOLIDAYS/DAYLIGHT SAVINGS")
247     && many(parseIgnoreLineWith(p,"COMMENTS"))
248     && parseIgnoreLineWith(p,"DATA PERIODS")
249     )){
250     ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Parser error in data file");
251     }
252    
253     CONSOLE_DEBUG("Loaded data for '%s' at (%.2fN,%.2fE)",loc.city,loc.latitude,loc.longitude);
254    
255     // set the value of some of the Data Reader parameters
256     d->i = 0;
257     d->ninputs = 1;
258     d->ndata = 8760; // FIXME
259 jpye 2505 d->nmaxoutputs = 7; // FIXME
260 jpye 2504
261     DATA(d)->rows = ASC_NEW_ARRAY(EePoint,d->ndata);
262    
263     /* set the number of inputs and outputs */
264     d->ninputs = 1;
265 jpye 2505 d->noutputs = 7;
266 jpye 2504
267     return 0;
268     }
269    
270     int datareader_ee_eof(DataReader *d){
271     //CONSOLE_DEBUG("Checking for EOF");
272     parse *p = DATA(d)->p;
273     if(parseEnd(p)){
274     CONSOLE_DEBUG("REACHED END OF FILE");
275     if(d->i < d->ndata){
276     ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Incomplete data set found (%d rows < %d expected",d->i, d->ndata);
277     }
278     d->ndata=d->i;
279 jpye 2505 int i;double tmin = +0.5*DBL_MAX,tmax = -0.5*DBL_MAX;
280     for(i=0; i<d->ndata; ++i){
281     double t = DATA(d)->rows[i].t;
282     if(t < tmin)tmin = t;
283     if(t > tmax)tmax = t;
284     }
285     ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Read %d rows, t in range [%f,%f] d",d->ndata,tmin/3600./24.,tmax/3600./24.);
286 jpye 2504 return 1;
287     }
288    
289     return 0;
290     }
291    
292     /**
293     Read a line of data and store in d.
294     @return 0 on success
295     */
296     int datareader_ee_data(DataReader *d){
297 jpye 2505 CONSOLE_DEBUG("Reading data, i = %d",d->i);
298 jpye 2504 unsigned year,month,day,hour,minute;
299     char uncerts[101];
300 jpye 2505 EePoint row;
301 jpye 2504
302     #define NUMFIELDS(D,X) D(T) X D(Tdew) X D(rh) X D(pres) X D(EHI) X D(EDNI) X D(HII) X D(GHI) X D(DNI) X D(DiffHI) X D(GHIll) X D(DNIll) X D(DiffHIll) X D(ZL) X D(winddir) X D(windspeed) X D(skycover) X D(opaqueskycover) X D(visibility) X D(ceilingheight) X D(weatherobs) X D(weathercodes) X D(precip) X D(aerosol) X D(snowdepth) X D(dayssincesnow) X D(albedo) X D(liquidprecipdepth) X D(liquidprecipqty)
303    
304     #define DECL(D) D
305     #define COMMA ,
306     double NUMFIELDS(DECL,COMMA);
307     #undef COMMA
308     #undef DECL
309    
310     // TODO what to do with 'missing' values??
311     parse *p = DATA(d)->p;
312    
313     #define PARSENUM(D) parseDouble(p,&D)
314     #define ANDTHEN && parseThisString(p,",") &&
315    
316     if(!(
317     ((parseNumber(p,&year)
318     && parseThisString(p,",")
319     && parseNumber(p,&month)
320     && parseThisString(p,",")
321     && parseNumber(p,&day)
322     && parseThisString(p,",")
323     && parseNumber(p,&hour)
324     && parseThisString(p,",")
325     && parseNumber(p,&minute)
326     && parseThisString(p,",")
327     && parseStrExcept(p,",",uncerts,100)
328     && parseThisString(p,",")
329     && NUMFIELDS(PARSENUM,ANDTHEN)
330     ) || parseError(p,"Missing/incorrect data field")
331     ) && (
332     parseEOL(p) || parseError(p,"Expected end-of-line")
333     )
334     )){
335     ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Failed to parse E/E data file");
336     return 1;
337     };
338     #undef ANDTHEN
339     #undef PARSENUM
340    
341 jpye 2505 row.t = ((day_of_year_specific(day,month,year) - 1)*24.0 + (hour - 1))*3600.0 + minute*60.;
342     row.T = T + 273.15;
343     row.p = pres;
344     row.rh = rh / 100.;
345     row.DNI = DNI; // FIXME need to allow for difference in dt, which might be other than 1h.
346     row.Gd = DiffHI; // FIXME need to allow for difference in dt, which might be other than 1h.
347     row.d_wind = winddir * 2*3.141592653589 / 360; // perhaps for variable continuity we should return sin and cos of this?
348     row.v_wind = windspeed;
349 jpye 2504
350 jpye 2505 DATA(d)->rows[d->i] = row;
351    
352     CONSOLE_DEBUG("Read i = %d, t = %f d, T = %.1f��C, rh = %.1f %",d->i,row.t / 3600. / 24., T, row.rh*100);
353    
354 jpye 2504 d->i++;
355     return 0;
356     }
357    
358     int datareader_ee_time(DataReader *d, double *t){
359 jpye 2505 *t = DATA(d)->rows[d->i].t;
360 jpye 2504 return 0;
361     }
362    
363     #define ROW DATA(d)->rows[d->i]
364    
365     int datareader_ee_vals(DataReader *d, double *v){
366     #if EE_DEBUG
367 jpye 2505 CONSOLE_DEBUG("At t=%f d, T = %lf, DNI = %f Wh/m2"
368     ,(ROW.t / 3600. / 24.),ROW.T, ROW.DNI
369 jpye 2504 );
370     #endif
371    
372     v[0]=ROW.T;
373     v[1]=ROW.p;
374     v[2]=ROW.rh;
375     v[3]=ROW.DNI;
376     v[4]=ROW.Gd;
377     v[5]=ROW.d_wind;
378     v[6]=ROW.v_wind;
379     return 0;
380     }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22