--- ray/src/util/eplus_adduvf.c 2014/02/10 04:51:26 2.3 +++ ray/src/util/eplus_adduvf.c 2014/02/11 23:44:11 2.7 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: eplus_adduvf.c,v 2.3 2014/02/10 04:51:26 greg Exp $"; +static const char RCSid[] = "$Id: eplus_adduvf.c,v 2.7 2014/02/11 23:44:11 greg Exp $"; #endif /* * Add User View Factors to EnergyPlus Input Data File @@ -16,18 +16,20 @@ static const char RCSid[] = "$Id: eplus_adduvf.c,v 2.3 #include "rtprocess.h" #ifndef NSAMPLES -#define NSAMPLES 100000 /* number of samples to use */ +#define NSAMPLES 80000 /* default number of samples */ #endif char *progname; /* global argv[0] */ -char temp_octree[128]; /* temporary octree */ +int nsamps = NSAMPLES; /* number of samples to use */ +char temp_octree[128]; /* temporary octree */ + const char UVF_PNAME[] = "ZoneProperty:UserViewFactor:bySurfaceName"; const char ADD_HEADER[] = - "!+++ User View Factors computed by Radiance +++!\n"; + "\n!+++ User View Factors computed by Radiance +++!\n\n"; #define NAME_FLD 1 /* name field always first? */ @@ -39,8 +41,11 @@ typedef struct { const SURF_PTYPE surf_type[] = { {"BuildingSurface:Detailed", 4, 10}, + {"Floor:Detailed", 3, 9}, + {"RoofCeiling:Detailed", 3, 9}, + {"Wall:Detailed", 3, 9}, {NULL} - }; + }; /* IDF surface types */ typedef struct s_zone { const char *zname; /* zone name */ @@ -54,6 +59,14 @@ ZONE *zone_list = NULL; /* our list of zones */ IDF_LOADED *our_idf = NULL; /* loaded/modified IDF */ +typedef struct { + FVECT sdir[3]; /* UVW unit sampling vectors */ + double poff; /* W-offset for plane of polygon */ + double area_left; /* area left to sample */ + int samp_left; /* remaining samples */ + int wd; /* output file descriptor */ +} POLYSAMP; /* structure for polygon sampling */ + /* Create a new zone and push to top of our list */ static ZONE * new_zone(const char *zname, IDF_PARAMETER *param) @@ -143,9 +156,9 @@ rad_surface(IDF_PARAMETER *param, FILE *ofp) static int start_rcontrib(SUBPROC *pd, ZONE *zp) { -#define BASE_AC 3 +#define BASE_AC 5 static char *base_av[BASE_AC] = { - "rcontrib", "-ff", "-h" + "rcontrib", "-ff", "-h", "-x", "1" }; char cbuf[300]; char **av; @@ -165,7 +178,7 @@ start_rcontrib(SUBPROC *pd, ZONE *zp) return(0); for (i = 0; i < BASE_AC; i++) av[i] = base_av[i]; - sprintf(cbuf, "%d", NSAMPLES); + sprintf(cbuf, "%d", nsamps); av[i++] = "-c"; av[i++] = cbuf; /* add modifier arguments */ for (n = zp->nsurf, pptr = zp->pfirst; n--; pptr = pptr->dnext) { @@ -197,14 +210,6 @@ start_rcontrib(SUBPROC *pd, ZONE *zp) #undef BASE_AC } -typedef struct { - FVECT sdir[3]; /* XYZ unit sampling vectors */ - double poff; /* Z-offset for plane of polygon */ - double area_left; /* area left to sample */ - int samp_left; /* remaining samples */ - int wd; /* output file descriptor */ -} POLYSAMP; /* structure for polygon sampling */ - /* Initialize polygon sampling */ static Vert2_list * init_poly(POLYSAMP *ps, IDF_FIELD *f0, int nv) @@ -221,14 +226,15 @@ init_poly(POLYSAMP *ps, IDF_FIELD *f0, int nv) vl3 = (FVECT *)malloc(sizeof(FVECT)*nv); if (vl3 == NULL) return(NULL); - for (i = 0; i < nv; i++) + for (i = nv; i--; ) /* reverse vertex ordering */ for (j = 0; j < 3; j++) { if (fptr == NULL) { fputs(progname, stderr); - fputs(": bad vertex in init_poly()\n", stderr); + fputs(": missing vertex in init_poly()\n", stderr); return(NULL); } vl3[i][j] = atof(fptr->val); + fptr = fptr->next; } /* compute area and normal */ ps->sdir[2][0] = ps->sdir[2][1] = ps->sdir[2][2] = 0; @@ -252,7 +258,7 @@ init_poly(POLYSAMP *ps, IDF_FIELD *f0, int nv) normalize(ps->sdir[0]); fcross(ps->sdir[1], ps->sdir[2], ps->sdir[0]); /* compute plane offset */ - ps->poff = DOT(vl3[0], ps->sdir[2]) + FTINY; + ps->poff = DOT(vl3[0], ps->sdir[2]); /* assign 2-D vertices */ for (i = 0; i < nv; i++) { vl2->v[i].mX = DOT(vl3[i], ps->sdir[0]); @@ -276,7 +282,7 @@ sample_triangle(const Vert2_list *vl2, int a, int b, i for (i = 3; i--; ) { orig[i] = vl2->v[a].mX*ps->sdir[0][i] + vl2->v[a].mY*ps->sdir[1][i] + - ps->poff*ps->sdir[2][i]; + (ps->poff+.001)*ps->sdir[2][i]; ab[i] = (vl2->v[b].mX - vl2->v[a].mX)*ps->sdir[0][i] + (vl2->v[b].mY - vl2->v[a].mY)*ps->sdir[1][i]; ac[i] = (vl2->v[c].mX - vl2->v[a].mX)*ps->sdir[0][i] + @@ -305,18 +311,23 @@ sample_triangle(const Vert2_list *vl2, int a, int b, i samp = (float *)malloc(sizeof(float)*6*ns); if (samp == NULL) return(0); - for (i = ns; i--; ) { + for (i = ns; i--; ) { /* stratified Monte Carlo sampling */ double sv[4]; + FVECT dv; multisamp(sv, 4, (i+frandom())/(double)ns); sv[0] *= sv[1] = sqrt(sv[1]); sv[1] = 1. - sv[1]; for (j = 3; j--; ) - samp[ns*6 + j] = orig[j] + sv[0]*ab[j] + sv[1]*ac[j]; - sv[3] = sqrt(sv[3]); - sv[4] *= 2.*PI; - samp[ns*6 + 3] = tcos(sv[4]) * sv[3]; - samp[ns*6 + 4] = tsin(sv[4]) * sv[3]; - samp[ns*6 + 5] = sqrt(1. - sv[3]*sv[3]); + samp[i*6 + j] = orig[j] + sv[0]*ab[j] + sv[1]*ac[j]; + sv[2] = sqrt(sv[2]); + sv[3] *= 2.*PI; + dv[0] = tcos(sv[3]) * sv[2]; + dv[1] = tsin(sv[3]) * sv[2]; + dv[2] = sqrt(1. - sv[2]*sv[2]); + for (j = 3; j--; ) + samp[i*6 + 3 + j] = dv[0]*ps->sdir[0][j] + + dv[1]*ps->sdir[1][j] + + dv[2]*ps->sdir[2][j] ; } /* send to our process */ writebuf(ps->wd, (char *)samp, sizeof(float)*6*ns); @@ -333,16 +344,14 @@ sample_surface(IDF_PARAMETER *param, int wd) int nv; Vert2_list *vlist2; /* set up our polygon sampler */ - if (fptr == NULL || (nv = atoi(fptr->val)) < 3) { - fprintf(stderr, "%s: error in %s '%s'\n", + if (fptr == NULL || (nv = atoi(fptr->val)) < 3 || + (vlist2 = init_poly(&psamp, fptr->next, nv)) == NULL) { + fprintf(stderr, "%s: bad polygon %s '%s'\n", progname, param->pname, idf_getfield(param,NAME_FLD)->val); return(0); } - vlist2 = init_poly(&psamp, fptr->next, nv); - if (vlist2 == NULL) - return(0); - psamp.samp_left = NSAMPLES; /* assign samples & destination */ + psamp.samp_left = nsamps; /* assign samples & destination */ psamp.wd = wd; /* sample each subtriangle */ if (!polyTriangulate(vlist2, &sample_triangle)) @@ -379,6 +388,7 @@ compute_uvfs(SUBPROC *pd, ZONE *zp) return(0); /* UVFs from each surface */ for (n = zp->nsurf, pptr = zp->pfirst; n--; pptr = pptr->dnext) { + double vfsum = 0; /* send samples to rcontrib */ if (!sample_surface(pptr, pd->w)) return(0); @@ -392,15 +402,16 @@ compute_uvfs(SUBPROC *pd, ZONE *zp) /* append UVF fields */ for (m = 0, pptr1 = zp->pfirst; m < zp->nsurf; m++, pptr1 = pptr1->dnext) { + vfsum += uvfa[3*m + 1]; if (pptr1 == pptr) { if (uvfa[3*m + 1] > .001) fprintf(stderr, - "%s: warning - non-zero self-VF (%.3e) for surface '%s'\n", - progname, uvfa[3*m + 1], + "%s: warning - non-zero self-VF (%.1f%%) for surface '%s'\n", + progname, 100.*uvfa[3*m + 1], idf_getfield(pptr,NAME_FLD)->val); continue; /* don't record self-factor */ } - sprintf(uvfbuf, "%.6f", uvfa[3*m + 1]); + sprintf(uvfbuf, "%.4f", uvfa[3*m + 1]); if (!idf_addfield(pout, idf_getfield(pptr,NAME_FLD)->val, NULL) || !idf_addfield(pout, @@ -413,6 +424,11 @@ compute_uvfs(SUBPROC *pd, ZONE *zp) return(0); } } + if (vfsum < 0.95) + fprintf(stderr, + "%s: warning - missing %.1f%% of energy from surface '%s'\n", + progname, 100.*(1.-vfsum), + idf_getfield(pptr,NAME_FLD)->val); } free(uvfa); /* clean up and return */ return(1); @@ -424,11 +440,7 @@ compute_zones(void) { ZONE *zptr; /* temporary octree name */ - if (temp_filename(temp_octree, sizeof(temp_octree), TEMPLATE) == NULL) { - fputs(progname, stderr); - fputs(": cannot create temporary octree\n", stderr); - return(0); - } + mktemp(strcpy(temp_octree, TEMPLATE)); /* compute each zone */ for (zptr = zone_list; zptr != NULL; zptr = zptr->next) { SUBPROC rcproc; @@ -457,19 +469,28 @@ main(int argc, char *argv[]) IDF_PARAMETER *pptr; int i; - progname = argv[0]; - if (argc > 2 && !strcmp(argv[1], "-c")) { - incl_comments = -1; /* output header only */ - ++argv; --argc; - } - if ((argc < 2) | (argc > 3)) { - fputs("Usage: ", stderr); - fputs(progname, stderr); - fputs(" [-c] Model.idf [Revised.idf]\n", stderr); - return(1); - } - origIDF = argv[1]; - revIDF = (argc == 2) ? argv[1] : argv[2]; + progname = *argv++; argc--; /* get options if any */ + while (argc > 1 && argv[0][0] == '-') + switch (argv[0][1]) { + case 'c': /* elide comments */ + incl_comments = -1; /* header only */ + argv++; argc--; + continue; + case 's': /* samples */ + nsamps = 1000*atoi(*++argv); + argv++; argc -= 2; + continue; + default: + fputs(progname, stderr); + fputs(": unknown option '", stderr); + fputs(argv[0], stderr); + fputs("'\n", stderr); + goto userr; + } + if ((argc < 1) | (argc > 2)) + goto userr; + origIDF = argv[0]; + revIDF = (argc == 1) ? argv[0] : argv[1]; /* load Input Data File */ our_idf = idf_load(origIDF); if (our_idf == NULL) { @@ -520,4 +541,9 @@ main(int argc, char *argv[]) return(1); } return(0); /* finito! */ +userr: + fputs("Usage: ", stderr); + fputs(progname, stderr); + fputs(" [-c][-s Ksamps] Model.idf [Revised.idf]\n", stderr); + return(1); }