| 81 | 
  | 
 | 
| 82 | 
  | 
/* Include files */ | 
| 83 | 
  | 
#define _USE_MATH_DEFINES | 
| 84 | 
– | 
#include <stdio.h> | 
| 84 | 
  | 
#include <stdlib.h> | 
| 86 | 
– | 
#include <string.h> | 
| 85 | 
  | 
#include <ctype.h> | 
| 88 | 
– | 
#include "rtmath.h" | 
| 86 | 
  | 
#include "platform.h" | 
| 87 | 
+ | 
#include "rtmath.h" | 
| 88 | 
+ | 
#include "rtio.h" | 
| 89 | 
  | 
#include "color.h" | 
| 90 | 
< | 
#include "resolu.h" | 
| 90 | 
> | 
#include "sun.h" | 
| 91 | 
  | 
 | 
| 92 | 
< | 
char *progname;                                                         /* Program name */ | 
| 94 | 
< | 
char errmsg[128];                                                       /* Error message buffer */ | 
| 92 | 
> | 
char *progname;                                 /* Program name */ | 
| 93 | 
  | 
const double DC_SolarConstantE = 1367.0;        /* Solar constant W/m^2 */ | 
| 94 | 
  | 
const double DC_SolarConstantL = 127.5;         /* Solar constant klux */ | 
| 95 | 
  | 
 | 
| 128 | 
  | 
extern void CalcSkyPatchLumin( float *parr ); | 
| 129 | 
  | 
extern void ComputeSky( float *parr ); | 
| 130 | 
  | 
 | 
| 131 | 
+ | 
 | 
| 132 | 
+ | 
extern double  solar_sunset(int month, int day); | 
| 133 | 
+ | 
extern double  solar_sunrise(int month, int day); | 
| 134 | 
+ | 
 | 
| 135 | 
  | 
/* Degrees into radians */ | 
| 136 | 
  | 
#define DegToRad(deg)   ((deg)*(PI/180.)) | 
| 137 | 
  | 
 | 
| 138 | 
  | 
/* Radiuans into degrees */ | 
| 139 | 
  | 
#define RadToDeg(rad)   ((rad)*(180./PI)) | 
| 140 | 
  | 
 | 
| 139 | 
– | 
 | 
| 141 | 
  | 
/* Perez sky model coefficients */ | 
| 142 | 
  | 
 | 
| 143 | 
  | 
/* Reference:   Perez, R., R. Seals, and J. Michalsky, 1993. "All- */ | 
| 254 | 
  | 
#define NSUNPATCH       4               /* max. # patches to spread sun into */ | 
| 255 | 
  | 
#endif | 
| 256 | 
  | 
 | 
| 257 | 
< | 
extern int jdate(int month, int day); | 
| 257 | 
< | 
extern double stadj(int  jd); | 
| 258 | 
< | 
extern double sdec(int  jd); | 
| 259 | 
< | 
extern double salt(double sd, double st); | 
| 260 | 
< | 
extern double sazi(double sd, double st); | 
| 261 | 
< | 
                                        /* sun calculation constants */ | 
| 262 | 
< | 
extern double  s_latitude; | 
| 263 | 
< | 
extern double  s_longitude; | 
| 264 | 
< | 
extern double  s_meridian; | 
| 257 | 
> | 
#define SUN_ANG_DEG     0.533           /* sun full-angle in degrees */ | 
| 258 | 
  | 
 | 
| 259 | 
  | 
int             nsuns = NSUNPATCH;      /* number of sun patches to use */ | 
| 260 | 
  | 
double          fixed_sun_sa = -1;      /* fixed solid angle per sun? */ | 
| 274 | 
  | 
float           *rh_pazi;               /* sky patch azimuths (radians) */ | 
| 275 | 
  | 
float           *rh_dom;                /* sky patch solid angle (sr) */ | 
| 276 | 
  | 
 | 
| 277 | 
< | 
#define         vector(v,alt,azi)       (       (v)[1] = tcos(alt), \ | 
| 278 | 
< | 
                                                (v)[0] = (v)[1]*tsin(azi), \ | 
| 279 | 
< | 
                                                (v)[1] *= tcos(azi), \ | 
| 280 | 
< | 
                                                (v)[2] = tsin(alt) ) | 
| 277 | 
> | 
#define         vector(v,alt,azi)       (       (v)[1] = cos(alt), \ | 
| 278 | 
> | 
                                                (v)[0] = (v)[1]*sin(azi), \ | 
| 279 | 
> | 
                                                (v)[1] *= cos(azi), \ | 
| 280 | 
> | 
                                                (v)[2] = sin(alt) ) | 
| 281 | 
  | 
 | 
| 282 | 
  | 
#define         rh_vector(v,i)          vector(v,rh_palt[i],rh_pazi[i]) | 
| 283 | 
  | 
 | 
| 284 | 
  | 
#define         rh_cos(i)               tsin(rh_palt[i]) | 
| 285 | 
  | 
 | 
| 286 | 
+ | 
#define         solar_minute(jd,hr)     ((24*60)*((jd)-1)+(int)((hr)*60.+.5)) | 
| 287 | 
+ | 
 | 
| 288 | 
  | 
extern int      rh_init(void); | 
| 289 | 
  | 
extern float *  resize_dmatrix(float *mtx_data, int nsteps, int npatch); | 
| 290 | 
+ | 
extern void     OutputSun(int id, int goodsun, FILE *fp, FILE *mfp); | 
| 291 | 
  | 
extern void     AddDirect(float *parr); | 
| 292 | 
  | 
 | 
| 293 | 
  | 
 | 
| 313 | 
  | 
        int     doheader = 1;           /* output header? */ | 
| 314 | 
  | 
        double  rotation = 0;           /* site rotation (degrees) */ | 
| 315 | 
  | 
        double  elevation;              /* site elevation (meters) */ | 
| 316 | 
+ | 
        int     leap_day = 0;           /* add leap day? */ | 
| 317 | 
+ | 
        int     sun_hours_only = 0;     /* only output sun hours? */ | 
| 318 | 
  | 
        int     dir_is_horiz;           /* direct is meas. on horizontal? */ | 
| 319 | 
+ | 
        FILE    *sunsfp = NULL;         /* output file for individual suns */ | 
| 320 | 
+ | 
        FILE    *modsfp = NULL;         /* modifier output file */ | 
| 321 | 
  | 
        float   *mtx_data = NULL;       /* our matrix data */ | 
| 322 | 
< | 
        int     ntsteps = 0;            /* number of rows in matrix */ | 
| 323 | 
< | 
        int     step_alloc = 0; | 
| 322 | 
> | 
        int     avgSky = 0;             /* compute average sky r.t. matrix? */ | 
| 323 | 
> | 
        int     ntsteps = 0;            /* number of time steps */ | 
| 324 | 
> | 
        int     tstorage = 0;           /* number of allocated time steps */ | 
| 325 | 
> | 
        int     nstored = 0;            /* number of time steps in matrix */ | 
| 326 | 
  | 
        int     last_monthly = 0;       /* month of last report */ | 
| 327 | 
  | 
        int     mo, da;                 /* month (1-12) and day (1-31) */ | 
| 328 | 
  | 
        double  hr;                     /* hour (local standard time) */ | 
| 329 | 
  | 
        double  dir, dif;               /* direct and diffuse values */ | 
| 330 | 
  | 
        int     mtx_offset; | 
| 331 | 
  | 
        int     i, j; | 
| 332 | 
+ | 
        double  timeinterval = 0; | 
| 333 | 
  | 
 | 
| 334 | 
  | 
        progname = argv[0]; | 
| 335 | 
  | 
                                        /* get options */ | 
| 379 | 
  | 
                        skycolor[1] = atof(argv[++i]); | 
| 380 | 
  | 
                        skycolor[2] = atof(argv[++i]); | 
| 381 | 
  | 
                        break; | 
| 382 | 
+ | 
                case 'D':                       /* output suns to file */ | 
| 383 | 
+ | 
                        if (strcmp(argv[++i], "-")) { | 
| 384 | 
+ | 
                                sunsfp = fopen(argv[i], "w"); | 
| 385 | 
+ | 
                                if (sunsfp == NULL) { | 
| 386 | 
+ | 
                                        fprintf(stderr, | 
| 387 | 
+ | 
                                        "%s: cannot open '%s' for output\n", | 
| 388 | 
+ | 
                                                        progname, argv[i]); | 
| 389 | 
+ | 
                                        exit(1); | 
| 390 | 
+ | 
                                } | 
| 391 | 
+ | 
                                break;          /* still may output matrix */ | 
| 392 | 
+ | 
                        } | 
| 393 | 
+ | 
                        sunsfp = stdout;        /* sending to stdout, so... */ | 
| 394 | 
+ | 
                        /* fall through */ | 
| 395 | 
+ | 
                case 'n':                       /* no matrix output */ | 
| 396 | 
+ | 
                        avgSky = -1; | 
| 397 | 
+ | 
                        rhsubdiv = 1; | 
| 398 | 
+ | 
                        /* fall through */ | 
| 399 | 
  | 
                case 'd':                       /* solar (direct) only */ | 
| 400 | 
  | 
                        skycolor[0] = skycolor[1] = skycolor[2] = 0; | 
| 401 | 
< | 
                        if (suncolor[1] <= 1e-4) | 
| 382 | 
< | 
                                suncolor[0] = suncolor[1] = suncolor[2] = 1; | 
| 401 | 
> | 
                        grefl[0] = grefl[1] = grefl[2] = 0; | 
| 402 | 
  | 
                        break; | 
| 403 | 
+ | 
                case 'M':                       /* send sun modifiers to file */ | 
| 404 | 
+ | 
                        if ((modsfp = fopen(argv[++i], "w")) == NULL) { | 
| 405 | 
+ | 
                                fprintf(stderr, "%s: cannot open '%s' for output\n", | 
| 406 | 
+ | 
                                                progname, argv[i]); | 
| 407 | 
+ | 
                                exit(1); | 
| 408 | 
+ | 
                        } | 
| 409 | 
+ | 
                        break; | 
| 410 | 
  | 
                case 's':                       /* sky only (no direct) */ | 
| 411 | 
  | 
                        suncolor[0] = suncolor[1] = suncolor[2] = 0; | 
| 386 | 
– | 
                        if (skycolor[1] <= 1e-4) | 
| 387 | 
– | 
                                skycolor[0] = skycolor[1] = skycolor[2] = 1; | 
| 412 | 
  | 
                        break; | 
| 413 | 
+ | 
                case 'u':                       /* solar hours only */ | 
| 414 | 
+ | 
                        sun_hours_only = 1; | 
| 415 | 
+ | 
                        break; | 
| 416 | 
  | 
                case 'r':                       /* rotate distribution */ | 
| 417 | 
  | 
                        if (argv[i][2] && argv[i][2] != 'z') | 
| 418 | 
  | 
                                goto userr; | 
| 420 | 
  | 
                        break; | 
| 421 | 
  | 
                case '5':                       /* 5-phase calculation */ | 
| 422 | 
  | 
                        nsuns = 1; | 
| 423 | 
< | 
                        fixed_sun_sa = 6.797e-05; | 
| 423 | 
> | 
                        fixed_sun_sa = PI/360.*atof(argv[++i]); | 
| 424 | 
> | 
                        if (fixed_sun_sa <= 0) { | 
| 425 | 
> | 
                                fprintf(stderr, "%s: missing solar disk size argument for '-5' option\n", | 
| 426 | 
> | 
                                                progname); | 
| 427 | 
> | 
                                exit(1); | 
| 428 | 
> | 
                        } | 
| 429 | 
> | 
                        fixed_sun_sa *= fixed_sun_sa*PI; | 
| 430 | 
  | 
                        break; | 
| 431 | 
+ | 
                case 'A':                       /* compute average sky */ | 
| 432 | 
+ | 
                        avgSky = 1; | 
| 433 | 
+ | 
                        break; | 
| 434 | 
+ | 
                case 'i': | 
| 435 | 
+ | 
                        timeinterval = atof(argv[++i]); | 
| 436 | 
+ | 
                        break; | 
| 437 | 
  | 
                default: | 
| 438 | 
  | 
                        goto userr; | 
| 439 | 
  | 
                } | 
| 444 | 
  | 
                                progname, argv[i]); | 
| 445 | 
  | 
                exit(1); | 
| 446 | 
  | 
        } | 
| 447 | 
+ | 
        if ((modsfp != NULL) & (sunsfp == NULL)) | 
| 448 | 
+ | 
                fprintf(stderr, "%s: warning -M output will be empty without -D\n", | 
| 449 | 
+ | 
                                progname); | 
| 450 | 
  | 
        if (verbose) { | 
| 451 | 
  | 
                if (i == argc-1) | 
| 452 | 
  | 
                        fprintf(stderr, "%s: reading weather tape '%s'\n", | 
| 489 | 
  | 
                fprintf(stderr, "%s: location '%s'\n", progname, buf); | 
| 490 | 
  | 
                fprintf(stderr, "%s: (lat,long)=(%.1f,%.1f) degrees north, west\n", | 
| 491 | 
  | 
                                progname, s_latitude, s_longitude); | 
| 492 | 
< | 
                fprintf(stderr, "%s: %d sky patches per time step\n", | 
| 493 | 
< | 
                                progname, nskypatch); | 
| 492 | 
> | 
                if (avgSky >= 0) | 
| 493 | 
> | 
                        fprintf(stderr, "%s: %d sky patches\n", | 
| 494 | 
> | 
                                        progname, nskypatch); | 
| 495 | 
> | 
                if (sunsfp) | 
| 496 | 
> | 
                        fprintf(stderr, "%s: outputting suns to %s\n", | 
| 497 | 
> | 
                                        progname, sunsfp==stdout ? "stdout" : "file"); | 
| 498 | 
  | 
                if (rotation != 0) | 
| 499 | 
  | 
                        fprintf(stderr, "%s: rotating output %.0f degrees\n", | 
| 500 | 
  | 
                                        progname, rotation); | 
| 503 | 
  | 
        s_latitude = DegToRad(s_latitude); | 
| 504 | 
  | 
        s_longitude = DegToRad(s_longitude); | 
| 505 | 
  | 
        s_meridian = DegToRad(s_meridian); | 
| 506 | 
+ | 
                                        /* initial allocation */ | 
| 507 | 
+ | 
        mtx_data = resize_dmatrix(mtx_data, tstorage=2, nskypatch); | 
| 508 | 
  | 
                                        /* process each time step in tape */ | 
| 509 | 
  | 
        while (scanf("%d %d %lf %lf %lf\n", &mo, &da, &hr, &dir, &dif) == 5) { | 
| 510 | 
< | 
                double          sda, sta; | 
| 511 | 
< | 
                                        /* make space for next time step */ | 
| 464 | 
< | 
                mtx_offset = 3*nskypatch*ntsteps++; | 
| 465 | 
< | 
                if (ntsteps > step_alloc) { | 
| 466 | 
< | 
                        step_alloc += (step_alloc>>1) + ntsteps + 7; | 
| 467 | 
< | 
                        mtx_data = resize_dmatrix(mtx_data, step_alloc, nskypatch); | 
| 468 | 
< | 
                } | 
| 469 | 
< | 
                if (dif <= 1e-4) { | 
| 470 | 
< | 
                        memset(mtx_data+mtx_offset, 0, sizeof(float)*3*nskypatch); | 
| 471 | 
< | 
                        continue; | 
| 472 | 
< | 
                } | 
| 473 | 
< | 
                if (verbose && mo != last_monthly) | 
| 474 | 
< | 
                        fprintf(stderr, "%s: stepping through month %d...\n", | 
| 475 | 
< | 
                                                progname, last_monthly=mo); | 
| 510 | 
> | 
                double          sda, sta, st; | 
| 511 | 
> | 
                int             sun_in_sky; | 
| 512 | 
  | 
                                        /* compute solar position */ | 
| 513 | 
< | 
                julian_date = jdate(mo, da); | 
| 513 | 
> | 
                if ((mo == 2) & (da == 29)) { | 
| 514 | 
> | 
                        julian_date = 60; | 
| 515 | 
> | 
                        leap_day = 1; | 
| 516 | 
> | 
                } else | 
| 517 | 
> | 
                        julian_date = jdate(mo, da) + leap_day; | 
| 518 | 
  | 
                sda = sdec(julian_date); | 
| 519 | 
  | 
                sta = stadj(julian_date); | 
| 520 | 
< | 
                altitude = salt(sda, hr+sta); | 
| 521 | 
< | 
                azimuth = sazi(sda, hr+sta) + PI - DegToRad(rotation); | 
| 520 | 
> | 
                st = hr + sta; | 
| 521 | 
> | 
                 | 
| 522 | 
> | 
                if (timeinterval > 0) { | 
| 523 | 
> | 
                        if (fabs(solar_sunrise(mo, da) - st) <= timeinterval/120) | 
| 524 | 
> | 
                                st = (st + timeinterval/120 + solar_sunrise(mo, da))/2; | 
| 525 | 
> | 
                        else if (fabs(solar_sunset(mo, da) - st) < timeinterval/120) | 
| 526 | 
> | 
                                st = (st - timeinterval/120 + solar_sunset(mo, da))/2; | 
| 527 | 
> | 
                } | 
| 528 | 
> | 
                altitude = salt(sda, st); | 
| 529 | 
> | 
                sun_in_sky = (altitude > -DegToRad(SUN_ANG_DEG/2.)); | 
| 530 | 
> | 
                if (sun_hours_only && !sun_in_sky) | 
| 531 | 
> | 
                        continue;       /* skipping nighttime points */ | 
| 532 | 
> | 
                azimuth = sazi(sda, st) + PI - DegToRad(rotation); | 
| 533 | 
> | 
 | 
| 534 | 
> | 
                mtx_offset = 3*nskypatch*nstored; | 
| 535 | 
> | 
                nstored += !avgSky | !nstored; | 
| 536 | 
> | 
                                        /* make space for next row */ | 
| 537 | 
> | 
                if (nstored > tstorage) { | 
| 538 | 
> | 
                        tstorage += (tstorage>>1) + nstored + 7; | 
| 539 | 
> | 
                        mtx_data = resize_dmatrix(mtx_data, tstorage, nskypatch); | 
| 540 | 
> | 
                } | 
| 541 | 
> | 
                ntsteps++;              /* keep count of time steps */ | 
| 542 | 
> | 
 | 
| 543 | 
> | 
                if (dir+dif <= 1e-4) {  /* effectively nighttime? */ | 
| 544 | 
> | 
                        if (!avgSky | !mtx_offset) | 
| 545 | 
> | 
                                memset(mtx_data+mtx_offset, 0, | 
| 546 | 
> | 
                                                sizeof(float)*3*nskypatch); | 
| 547 | 
> | 
                                        /* output black sun? */ | 
| 548 | 
> | 
                        if (sunsfp && sun_in_sky) | 
| 549 | 
> | 
                                OutputSun(solar_minute(julian_date,hr), 0, | 
| 550 | 
> | 
                                                        sunsfp, modsfp); | 
| 551 | 
> | 
                        continue; | 
| 552 | 
> | 
                } | 
| 553 | 
> | 
                if (!sun_in_sky && dir > (input==1 ? 20. : 20.*WHTEFFICACY)) | 
| 554 | 
> | 
                        fprintf(stderr, | 
| 555 | 
> | 
                                "%s: warning - unusually bright at %.1f on %d-%d\n", | 
| 556 | 
> | 
                                        progname, hr, mo, da); | 
| 557 | 
  | 
                                        /* convert measured values */ | 
| 558 | 
< | 
                if (dir_is_horiz && altitude > 0.) | 
| 558 | 
> | 
                if (dir_is_horiz && altitude > FTINY) | 
| 559 | 
  | 
                        dir /= sin(altitude); | 
| 560 | 
  | 
                if (input == 1) { | 
| 561 | 
  | 
                        dir_irrad = dir; | 
| 566 | 
  | 
                } | 
| 567 | 
  | 
                                        /* compute sky patch values */ | 
| 568 | 
  | 
                ComputeSky(mtx_data+mtx_offset); | 
| 569 | 
+ | 
                                        /* output sun if requested */ | 
| 570 | 
+ | 
                if (sunsfp && sun_in_sky) | 
| 571 | 
+ | 
                        OutputSun(solar_minute(julian_date,hr), 1, | 
| 572 | 
+ | 
                                                sunsfp, modsfp); | 
| 573 | 
+ | 
 | 
| 574 | 
+ | 
                if (avgSky < 0)         /* no matrix? */ | 
| 575 | 
+ | 
                        continue; | 
| 576 | 
+ | 
 | 
| 577 | 
  | 
                AddDirect(mtx_data+mtx_offset); | 
| 578 | 
+ | 
                                        /* update cumulative sky? */ | 
| 579 | 
+ | 
                for (i = 3*nskypatch*(avgSky&(ntsteps>1)); i--; ) | 
| 580 | 
+ | 
                        mtx_data[i] += mtx_data[mtx_offset+i]; | 
| 581 | 
+ | 
                                        /* monthly reporting */ | 
| 582 | 
+ | 
                if (verbose && mo != last_monthly) | 
| 583 | 
+ | 
                        fprintf(stderr, "%s: stepping through month %d...\n", | 
| 584 | 
+ | 
                                                progname, last_monthly=mo); | 
| 585 | 
+ | 
                                        /* note whether leap-day was given */ | 
| 586 | 
  | 
        } | 
| 587 | 
+ | 
        if (!ntsteps) { | 
| 588 | 
+ | 
                fprintf(stderr, "%s: no valid time steps on input\n", progname); | 
| 589 | 
+ | 
                exit(1); | 
| 590 | 
+ | 
        } | 
| 591 | 
  | 
                                        /* check for junk at end */ | 
| 592 | 
  | 
        while ((i = fgetc(stdin)) != EOF) | 
| 593 | 
  | 
                if (!isspace(i)) { | 
| 598 | 
  | 
                        fputs(buf, stderr); fputc('\n', stderr); | 
| 599 | 
  | 
                        break; | 
| 600 | 
  | 
                } | 
| 601 | 
+ | 
 | 
| 602 | 
+ | 
        if (avgSky < 0)                 /* no matrix output? */ | 
| 603 | 
+ | 
                goto alldone; | 
| 604 | 
+ | 
 | 
| 605 | 
+ | 
        dif = 1./(double)ntsteps;       /* average sky? */ | 
| 606 | 
+ | 
        for (i = 3*nskypatch*(avgSky&(ntsteps>1)); i--; ) | 
| 607 | 
+ | 
                mtx_data[i] *= dif; | 
| 608 | 
  | 
                                        /* write out matrix */ | 
| 609 | 
  | 
        if (outfmt != 'a') | 
| 610 | 
  | 
                SET_FILE_BINARY(stdout); | 
| 613 | 
  | 
#endif | 
| 614 | 
  | 
        if (verbose) | 
| 615 | 
  | 
                fprintf(stderr, "%s: writing %smatrix with %d time steps...\n", | 
| 616 | 
< | 
                                progname, outfmt=='a' ? "" : "binary ", ntsteps); | 
| 616 | 
> | 
                                progname, outfmt=='a' ? "" : "binary ", nstored); | 
| 617 | 
  | 
        if (doheader) { | 
| 618 | 
  | 
                newheader("RADIANCE", stdout); | 
| 619 | 
  | 
                printargs(argc, argv, stdout); | 
| 620 | 
  | 
                printf("LATLONG= %.8f %.8f\n", RadToDeg(s_latitude), | 
| 621 | 
  | 
                                        -RadToDeg(s_longitude)); | 
| 622 | 
  | 
                printf("NROWS=%d\n", nskypatch); | 
| 623 | 
< | 
                printf("NCOLS=%d\n", ntsteps); | 
| 623 | 
> | 
                printf("NCOLS=%d\n", nstored); | 
| 624 | 
  | 
                printf("NCOMP=3\n"); | 
| 625 | 
+ | 
                if ((outfmt == 'f') | (outfmt == 'd')) | 
| 626 | 
+ | 
                        fputendian(stdout); | 
| 627 | 
  | 
                fputformat((char *)getfmtname(outfmt), stdout); | 
| 628 | 
  | 
                putchar('\n'); | 
| 629 | 
  | 
        } | 
| 632 | 
  | 
                mtx_offset = 3*i; | 
| 633 | 
  | 
                switch (outfmt) { | 
| 634 | 
  | 
                case 'a': | 
| 635 | 
< | 
                        for (j = 0; j < ntsteps; j++) { | 
| 635 | 
> | 
                        for (j = 0; j < nstored; j++) { | 
| 636 | 
  | 
                                printf("%.3g %.3g %.3g\n", mtx_data[mtx_offset], | 
| 637 | 
  | 
                                                mtx_data[mtx_offset+1], | 
| 638 | 
  | 
                                                mtx_data[mtx_offset+2]); | 
| 639 | 
  | 
                                mtx_offset += 3*nskypatch; | 
| 640 | 
  | 
                        } | 
| 641 | 
< | 
                        if (ntsteps > 1) | 
| 641 | 
> | 
                        if (nstored > 1) | 
| 642 | 
  | 
                                fputc('\n', stdout); | 
| 643 | 
  | 
                        break; | 
| 644 | 
  | 
                case 'f': | 
| 645 | 
< | 
                        for (j = 0; j < ntsteps; j++) { | 
| 646 | 
< | 
                                fwrite(mtx_data+mtx_offset, sizeof(float), 3, | 
| 645 | 
> | 
                        for (j = 0; j < nstored; j++) { | 
| 646 | 
> | 
                                putbinary(mtx_data+mtx_offset, sizeof(float), 3, | 
| 647 | 
  | 
                                                stdout); | 
| 648 | 
  | 
                                mtx_offset += 3*nskypatch; | 
| 649 | 
  | 
                        } | 
| 650 | 
  | 
                        break; | 
| 651 | 
  | 
                case 'd': | 
| 652 | 
< | 
                        for (j = 0; j < ntsteps; j++) { | 
| 652 | 
> | 
                        for (j = 0; j < nstored; j++) { | 
| 653 | 
  | 
                                double  ment[3]; | 
| 654 | 
  | 
                                ment[0] = mtx_data[mtx_offset]; | 
| 655 | 
  | 
                                ment[1] = mtx_data[mtx_offset+1]; | 
| 656 | 
  | 
                                ment[2] = mtx_data[mtx_offset+2]; | 
| 657 | 
< | 
                                fwrite(ment, sizeof(double), 3, stdout); | 
| 657 | 
> | 
                                putbinary(ment, sizeof(double), 3, stdout); | 
| 658 | 
  | 
                                mtx_offset += 3*nskypatch; | 
| 659 | 
  | 
                        } | 
| 660 | 
  | 
                        break; | 
| 662 | 
  | 
                if (ferror(stdout)) | 
| 663 | 
  | 
                        goto writerr; | 
| 664 | 
  | 
        } | 
| 665 | 
< | 
        if (fflush(stdout) == EOF) | 
| 665 | 
> | 
alldone: | 
| 666 | 
> | 
        if (fflush(NULL) == EOF) | 
| 667 | 
  | 
                goto writerr; | 
| 668 | 
  | 
        if (verbose) | 
| 669 | 
  | 
                fprintf(stderr, "%s: done.\n", progname); | 
| 670 | 
  | 
        exit(0); | 
| 671 | 
  | 
userr: | 
| 672 | 
< | 
        fprintf(stderr, "Usage: %s [-v][-h][-d|-s][-r deg][-m N][-g r g b][-c r g b][-o{f|d}][-O{0|1}] [tape.wea]\n", | 
| 672 | 
> | 
        fprintf(stderr, "Usage: %s [-v][-h][-A][-d|-s|-n][-u][-D file [-M modfile]][-r deg][-m N][-g r g b][-c r g b][-o{f|d}][-O{0|1}] [tape.wea]\n", | 
| 673 | 
  | 
                        progname); | 
| 674 | 
  | 
        exit(1); | 
| 675 | 
  | 
fmterr: | 
| 676 | 
< | 
        fprintf(stderr, "%s: input weather tape format error\n", progname); | 
| 676 | 
> | 
        fprintf(stderr, "%s: weather tape format error in header\n", progname); | 
| 677 | 
  | 
        exit(1); | 
| 678 | 
  | 
writerr: | 
| 679 | 
  | 
        fprintf(stderr, "%s: write error on output\n", progname); | 
| 680 | 
  | 
        exit(1); | 
| 681 | 
  | 
} | 
| 682 | 
  | 
 | 
| 683 | 
+ | 
 | 
| 684 | 
  | 
/* Return maximum of two doubles */ | 
| 685 | 
  | 
double dmax( double a, double b ) | 
| 686 | 
  | 
{ return (a > b) ? a : b; } | 
| 726 | 
  | 
                /* Limit sky clearness */ | 
| 727 | 
  | 
                if (sky_clearness > 11.9) | 
| 728 | 
  | 
                        sky_clearness = 11.9; | 
| 729 | 
+ | 
                else if (sky_clearness < 1.0) | 
| 730 | 
+ | 
                        sky_clearness = 1.0; | 
| 731 | 
  | 
 | 
| 732 | 
  | 
                /* Limit sky brightness */ | 
| 733 | 
  | 
                if (sky_brightness < 0.01) | 
| 734 | 
  | 
                        sky_brightness = 0.01; | 
| 735 | 
+ | 
                else if (sky_brightness > 0.6) | 
| 736 | 
+ | 
                        sky_brightness = 0.6; | 
| 737 | 
  | 
 | 
| 738 | 
  | 
                /* Calculate illuminance */ | 
| 739 | 
  | 
                index = GetCategoryIndex(); | 
| 750 | 
  | 
                diff_illum = diff_irrad * WHTEFFICACY; | 
| 751 | 
  | 
                dir_illum = dir_irrad * WHTEFFICACY; | 
| 752 | 
  | 
        } | 
| 643 | 
– | 
 | 
| 644 | 
– | 
        if (bright(skycolor) <= 1e-4) {                 /* 0 sky component? */ | 
| 645 | 
– | 
                memset(parr, 0, sizeof(float)*3*nskypatch); | 
| 646 | 
– | 
                return; | 
| 647 | 
– | 
        } | 
| 753 | 
  | 
        /* Compute ground radiance (include solar contribution if any) */ | 
| 754 | 
  | 
        parr[0] = diff_illum; | 
| 755 | 
  | 
        if (altitude > 0) | 
| 757 | 
  | 
        parr[2] = parr[1] = parr[0] *= (1./PI/WHTEFFICACY); | 
| 758 | 
  | 
        multcolor(parr, grefl); | 
| 759 | 
  | 
 | 
| 760 | 
+ | 
        if (bright(skycolor) <= 1e-4) {                 /* 0 sky component? */ | 
| 761 | 
+ | 
                memset(parr+3, 0, sizeof(float)*3*(nskypatch-1)); | 
| 762 | 
+ | 
                return; | 
| 763 | 
+ | 
        } | 
| 764 | 
  | 
        /* Calculate Perez sky model parameters */ | 
| 765 | 
  | 
        CalcPerezParam(sun_zenith, sky_clearness, sky_brightness, index); | 
| 766 | 
  | 
 | 
| 786 | 
  | 
        } | 
| 787 | 
  | 
} | 
| 788 | 
  | 
 | 
| 789 | 
+ | 
 | 
| 790 | 
+ | 
double | 
| 791 | 
+ | 
solar_sunset(int month, int day) | 
| 792 | 
+ | 
{ | 
| 793 | 
+ | 
        float W; | 
| 794 | 
+ | 
        W = -1 * (tan(s_latitude) * tan(sdec(jdate(month, day)))); | 
| 795 | 
+ | 
        return(12 + (M_PI / 2 - atan2(W, sqrt(1 - W * W))) * 180 / (M_PI * 15)); | 
| 796 | 
+ | 
} | 
| 797 | 
+ | 
 | 
| 798 | 
+ | 
 | 
| 799 | 
+ | 
double | 
| 800 | 
+ | 
solar_sunrise(int month, int day) | 
| 801 | 
+ | 
{ | 
| 802 | 
+ | 
        float W; | 
| 803 | 
+ | 
        W = -1 * (tan(s_latitude) * tan(sdec(jdate(month, day)))); | 
| 804 | 
+ | 
        return(12 - (M_PI / 2 - atan2(W, sqrt(1 - W * W))) * 180 / (M_PI * 15)); | 
| 805 | 
+ | 
} | 
| 806 | 
+ | 
 | 
| 807 | 
+ | 
 | 
| 808 | 
  | 
/* Add in solar direct to nearest sky patches (GW) */ | 
| 809 | 
  | 
void | 
| 810 | 
  | 
AddDirect(float *parr) | 
| 857 | 
  | 
        } | 
| 858 | 
  | 
} | 
| 859 | 
  | 
 | 
| 860 | 
+ | 
/* Output a sun to indicated file if appropriate for this time step */ | 
| 861 | 
+ | 
void | 
| 862 | 
+ | 
OutputSun(int id, int goodsun, FILE *fp, FILE *mfp) | 
| 863 | 
+ | 
{ | 
| 864 | 
+ | 
        double  srad; | 
| 865 | 
+ | 
        FVECT   sv; | 
| 866 | 
+ | 
 | 
| 867 | 
+ | 
        srad = DegToRad(SUN_ANG_DEG/2.); | 
| 868 | 
+ | 
        srad = goodsun ? dir_illum/(WHTEFFICACY * PI*srad*srad) : 0; | 
| 869 | 
+ | 
        vector(sv, altitude, azimuth); | 
| 870 | 
+ | 
        fprintf(fp, "\nvoid light solar%d\n0\n0\n", id); | 
| 871 | 
+ | 
        fprintf(fp, "3 %.3e %.3e %.3e\n", srad*suncolor[0], | 
| 872 | 
+ | 
                        srad*suncolor[1], srad*suncolor[2]); | 
| 873 | 
+ | 
        fprintf(fp, "\nsolar%d source sun%d\n0\n0\n", id, id); | 
| 874 | 
+ | 
        fprintf(fp, "4 %.6f %.6f %.6f %.4f\n", sv[0], sv[1], sv[2], SUN_ANG_DEG); | 
| 875 | 
+ | 
         | 
| 876 | 
+ | 
        if (mfp != NULL)                /* saving modifier IDs? */ | 
| 877 | 
+ | 
                fprintf(mfp, "solar%d\n", id); | 
| 878 | 
+ | 
} | 
| 879 | 
+ | 
 | 
| 880 | 
  | 
/* Initialize Reinhart sky patch positions (GW) */ | 
| 881 | 
  | 
int | 
| 882 | 
  | 
rh_init(void) | 
| 1074 | 
  | 
        if (sky_brightness < 0.01) | 
| 1075 | 
  | 
                        sky_brightness = 0.01;  | 
| 1076 | 
  | 
 | 
| 1077 | 
+ | 
        if (sky_clearness < 1.0000) | 
| 1078 | 
+ | 
        { | 
| 1079 | 
+ | 
                sky_clearness = 1.0000; | 
| 1080 | 
+ | 
        } | 
| 1081 | 
+ | 
 | 
| 1082 | 
+ | 
        if (sky_brightness > 0.6) | 
| 1083 | 
+ | 
        { | 
| 1084 | 
+ | 
                sky_brightness = 0.6; | 
| 1085 | 
+ | 
        } | 
| 1086 | 
+ | 
 | 
| 1087 | 
  | 
        while (((fabs(diff_irrad - test1) > 10.0) || | 
| 1088 | 
  | 
                        (fabs(dir_irrad - test2) > 10.0)) && !(counter == 5)) | 
| 1089 | 
  | 
        { | 
| 1094 | 
  | 
                /* Convert illuminance to irradiance */ | 
| 1095 | 
  | 
                index = GetCategoryIndex(); | 
| 1096 | 
  | 
                diff_irrad = diff_illum / CalcDiffuseIllumRatio(index); | 
| 1097 | 
< | 
                dir_irrad = dir_illum / CalcDirectIllumRatio(index); | 
| 1097 | 
> | 
                dir_irrad = CalcDirectIllumRatio(index); | 
| 1098 | 
> | 
                if (dir_irrad > 0.1) | 
| 1099 | 
> | 
                        dir_irrad = dir_illum / dir_irrad; | 
| 1100 | 
  | 
         | 
| 1101 | 
  | 
                /* Calculate sky brightness and clearness */ | 
| 1102 | 
  | 
                sky_brightness = CalcSkyBrightness(); | 
| 1109 | 
  | 
                /* Limit sky brightness */ | 
| 1110 | 
  | 
                if (sky_brightness < 0.01) | 
| 1111 | 
  | 
                        sky_brightness = 0.01;  | 
| 1112 | 
+ | 
 | 
| 1113 | 
+ | 
                if (sky_clearness < 1.0000) | 
| 1114 | 
+ | 
                { | 
| 1115 | 
+ | 
                        sky_clearness = 1.0000; | 
| 1116 | 
+ | 
                } | 
| 1117 | 
+ | 
 | 
| 1118 | 
+ | 
                if (sky_brightness > 0.6) | 
| 1119 | 
+ | 
                { | 
| 1120 | 
+ | 
                        sky_brightness = 0.6; | 
| 1121 | 
+ | 
                } | 
| 1122 | 
  | 
        } | 
| 1123 | 
  | 
 | 
| 1124 | 
  | 
        return GetCategoryIndex(); |