ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/loadEPW.c
Revision: 2.3
Committed: Tue Mar 4 17:45:41 2025 UTC (8 weeks, 2 days ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.2: +2 -2 lines
Log Message:
fix(gendaymtx): Somehow missed "May" in month list!

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: loadEPW.c,v 2.2 2025/02/27 19:00:00 greg Exp $";
3 #endif
4 /*
5 * Load an EPW (or WEA) file, one data point at a time
6 *
7 * G. Ward, Feb 2025
8 */
9
10 #include "rtio.h"
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include "loadEPW.h"
14
15 const char WDname[7][10] = {
16 "Sunday", "Monday", "Tuesday", "Wednesday",
17 "Thursday", "Friday", "Saturday"
18 };
19
20 const char MOname[12][10] = {
21 "January", "February", "March", "April", "May", "June", "July",
22 "August", "September", "October", "November", "December"
23 };
24
25 #define EPWDATE_INIT {.0f,0,0,0}
26
27 static const struct DataPeriod EPWperiodInit = {
28 "DEFAULT", 1, Sunday, {.0f, 1, 0, 0}, {24.f, 31, 11, 0}
29 };
30
31 const EPWrecord EPWrecInit = {
32 EPWDATE_INIT, "", 99.9f, 99.9f, 999.f, 999999.f, 9999.f, 9999.f, 9999.f,
33 9999.f, 9999.f, 9999.f, 999999.f, 999999.f, 999999.f, 9999.f, 999.f, 999.f,
34 99.f, 99.f, 9999e3f, 99999.f, 999e-3f, 999e-3f, 999e-2f, 99,
35 .0f, 1.5e-3f, .0f
36 };
37
38 #define EPWdateInit (EPWrecInit.date)
39
40 static const short mo_da[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
41
42 /* Get day-of-week from name (may be abbreviated) */
43 static int
44 get_day(const char dnm[])
45 {
46 int n = strlen(dnm);
47 int i;
48
49 if (n < 3)
50 return(-1);
51
52 for (i = 0; i < 7; i++)
53 if (!strncasecmp(dnm, WDname[i], n))
54 return(i);
55 return(-1);
56 }
57
58 /* Hour difference calculator dt1 - dt2 (crude) */
59 static double
60 hour_diff(const EPWdate *dt1, const EPWdate *dt2)
61 {
62 double hrdiff = dt1->hour - dt2->hour;
63
64 hrdiff += 24.*(mo_da[dt1->month] + dt1->day - mo_da[dt2->month] - dt2->day);
65
66 if ((dt1->year > 0) & (dt2->year > 0))
67 hrdiff += 365.*24.*(dt1->year - dt2->year);
68
69 return(hrdiff);
70 }
71
72 /* Check that a date/time is legal */
73 static int
74 date_OK(const EPWdate *dt)
75 {
76 if ((0 > dt->month) | (dt->month > 11) |
77 (0 > dt->hour) | (dt->hour > 24) | (dt->day < 1))
78 return(0);
79
80 return(dt->day <= (dt->month==1 ? 29 :
81 mo_da[dt->month+1] - mo_da[dt->month]));
82 }
83
84 /* Parse date (less hour) */
85 static int
86 get_date(EPWdate *dt, const char date[])
87 {
88 int mo, da, yr;
89 int nf;
90
91 *dt = EPWdateInit;
92 switch (sscanf(date, "%d/%d/%d", &mo, &da, &yr)) {
93 case 1:
94 da = mo; /* jdate */
95 if (da <= 0)
96 return(0);
97 for (mo = 0; mo_da[mo+1] < da; mo++)
98 if (mo >= 11)
99 return(0);
100 dt->day = da - mo_da[dt->month = mo];
101 return(1);
102 case 3: /* month/day/year */
103 dt->year = yr;
104 /* fall through */
105 case 2: /* month/day */
106 dt->month = mo-1;
107 dt->day = da;
108 return(date_OK(dt));
109 }
110 return(0);
111 }
112
113 /* Check that site data is sensible */
114 static int
115 bad_location(const struct Location *lp)
116 {
117 if ((-90. > lp->latitude) | (lp->latitude > 90.)) {
118 fputs("Bad latitude in ", stderr);
119 return(1);
120 }
121 if ((-180. > lp->longitude) | (lp->longitude > 180.)) {
122 fputs("Bad longitude in ", stderr);
123 return(2);
124 }
125 if ((-12. > lp->timezone) | (lp->timezone > 12.)) {
126 fputs("Bad time zone in ", stderr);
127 return(3);
128 }
129 if ((-1000. > lp->elevation) | (lp->elevation > 9999.9)) {
130 fputs("Bad elevation in ", stderr);
131 return(4);
132 }
133 return(0);
134 }
135
136 /* Copy word to next comma in string */
137 static char *
138 tocomma(char *dst, char *src)
139 {
140 while (*src && *src != ',')
141 *dst++ = *src++;
142 src += (*src == ',');
143 *dst = '\0';
144 return(src);
145 }
146
147 /* Use fscanf() to load next date and time from input */
148 static int
149 scan_date(EPWheader *epw)
150 {
151 int hour;
152 int minute;
153
154 ++epw->lino;
155 if (epw->isWEA) { /* simpler for WEA input */
156 epw->dtpos = EPWdateInit;
157 if (fscanf(epw->fp, "%hd %hd %f", &epw->dtpos.month, &epw->dtpos.day,
158 &epw->dtpos.hour) != 3)
159 goto scanerr;
160 epw->dtpos.month--;
161 } else {
162 /* EPW input line */
163 if (fscanf(epw->fp, "%hd,%hd,%hd,%d,%d,", &epw->dtpos.year,
164 &epw->dtpos.month, &epw->dtpos.day, &hour, &minute) != 5)
165 goto scanerr;
166 epw->dtpos.hour = hour-1;
167 if (epw->period[0].nperhour == 1)
168 epw->dtpos.hour += .5;
169 else
170 epw->dtpos.hour += minute*(1./60.);
171 epw->dtpos.month--;
172 }
173 /* check date/time */
174 if (!date_OK(&epw->dtpos)) {
175 fputs("Illegal date/time in ", stderr);
176 return(0);
177 }
178 return(1);
179 scanerr:
180 if (!feof(epw->fp))
181 fputs("Unable to scan date in ", stderr);
182 return(0);
183 }
184
185 /* Open input file and load header info. */
186 EPWheader *
187 EPWopen(const char *fname)
188 {
189 char linbuf[1024], wbuf[64];
190 char *cp;
191 int n;
192 EPWheader *hdr = (EPWheader *)calloc(1, sizeof(EPWheader));
193
194 if (hdr == NULL)
195 goto memerr;
196 if (fname == NULL || !*fname) {
197 fname = "<stdin>";
198 hdr->fp = stdin;
199 } else if ((hdr->fp = fopen(fname, "r")) == NULL) {
200 perror(fname);
201 free(hdr);
202 return(NULL);
203 }
204 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
205 goto readerr;
206 ++hdr->lino;
207 if (!strncasecmp(linbuf, "place ", 6))
208 hdr->isWEA = 1;
209 else if (strncasecmp(linbuf, "LOCATION,", 9))
210 goto badformat;
211 if (hdr->isWEA) { /* getting WEA header */
212 cp = linbuf+6;
213 if (sscanf(cp, "%[^_]_%[^\r\n]q",
214 hdr->loc.city, hdr->loc.country) != 2)
215 goto badformat;
216 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
217 goto readerr;
218 ++hdr->lino;
219 if (sscanf(linbuf, "latitude %lf", &hdr->loc.latitude) != 1)
220 goto badformat;
221 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
222 goto readerr;
223 ++hdr->lino;
224 if (sscanf(linbuf, "longitude %lf", &hdr->loc.longitude) != 1)
225 goto badformat;
226 hdr->loc.longitude *= -1.;
227 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
228 goto readerr;
229 ++hdr->lino;
230 if (sscanf(linbuf, "time_zone %f", &hdr->loc.timezone) != 1)
231 goto badformat;
232 hdr->loc.timezone *= -1./15.;
233 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
234 goto readerr;
235 ++hdr->lino;
236 if (sscanf(linbuf, "site_elevation %f", &hdr->loc.elevation) != 1)
237 goto badformat;
238 if (bad_location(&hdr->loc))
239 goto badformat;
240 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
241 goto readerr;
242 ++hdr->lino;
243 if (sscanf(linbuf, "weather_data_file_units %hd", &hdr->isWEA) != 1)
244 goto badformat;
245 hdr->nperiods = 1;
246 hdr->period[0] = EPWperiodInit;
247 hdr->dstart = (int)ftell(hdr->fp);
248 hdr->lin0 = hdr->lino;
249 if (!scan_date(hdr)) /* get date */
250 goto badformat;
251 return(hdr);
252 } /* else EPW header */
253 cp = linbuf+9;
254 cp = tocomma(hdr->loc.city, cp);
255 if (!*cp) goto badformat;
256 cp = tocomma(hdr->loc.state, cp);
257 if (!*cp) goto badformat;
258 cp = tocomma(hdr->loc.country, cp);
259 if (!*cp) goto badformat;
260 cp = tocomma(hdr->loc.source, cp);
261 if (!*cp) goto badformat;
262 cp = tocomma(hdr->loc.wmo, cp);
263 if (sscanf(cp, "%lf,%lf,%f,%f", &hdr->loc.latitude, &hdr->loc.longitude,
264 &hdr->loc.timezone, &hdr->loc.elevation) != 4)
265 goto badformat;
266 if (bad_location(&hdr->loc))
267 goto badformat;
268 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
269 goto readerr;
270 ++hdr->lino;
271 if (strncasecmp(linbuf, "DESIGN CONDITIONS,", 18))
272 goto badformat;
273 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
274 goto readerr;
275 ++hdr->lino;
276 if (strncasecmp(linbuf, "TYPICAL/EXTREME PERIODS,", 24))
277 goto badformat;
278 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
279 goto readerr;
280 ++hdr->lino;
281 if (strncasecmp(linbuf, "GROUND TEMPERATURES,", 20))
282 goto badformat;
283 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
284 goto readerr;
285 ++hdr->lino;
286 if (strncasecmp(linbuf, "HOLIDAYS/DAYLIGHT SAVINGS,", 26))
287 goto badformat;
288 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
289 goto readerr;
290 ++hdr->lino;
291 if (strncasecmp(linbuf, "COMMENTS 1,", 11))
292 goto badformat;
293 n = strlen(linbuf+11);
294 if (n > 1) {
295 hdr->comments1 = (char *)malloc(n);
296 if (hdr->comments1 == NULL)
297 goto memerr;
298 memcpy(hdr->comments1, linbuf+11, n);
299 hdr->comments1[n] = '\0';
300 }
301 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
302 goto readerr;
303 ++hdr->lino;
304 if (strncasecmp(linbuf, "COMMENTS 2,", 11))
305 goto badformat;
306 n = strlen(linbuf+11);
307 if (n > 1) {
308 hdr->comments2 = (char *)malloc(n);
309 if (hdr->comments2 == NULL)
310 goto memerr;
311 memcpy(hdr->comments2, linbuf+11, n);
312 hdr->comments2[n] = '\0';
313 }
314 if (!fgets(linbuf, sizeof(linbuf), hdr->fp))
315 goto readerr;
316 ++hdr->lino;
317 if (strncasecmp(linbuf, "DATA PERIODS,", 13))
318 goto badformat;
319 hdr->nperiods = 1; /* XXX one for now */
320 if (atoi(linbuf+13) != 1)
321 fprintf(stderr, "%s: warning - ignoring data periods after first\n",
322 fname);
323 cp = strchr(linbuf+13, ',');
324 if (!cp++) goto badformat;
325 if ((hdr->period[0].nperhour = atoi(cp)) <= 0)
326 goto badformat;
327 cp = strchr(cp, ',');
328 if (!cp++) goto badformat;
329 cp = tocomma(hdr->period[0].name, cp);
330 if (!*cp) goto badformat;
331 cp = tocomma(wbuf, cp);
332 if ((hdr->period[0].startday = get_day(wbuf)) < 0)
333 goto badformat;
334 if (!*cp) goto badformat;
335 cp = tocomma(wbuf, cp);
336 if (!get_date(&hdr->period[0].firstdate, wbuf))
337 goto badformat;
338 if (!*cp) goto badformat;
339 cp = tocomma(wbuf, cp);
340 if (!get_date(&hdr->period[0].lastdate, wbuf))
341 goto badformat;
342 hdr->period[0].lastdate.hour = 24.f;
343 hdr->dstart = (int)ftell(hdr->fp);
344 hdr->lin0 = hdr->lino;
345 if (!scan_date(hdr)) /* and get/check date */
346 goto badformat;
347 if ((hdr->dtpos.month != hdr->period[0].firstdate.month) |
348 (hdr->dtpos.day != hdr->period[0].firstdate.day))
349 fprintf(stderr, "%s: warning - starting date does not match first record\n",
350 fname);
351 return(hdr); /* seems we're good! */
352 memerr:
353 perror("malloc");
354 if (hdr) {
355 if (hdr->fp != stdin) fclose(hdr->fp);
356 free(hdr);
357 }
358 return(NULL);
359 readerr:
360 fprintf(stderr, "%s: header read error at line %d\n", fname, hdr->lino);
361 EPWclose(hdr);
362 return(NULL);
363 badformat:
364 fprintf(stderr, "%s: header format error in %s file at line %d\n",
365 fname, hdr->isWEA ? "WEA" : "EPW", hdr->lino);
366 EPWclose(hdr);
367 return(NULL);
368 }
369
370 /* Seek to a particular data record if we can */
371 int
372 EPWseek(EPWheader *epw, const EPWdate *dt)
373 {
374 if (!epw | !dt || !epw->fp || !date_OK(dt))
375 return(EOF);
376 /* need to back up? */
377 if (feof(epw->fp) || hour_diff(&epw->dtpos, dt) > 0.99) {
378 if (epw->dstart < 0 || fseek(epw->fp, epw->dstart, SEEK_SET) < 0) {
379 if (epw->fp == stdin)
380 fputs("Cannot seek on standard input\n", stderr);
381 else
382 fprintf(stderr, "Seek error on %s input file\n",
383 epw->isWEA ? "WEA" : "EPW");
384 return(EOF);
385 }
386 epw->lino = epw->lin0;
387 scan_date(epw); /* assume this much works! */
388 }
389 /* step through earlier records */
390 while (hour_diff(&epw->dtpos, dt) < -.99) {
391 int c;
392 while ((c = getc(epw->fp)) != EOF)
393 if (c == '\n') /* skip record data */
394 break;
395 if (scan_date(epw)) /* load next date/time */
396 continue;
397 if (feof(epw->fp))
398 fputs("Requested date/time not found in ", stderr);
399 fputs(epw->isWEA ? "WEA" : "EPW", stderr);
400 fputs(" input\n", stderr);
401 return(0);
402 }
403 return(1);
404 }
405
406 /* Read the next data record from input */
407 int
408 EPWread(EPWheader *epw, EPWrecord *rp)
409 {
410 char linbuf[1024];
411 char *cp;
412
413 if (!epw | !rp || feof(epw->fp))
414 return(EOF);
415
416 *rp = EPWrecInit; /* initialize to defaults */
417 rp->date = epw->dtpos; /* date already read in */
418 if (!fgets(linbuf, sizeof(linbuf), epw->fp)) {
419 fputs("Unexpected EOF on input\n", stderr);
420 return(0);
421 }
422 switch (epw->isWEA) { /* check for WEA input */
423 case WEAnot: /* nope */
424 break;
425 case WEAradnorm: /* radiometric w/ direct normal */
426 if (sscanf(linbuf, "%f %f", &rp->dirirrad,
427 &rp->horizdiffirrad) != 2)
428 goto badformat;
429 break;
430 case WEAradhoriz: /* radiometric w/ direct horizontal */
431 if (sscanf(linbuf, "%f %f", &rp->globhorizirrad,
432 &rp->horizdiffirrad) != 2)
433 goto badformat;
434 rp->globhorizirrad += rp->horizdiffirrad;
435 break;
436 case WEAphotnorm: /* photometric w/ direct normal */
437 if (sscanf(linbuf, "%f %f", &rp->dirillum,
438 &rp->diffillum) != 2)
439 goto badformat;
440 break;
441 default:
442 fputs("Illegal WEA data type\n", stderr);
443 return(0);
444 }
445 if (epw->isWEA) {
446 if (sscanf(linbuf, "%*f %*f %f %f",
447 &rp->optdepth, &rp->skycover) == 2) {
448 rp->optdepth *= 1e-3;
449 }
450 if (!scan_date(epw) && !feof(epw->fp))
451 goto badformat;
452 return(1);
453 }
454 /* continue here if EPW file */
455 cp = tocomma(rp->uncert, linbuf);
456 if (!*cp) goto badformat;
457 if (*cp != ',') {
458 rp->dbtemp = atof(cp);
459 cp = strchr(cp, ',');
460 }
461 if (!cp++) goto badformat;
462 if (*cp != ',') {
463 rp->dptemp = atof(cp);
464 cp = strchr(cp, ',');
465 }
466 if (!cp++) goto badformat;
467 if (*cp != ',') {
468 rp->humidity = atof(cp);
469 cp = strchr(cp, ',');
470 }
471 if (!cp++) goto badformat;
472 if (*cp != ',') {
473 rp->atmospressure = atof(cp);
474 cp = strchr(cp, ',');
475 }
476 if (!cp++) goto badformat;
477 if (*cp != ',') {
478 rp->exthorizirrad = atof(cp);
479 cp = strchr(cp, ',');
480 }
481 if (!cp++) goto badformat;
482 if (*cp != ',') {
483 rp->extdirirrad = atof(cp);
484 cp = strchr(cp, ',');
485 }
486 if (!cp++) goto badformat;
487 if (*cp != ',') {
488 rp->horizirrad_ir = atof(cp);
489 cp = strchr(cp, ',');
490 }
491 if (!cp++) goto badformat;
492 if (*cp != ',') {
493 rp->globhorizirrad = atof(cp);
494 cp = strchr(cp, ',');
495 }
496 if (!cp++) goto badformat;
497 if (*cp != ',') {
498 rp->dirirrad = atof(cp);
499 cp = strchr(cp, ',');
500 }
501 if (!cp++) goto badformat;
502 if (*cp != ',') {
503 rp->horizdiffirrad = atof(cp);
504 cp = strchr(cp, ',');
505 }
506 if (!cp++) goto badformat;
507 if (*cp != ',') {
508 rp->globhorizillum = atof(cp);
509 if (rp->globhorizillum >= 999900.f)
510 rp->globhorizillum = EPWrecInit.globhorizillum;
511 cp = strchr(cp, ',');
512 }
513 if (!cp++) goto badformat;
514 if (*cp != ',') {
515 rp->diffillum = atof(cp);
516 if (rp->diffillum >= 999900.f)
517 rp->diffillum = EPWrecInit.diffillum;
518 cp = strchr(cp, ',');
519 }
520 if (!cp++) goto badformat;
521 if (*cp != ',') {
522 rp->dirillum = atof(cp);
523 if (rp->dirillum >= 999900.f)
524 rp->dirillum = EPWrecInit.dirillum;
525 cp = strchr(cp, ',');
526 }
527 if (!cp++) goto badformat;
528 if (*cp != ',') {
529 rp->zenlum = atof(cp);
530 if (rp->zenlum >= 9999.f)
531 rp->zenlum = EPWrecInit.zenlum;
532 cp = strchr(cp, ',');
533 }
534 if (!cp++) goto badformat;
535 if (*cp != ',') {
536 rp->windirection = atof(cp);
537 cp = strchr(cp, ',');
538 }
539 if (!cp++) goto badformat;
540 if (*cp != ',') {
541 rp->windspeed = atof(cp);
542 cp = strchr(cp, ',');
543 }
544 if (!cp++) goto badformat;
545 if (*cp != ',') {
546 rp->skycover = atof(cp) * 0.1;
547 cp = strchr(cp, ',');
548 }
549 if (!cp++) goto badformat;
550 if (*cp != ',') {
551 rp->opskycover = atof(cp) * 0.1;
552 cp = strchr(cp, ',');
553 }
554 if (!cp++) goto badformat;
555 if (*cp != ',') {
556 rp->visibility = atof(cp) * 1000.;
557 cp = strchr(cp, ',');
558 }
559 if (!cp++) goto badformat;
560 if (*cp != ',') {
561 rp->ceilheight = atof(cp);
562 cp = strchr(cp, ',');
563 }
564 if (!cp++) goto badformat;
565 cp = strchr(cp, ',');
566 if (!cp++) goto badformat;
567 cp = strchr(cp, ',');
568 if (!cp++) goto badformat;
569 if (*cp != ',') {
570 rp->precip = atof(cp) * 1e-3;
571 cp = strchr(cp, ',');
572 }
573 if (!cp++) goto badformat;
574 if (*cp != ',') {
575 rp->optdepth = atof(cp) * 1e-3;
576 cp = strchr(cp, ',');
577 }
578 if (!cp++) goto badformat;
579 if (*cp != ',') {
580 rp->snowdepth = atof(cp) * 1e-2;
581 cp = strchr(cp, ',');
582 }
583 if (!cp++) goto badformat;
584 if (*cp != ',') {
585 rp->nosnowdays = atoi(cp);
586 cp = strchr(cp, ',');
587 }
588 if (!cp++) goto badformat;
589 if (*cp != ',') {
590 rp->albedo = atof(cp);
591 cp = strchr(cp, ',');
592 }
593 if (!cp++) goto badformat;
594 if (*cp != ',') {
595 rp->liqpdepth = atof(cp) * 1e-3;
596 cp = strchr(cp, ',');
597 }
598 if (!cp++) goto badformat;
599 if ((*cp != ',') & (*cp != '\n'))
600 rp->liqhours = atof(cp);
601 if (scan_date(epw) || feof(epw->fp))
602 return(1); /* normal return (even if next is EOF) */
603 badformat:
604 fprintf(stderr, "%s file, format error at line %d\n",
605 epw->isWEA ? "WEA" : "EPW", epw->lino);
606 return(0);
607 }
608
609 /* Close input and free header data */
610 void
611 EPWclose(EPWheader *epw)
612 {
613 if (!epw) return;
614 if (epw->fp != stdin) fclose(epw->fp);
615 if (epw->comments1) free(epw->comments1);
616 if (epw->comments2) free(epw->comments2);
617 free(epw);
618 return;
619 }
620
621 #ifdef TEST_MAIN
622 int
623 main(int argc, char *argv[])
624 {
625 EPWheader *epw = EPWopen(argv[1]);
626 EPWrecord erec;
627 int rval;
628
629 if (!epw) return(1);
630
631 printf("Weather input file type is %d\n", epw->isWEA);
632 printf("Location is %s, %s\n", epw->loc.city, epw->loc.country);
633 printf("Time zone is %.2f hours from GMT\n", epw->loc.timezone);
634 printf("Latitude, longitude is (%.8f,%.8f) degrees (N,E)\n",
635 epw->loc.latitude, epw->loc.longitude);
636 printf("Elevation is %.0f meters\n", epw->loc.elevation);
637 printf("'%s' starts %d/%d on a %s and ends %d/%d\n", epw->period[0].name,
638 epw->period[0].firstdate.month+1, epw->period[0].firstdate.day,
639 WDname[epw->period[0].startday],
640 epw->period[0].lastdate.month+1, epw->period[0].lastdate.day);
641 while ((rval = EPWread(epw, &erec)) > 0) {
642 printf("Weather record for %d/%d/%d @ %.2f hours:\n", erec.date.month+1,
643 erec.date.day, erec.date.year, erec.date.hour);
644 if (EPWisset(&erec,dbtemp))
645 printf("\tDry bulb temp: %.1f °C\n", erec.dbtemp);
646 if (EPWisset(&erec,dptemp))
647 printf("\tDew point temp: %.1f °C\n", erec.dptemp);
648 if (EPWisset(&erec,humidity))
649 printf("\tHumidity: %.1f%%\n", erec.humidity);
650 if (EPWisset(&erec,atmospressure))
651 printf("\tAtmospheric pressure: %.0f Pa\n", erec.atmospressure);
652 if (EPWisset(&erec,exthorizirrad))
653 printf("\tExtraterrestrial horiz irrad: %.1f w/m2\n", erec.exthorizirrad);
654 if (EPWisset(&erec,horizirrad_ir))
655 printf("\tInfrared direct normal irrad: %.1f w/m2\n", erec.horizirrad_ir);
656 if (EPWisset(&erec,globhorizirrad))
657 printf("\tGlobal horiz irrad: %.1f w/m2\n", erec.globhorizirrad);
658 if (EPWisset(&erec,dirirrad))
659 printf("\tDirect normal irrad: %.1f w/m2\n", erec.dirirrad);
660 if (EPWisset(&erec,horizdiffirrad))
661 printf("\tHorizontal diffuse irrad: %.1f w/m2\n", erec.horizdiffirrad);
662 if (EPWisset(&erec,globhorizillum))
663 printf("\tGlobal horizontal illuminance: %.0f lux\n", erec.globhorizillum);
664 if (EPWisset(&erec,diffillum))
665 printf("\tDiffuse horizontal illuminance: %.0f lux\n", erec.diffillum);
666 if (EPWisset(&erec,dirillum))
667 printf("\tDirect normal illuminance: %.0f lux\n", erec.dirillum);
668 if (EPWisset(&erec,zenlum))
669 printf("\tZenith luminance: %.0f nits\n", erec.zenlum);
670 if (EPWisset(&erec,windirection))
671 printf("\tWind direction: %.1f °E of S\n", erec.windirection);
672 if (EPWisset(&erec,windspeed))
673 printf("\tWind speed: %.2f m/s\n", erec.windspeed);
674 if (EPWisset(&erec,skycover))
675 printf("\tSky cover fraction: %.3f\n", erec.skycover);
676 if (EPWisset(&erec,opskycover))
677 printf("\tOpaque sky cover fraction: %.3f\n", erec.opskycover);
678 if (EPWisset(&erec,visibility))
679 printf("\tVisibility: %.0f meters\n", erec.visibility);
680 if (EPWisset(&erec,ceilheight))
681 printf("\tCloud ceiling height: %.0f meters\n", erec.ceilheight);
682 if (EPWisset(&erec,precip))
683 printf("\tPrecipitation: %f meters\n", erec.precip);
684 if (EPWisset(&erec,optdepth))
685 printf("\tAerosol optical depth: %.4f\n", erec.optdepth);
686 if (EPWisset(&erec,snowdepth))
687 printf("\tSnow depth: %.2f meters\n", erec.snowdepth);
688 if (EPWisset(&erec,nosnowdays))
689 printf("\tDays since last snow: %d\n", erec.nosnowdays);
690 if (EPWisset(&erec,albedo))
691 printf("\tAlbedo: %.4f\n", erec.albedo);
692 if (EPWisset(&erec,liqpdepth))
693 printf("\tLiquid precipitation depth: %.6f meters\n", erec.liqpdepth);
694 if (EPWisset(&erec,liqhours))
695 printf("\tLiquid precipitation time: %.1f hours\n", erec.liqhours);
696 }
697 EPWclose(epw);
698 return(!rval);
699 }
700 #endif /* TEST_MAIN */