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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2505 - (show annotations) (download) (as text)
Sat Oct 1 10:31:24 2011 UTC (12 years, 8 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 /* 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 #define EE_DEBUG 1
162
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 d->nmaxoutputs = 7; // FIXME
260
261 DATA(d)->rows = ASC_NEW_ARRAY(EePoint,d->ndata);
262
263 /* set the number of inputs and outputs */
264 d->ninputs = 1;
265 d->noutputs = 7;
266
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 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 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 CONSOLE_DEBUG("Reading data, i = %d",d->i);
298 unsigned year,month,day,hour,minute;
299 char uncerts[101];
300 EePoint row;
301
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 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
350 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 d->i++;
355 return 0;
356 }
357
358 int datareader_ee_time(DataReader *d, double *t){
359 *t = DATA(d)->rows[d->i].t;
360 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 CONSOLE_DEBUG("At t=%f d, T = %lf, DNI = %f Wh/m2"
368 ,(ROW.t / 3600. / 24.),ROW.T, ROW.DNI
369 );
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