ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/genssky.c
Revision: 2.8
Committed: Sat Jun 7 05:09:45 2025 UTC (23 hours, 10 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.7: +4 -5 lines
Log Message:
refactor: Put some declarations into "paths.h" and included in "platform.h"

File Contents

# User Rev Content
1 greg 2.6 #include "color.h"
2 greg 2.2 #ifndef lint
3 greg 2.6 static const char RCSid[] =
4 greg 2.8 "$Id: genssky.c,v 2.7 2025/04/10 23:30:58 greg Exp $";
5 greg 2.2 #endif
6     /* Main function for generating spectral sky */
7     /* Cloudy sky computed as weight average of clear and cie overcast sky */
8 greg 2.1
9 greg 2.8 #include "copyright.h"
10     #include "paths.h"
11 greg 2.2 #include "atmos.h"
12 greg 2.1 #include "resolu.h"
13 greg 2.2 #include "rtio.h"
14     #include <ctype.h>
15     #ifdef _WIN32
16     #include <windows.h>
17     #else
18     #include <errno.h>
19     #include <sys/stat.h>
20     #include <sys/types.h>
21     #endif
22 greg 2.1
23     const double ARCTIC_LAT = 67.;
24     const double TROPIC_LAT = 23.;
25     const int SUMMER_START = 4;
26     const int SUMMER_END = 9;
27     const double GNORM = 0.777778;
28    
29     const double D65EFF = 203.; /* standard illuminant D65 */
30    
31 greg 2.2 /* Mean normalized relative daylight spectra where CCT = 6415K for overcast; */
32 greg 2.1 const double D6415[NSSAMP] = {0.63231, 1.06171, 1.00779, 1.36423, 1.34133,
33     1.27258, 1.26276, 1.26352, 1.22201, 1.13246,
34     1.0434, 1.05547, 0.98212, 0.94445, 0.9722,
35     0.82387, 0.87853, 0.82559, 0.75111, 0.78925};
36    
37 greg 2.2 /* European and North American zones */
38     struct {
39     char zname[8]; /* time zone name (all caps) */
40     float zmer; /* standard meridian */
41     } tzone[] = {{"YST", 135}, {"YDT", 120}, {"PST", 120}, {"PDT", 105},
42     {"MST", 105}, {"MDT", 90}, {"CST", 90}, {"CDT", 75},
43     {"EST", 75}, {"EDT", 60}, {"AST", 60}, {"ADT", 45},
44     {"NST", 52.5}, {"NDT", 37.5}, {"GMT", 0}, {"BST", -15},
45     {"CET", -15}, {"CEST", -30}, {"EET", -30}, {"EEST", -45},
46     {"AST", -45}, {"ADT", -60}, {"GST", -60}, {"GDT", -75},
47     {"IST", -82.5}, {"IDT", -97.5}, {"JST", -135}, {"NDT", -150},
48     {"NZST", -180}, {"NZDT", -195}, {"", 0}};
49    
50     static int make_directory(const char *path) {
51     #ifdef _WIN32
52     if (CreateDirectory(path, NULL) || GetLastError() == ERROR_ALREADY_EXISTS) {
53     return 1;
54     }
55     return 0;
56     #else
57     if (mkdir(path, 0777) == 0 || errno == EEXIST) {
58     return 1;
59     }
60     return 0;
61     #endif
62     }
63    
64 greg 2.3 inline static float deg2rad(float deg) { return deg * (PI / 180.); }
65    
66 greg 2.2 static int cvthour(char *hs, int *tsolar, double *hour) {
67     char *cp = hs;
68     int i, j;
69    
70     if ((*tsolar = *cp == '+'))
71     cp++; /* solar time? */
72     while (isdigit(*cp))
73     cp++;
74     if (*cp == ':')
75     *hour = atoi(hs) + atoi(++cp) / 60.0;
76     else {
77     *hour = atof(hs);
78     if (*cp == '.')
79     cp++;
80     }
81     while (isdigit(*cp))
82     cp++;
83     if (!*cp)
84     return (0);
85     if (*tsolar || !isalpha(*cp)) {
86     fprintf(stderr, "%s: bad time format: %s\n", progname, hs);
87     exit(1);
88     }
89     i = 0;
90     do {
91     for (j = 0; cp[j]; j++)
92     if (toupper(cp[j]) != tzone[i].zname[j])
93     break;
94     if (!cp[j] && !tzone[i].zname[j]) {
95     s_meridian = tzone[i].zmer * (PI / 180);
96     return (1);
97     }
98     } while (tzone[i++].zname[0]);
99    
100     fprintf(stderr, "%s: unknown time zone: %s\n", progname, cp);
101     fprintf(stderr, "Known time zones:\n\t%s", tzone[0].zname);
102     for (i = 1; tzone[i].zname[0]; i++)
103     fprintf(stderr, " %s", tzone[i].zname);
104     putc('\n', stderr);
105     exit(1);
106     }
107    
108     static void basename(const char *path, char *output, size_t outsize) {
109     const char *last_slash = strrchr(path, '/');
110     const char *last_backslash = strrchr(path, '\\');
111     const char *filename = path;
112     const char *last_dot;
113    
114     if (last_slash && last_backslash) {
115     filename =
116     (last_slash > last_backslash) ? last_slash + 1 : last_backslash + 1;
117     } else if (last_slash) {
118     filename = last_slash + 1;
119     } else if (last_backslash) {
120     filename = last_backslash + 1;
121     }
122    
123     last_dot = strrchr(filename, '.');
124     if (last_dot) {
125     size_t length = last_dot - filename;
126     if (length < outsize) {
127     strncpy(output, filename, length);
128     output[length] = '\0';
129     } else {
130     strncpy(output, filename, outsize - 1);
131     output[outsize - 1] = '\0';
132     }
133     }
134     }
135    
136 greg 2.3 static char *join_paths(const char *path1, const char *path2) {
137 greg 2.2 size_t len1 = strlen(path1);
138     size_t len2 = strlen(path2);
139     int need_separator = (path1[len1 - 1] != DIRSEP);
140    
141     char *result = malloc(len1 + len2 + (need_separator ? 2 : 1));
142     if (!result)
143     return NULL;
144    
145     strcpy(result, path1);
146     if (need_separator) {
147     result[len1] = DIRSEP;
148     len1++;
149     }
150     strcpy(result + len1, path2);
151    
152     return result;
153     }
154    
155 greg 2.1 static inline double wmean2(const double a, const double b, const double x) {
156     return a * (1 - x) + b * x;
157     }
158    
159     static inline double wmean(const double a, const double x, const double b,
160     const double y) {
161     return (a * x + b * y) / (a + b);
162     }
163    
164 greg 2.6 static double get_overcast_zenith_brightness(const double sundir[3]) {
165 greg 2.1 double zenithbr;
166     if (sundir[2] < 0) {
167     zenithbr = 0;
168     } else {
169     zenithbr = (8.6 * sundir[2] + .123) * 1000.0 / D65EFF;
170     }
171     return zenithbr;
172     }
173    
174 greg 2.2 /* from gensky.c */
175 greg 2.1 static double get_overcast_brightness(const double dz, const double zenithbr) {
176     double groundbr = zenithbr * GNORM;
177     return wmean(pow(dz + 1.01, 10), zenithbr * (1 + 2 * dz) / 3,
178     pow(dz + 1.01, -10), groundbr);
179     }
180    
181 greg 2.2 static void write_header(const int argc, char **argv, const double cloud_cover,
182     const double grefl, const int res) {
183 greg 2.4 int i;
184 greg 2.2 printf("# ");
185 greg 2.4 for (i = 0; i < argc; i++) {
186 greg 2.2 printf("%s ", argv[i]);
187     }
188     printf("\n");
189 greg 2.3 printf(
190     "#Cloud cover: %g\n#Ground reflectance: %g\n#Sky map resolution: %d\n\n",
191     cloud_cover, grefl, res);
192 greg 2.2 }
193    
194 greg 2.6 static void write_rad(const double *sun_radiance, const double intensity,
195     const FVECT sundir, const char *ddir,
196     const char *skyfile) {
197 greg 2.1 if (sundir[2] > 0) {
198 greg 2.2 printf("void spectrum sunrad\n0\n0\n22 380 780 ");
199 greg 2.4 int i;
200     for (i = 0; i < NSSAMP; ++i) {
201 greg 2.6 printf("%.3f ", sun_radiance[i]);
202 greg 2.1 }
203 greg 2.2 printf("\n\nsunrad light solar\n0\n0\n3 %.1f %.1f %.1f\n\n", intensity,
204     intensity, intensity);
205     printf("solar source sun\n0\n0\n4 %f %f %f 0.533\n\n", sundir[0], sundir[1],
206     sundir[2]);
207     }
208 greg 2.5 printf("void specpict skyfunc\n5 noop %s . 'Atan2(Dy,Dx)/PI+1' "
209     "'1-Acos(Dz)/PI'\n0\n0\n\n",
210 greg 2.2 skyfile);
211 greg 2.1 }
212    
213     static void write_hsr_header(FILE *fp, RESOLU *res) {
214 greg 2.3 float wvsplit[4] = {380, 480, 588, 780};
215 greg 2.1 newheader("RADIANCE", fp);
216     fputncomp(NSSAMP, fp);
217     fputwlsplit(wvsplit, fp);
218     fputformat(SPECFMT, fp);
219     fputc('\n', fp);
220     fputsresolu(res, fp);
221     }
222    
223 greg 2.3 static inline float frac(float x) { return x - floor(x); }
224    
225 greg 2.1 int gen_spect_sky(DATARRAY *tau_clear, DATARRAY *scat_clear,
226     DATARRAY *scat1m_clear, DATARRAY *irrad_clear,
227     const double cloud_cover, const FVECT sundir,
228 greg 2.3 const double grefl, const int res, const char *outname,
229 greg 2.6 const char *ddir, const double dirnorm, const double difhor) {
230 greg 2.1 char skyfile[PATH_MAX];
231 greg 2.3 if (!snprintf(skyfile, sizeof(skyfile), "%s%c%s_sky.hsr", ddir, DIRSEP,
232     outname)) {
233 greg 2.1 fprintf(stderr, "Error setting sky file name\n");
234     return 0;
235     };
236 greg 2.3 int xres = res;
237     int yres = xres / 2;
238     RESOLU rs = {PIXSTANDARD, xres, yres};
239 greg 2.1 FILE *skyfp = fopen(skyfile, "w");
240     write_hsr_header(skyfp, &rs);
241    
242     CNDX[3] = NSSAMP;
243    
244 greg 2.3 FVECT view_point = {0, 0, ER + 10};
245 greg 2.1 const double radius = VLEN(view_point);
246     const double sun_ct = fdot(view_point, sundir) / radius;
247 greg 2.6
248     double overcast_zenithbr = get_overcast_zenith_brightness(sundir);
249     double overcast_grndbr = overcast_zenithbr * GNORM;
250    
251     double dif_ratio = 1;
252     if (difhor > 0) {
253     DATARRAY *indirect_irradiance_clear = get_indirect_irradiance(irrad_clear, radius, sun_ct);
254     double overcast_ghi = overcast_zenithbr * 7.0 * PI / 9.0;
255     double diffuse_irradiance = 0;
256     int l;
257     for (l = 0; l < NSSAMP; ++l) {
258     diffuse_irradiance += indirect_irradiance_clear->arr.d[l] * 20; /* 20nm interval */
259     }
260     free(indirect_irradiance_clear);
261     diffuse_irradiance = wmean2(diffuse_irradiance, overcast_ghi, cloud_cover);
262 greg 2.7 if (diffuse_irradiance > 0) {
263     dif_ratio = difhor / WHTEFFICACY / diffuse_irradiance / 1.15; /* fudge */
264     }
265 greg 2.6 }
266 greg 2.4 int i, j, k;
267     for (j = 0; j < yres; ++j) {
268     for (i = 0; i < xres; ++i) {
269 greg 2.3 SCOLOR radiance = {0};
270 greg 2.1 SCOLR sky_sclr = {0};
271    
272 greg 2.3 float px = i / (xres - 1.0);
273     float py = j / (yres - 1.0);
274     float lambda = ((1 - py) * PI) - (PI / 2.0);
275     float phi = (px * 2.0 * PI) - PI;
276    
277     FVECT rdir = {cos(lambda) * cos(phi), cos(lambda) * sin(phi),
278     sin(lambda)};
279    
280     const double mu = fdot(view_point, rdir) / radius;
281     const double nu = fdot(rdir, sundir);
282    
283     /* hit ground */
284     if (rdir[2] < 0) {
285     get_ground_radiance(tau_clear, scat_clear, scat1m_clear, irrad_clear,
286     view_point, rdir, radius, mu, sun_ct, nu, grefl,
287     sundir, radiance);
288     } else {
289     get_sky_radiance(scat_clear, scat1m_clear, radius, mu, sun_ct, nu,
290     radiance);
291     }
292 greg 2.1
293 greg 2.4 for (k = 0; k < NSSAMP; ++k) {
294 greg 2.3 radiance[k] *= WVLSPAN;
295 greg 2.1 }
296    
297     if (cloud_cover > 0) {
298 greg 2.6 double skybr = get_overcast_brightness(rdir[2], overcast_zenithbr);
299 greg 2.3 if (rdir[2] < 0) {
300 greg 2.4 for (k = 0; k < NSSAMP; ++k) {
301 greg 2.6 radiance[k] = wmean2(radiance[k], overcast_grndbr * D6415[k], cloud_cover);
302 greg 2.3 }
303     } else {
304 greg 2.4 for (k = 0; k < NSSAMP; ++k) {
305 greg 2.3 radiance[k] = wmean2(radiance[k], skybr * D6415[k], cloud_cover);
306     }
307 greg 2.1 }
308     }
309    
310 greg 2.6 for (k = 0; k < NSSAMP; ++k) {
311     radiance[k] *= dif_ratio;
312     }
313    
314     scolor2scolr(sky_sclr, radiance, NSSAMP);
315 greg 2.1 putbinary(sky_sclr, LSCOLR, 1, skyfp);
316     }
317     }
318     fclose(skyfp);
319    
320 greg 2.2 /* Get solar radiance */
321 greg 2.1 double sun_radiance[NSSAMP] = {0};
322     get_solar_radiance(tau_clear, scat_clear, scat1m_clear, sundir, radius,
323     sun_ct, sun_radiance);
324     if (cloud_cover > 0) {
325 greg 2.6 double skybr = get_overcast_brightness(sundir[2], overcast_zenithbr);
326 greg 2.4 int i;
327     for (i = 0; i < NSSAMP; ++i) {
328 greg 2.1 sun_radiance[i] =
329     wmean2(sun_radiance[i], D6415[i] * skybr / WVLSPAN, cloud_cover);
330     }
331     }
332    
333 greg 2.6 /* Normalize */
334     double sum = 0.0;
335     for (i = 0; i < NSSAMP; ++i) {
336     sum += sun_radiance[i];
337     }
338     double mean = sum / NSSAMP;
339     for (i = 0; i < NSSAMP; ++i) {
340     sun_radiance[i] /= mean;
341     }
342     double intensity = mean * WVLSPAN;
343     if (dirnorm > 0) {
344     intensity = dirnorm / SOLOMG / WHTEFFICACY;
345     }
346    
347     write_rad(sun_radiance, intensity, sundir, ddir, skyfile);
348 greg 2.1 return 1;
349     }
350    
351 greg 2.2 static DpPaths get_dppaths(const char *dir, const double aod, const char *mname,
352     const char *tag) {
353 greg 2.1 DpPaths paths;
354    
355 greg 2.2 snprintf(paths.tau, PATH_MAX, "%s%ctau_%s_%s_%.2f.dat", dir, DIRSEP, tag,
356     mname, aod);
357     snprintf(paths.scat, PATH_MAX, "%s%cscat_%s_%s_%.2f.dat", dir, DIRSEP, tag,
358     mname, aod);
359     snprintf(paths.scat1m, PATH_MAX, "%s%cscat1m_%s_%s_%.2f.dat", dir, DIRSEP,
360     tag, mname, aod);
361     snprintf(paths.irrad, PATH_MAX, "%s%cirrad_%s_%s_%.2f.dat", dir, DIRSEP, tag,
362     mname, aod);
363 greg 2.1
364     return paths;
365     }
366    
367 greg 2.2 static void set_rayleigh_density_profile(Atmosphere *atmos, char *tag,
368     const int is_summer,
369 greg 2.1 const double s_latitude) {
370 greg 2.2 if (fabs(s_latitude * 180.0 / PI) > ARCTIC_LAT) {
371 greg 2.1 tag[0] = 's';
372     if (is_summer) {
373     tag[1] = 's';
374     atmos->rayleigh_density.layers[0].exp_scale = -1.0 / HR_SS;
375     atmos->beta_r0 = BR0_SS;
376     } else {
377     tag[1] = 'w';
378     atmos->rayleigh_density.layers[0].exp_scale = -1.0 / HR_SW;
379     atmos->beta_r0 = BR0_SW;
380     }
381 greg 2.2 } else if (fabs(s_latitude * 180.0 / PI) > TROPIC_LAT) {
382 greg 2.1 tag[0] = 'm';
383     if (is_summer) {
384     tag[1] = 's';
385     atmos->rayleigh_density.layers[0].exp_scale = -1.0 / HR_MS;
386     atmos->beta_r0 = BR0_MS;
387     } else {
388     tag[1] = 'w';
389     atmos->rayleigh_density.layers[0].exp_scale = -1.0 / HR_MW;
390     atmos->beta_r0 = BR0_MW;
391     }
392     } else {
393     tag[0] = 't';
394     tag[1] = 'r';
395     atmos->rayleigh_density.layers[0].exp_scale = -1.0 / HR_T;
396     atmos->beta_r0 = BR0_T;
397     }
398     tag[2] = '\0';
399     }
400    
401     static Atmosphere init_atmos(const double aod, const double grefl) {
402 greg 2.2 Atmosphere atmos = {.ozone_density = {.layers =
403     {
404     {.width = 25000.0,
405     .exp_term = 0.0,
406     .exp_scale = 0.0,
407     .linear_term = 1.0 / 15000.0,
408     .constant_term = -2.0 / 3.0},
409     {.width = AH,
410     .exp_term = 0.0,
411     .exp_scale = 0.0,
412     .linear_term = -1.0 / 15000.0,
413     .constant_term = 8.0 / 3.0},
414     }},
415     .rayleigh_density = {.layers =
416     {
417     {.width = AH,
418     .exp_term = 1.0,
419     .exp_scale = -1.0 / HR_MS,
420     .linear_term = 0.0,
421     .constant_term = 0.0},
422     }},
423     .beta_r0 = BR0_MS,
424     .beta_scale = aod / AOD0_CA,
425     .beta_m = NULL,
426     .grefl = grefl};
427 greg 2.1 return atmos;
428     }
429    
430     int main(int argc, char *argv[]) {
431     int month, day;
432     double hour;
433     FVECT sundir;
434     int num_threads = 1;
435     int sorder = 4;
436     int year = 0;
437     int tsolar = 0;
438 greg 2.2 int got_meridian = 0;
439 greg 2.1 double grefl = 0.2;
440     double ccover = 0.0;
441 greg 2.3 int res = 64;
442 greg 2.1 double aod = AOD0_CA;
443     char *outname = "out";
444     char *mie_path = getpath("mie_ca.dat", getrlibpath(), R_OK);
445 greg 2.2 char mie_name[20] = "mie_ca";
446 greg 2.1 char lstag[3];
447 greg 2.2 char *ddir = ".";
448 greg 2.4 int i;
449 greg 2.6 double dirnorm = 0; /* direct normal illuminance */
450     double difhor = 0; /* diffuse horizontal illuminance */
451 greg 2.2
452 greg 2.8 fixargv0(argv[0]);
453 greg 2.3 if (argc == 2 && !strcmp(argv[1], "-defaults")) {
454 greg 2.2 printf("-i %d\t\t\t\t#scattering order\n", sorder);
455     printf("-g %f\t\t\t#ground reflectance\n", grefl);
456     printf("-c %f\t\t\t#cloud cover\n", ccover);
457     printf("-r %d\t\t\t\t#image resolution\n", res);
458     printf("-d %f\t\t\t#broadband aerosol optical depth\n", AOD0_CA);
459     printf("-f %s\t\t\t\t#output name (-f)\n", outname);
460     printf("-p %s\t\t\t\t#atmos data directory\n", ddir);
461 greg 2.3 exit(0);
462 greg 2.2 }
463 greg 2.1
464     if (argc < 4) {
465 greg 2.2 fprintf(stderr,
466     "Usage: %s month day hour -y year -a lat -o lon -m tz -d aod -r "
467 greg 2.6 "res -n nproc -c ccover -l mie -L dirnorm_illum difhor_illum "
468     "-g grefl -f outpath\n",
469 greg 2.1 argv[0]);
470     return 0;
471     }
472    
473     month = atoi(argv[1]);
474 greg 2.2 if (month < 1 || month > 12) {
475     fprintf(stderr, "bad month");
476     exit(1);
477     }
478 greg 2.1 day = atoi(argv[2]);
479 greg 2.2 if (day < 1 || day > 31) {
480     fprintf(stderr, "bad month");
481     exit(1);
482     }
483     got_meridian = cvthour(argv[3], &tsolar, &hour);
484 greg 2.1
485     if (!compute_sundir(year, month, day, hour, tsolar, sundir)) {
486     fprintf(stderr, "Cannot compute solar angle\n");
487     exit(1);
488     }
489    
490 greg 2.4 for (i = 4; i < argc; i++) {
491 greg 2.1 if (argv[i][0] == '-') {
492     switch (argv[i][1]) {
493     case 'a':
494     s_latitude = atof(argv[++i]) * (PI / 180.0);
495     break;
496     case 'c':
497     ccover = atof(argv[++i]);
498     break;
499     case 'd':
500     aod = atof(argv[++i]);
501     break;
502 greg 2.2 case 'f':
503     outname = argv[++i];
504     break;
505     case 'g':
506     grefl = atof(argv[++i]);
507     break;
508 greg 2.1 case 'i':
509     sorder = atoi(argv[++i]);
510     break;
511     case 'l':
512     mie_path = argv[++i];
513 greg 2.2 basename(mie_path, mie_name, sizeof(mie_name));
514 greg 2.1 break;
515     case 'm':
516 greg 2.2 if (got_meridian) {
517     ++i;
518     break;
519     }
520 greg 2.1 s_meridian = atof(argv[++i]) * (PI / 180.0);
521     break;
522     case 'n':
523     num_threads = atoi(argv[++i]);
524     break;
525 greg 2.2 case 'o':
526     s_longitude = atof(argv[++i]) * (PI / 180.0);
527 greg 2.1 break;
528 greg 2.6 case 'L':
529     dirnorm = atof(argv[++i]);
530     difhor = atof(argv[++i]);
531     break;
532 greg 2.2 case 'p':
533     ddir = argv[++i];
534 greg 2.1 break;
535     case 'r':
536     res = atoi(argv[++i]);
537     break;
538 greg 2.2 case 'y':
539     year = atoi(argv[++i]);
540     break;
541 greg 2.1 default:
542     fprintf(stderr, "Unknown option %s\n", argv[i]);
543     exit(1);
544     }
545     }
546     }
547 greg 2.2 if (year && (year < 1950) | (year > 2050))
548     fprintf(stderr, "%s: warning - year should be in range 1950-2050\n",
549     progname);
550     if (month && !tsolar && fabs(s_meridian - s_longitude) > 45 * PI / 180)
551     fprintf(stderr,
552     "%s: warning - %.1f hours btwn. standard meridian and longitude\n",
553     progname, (s_longitude - s_meridian) * 12 / PI);
554 greg 2.1
555     Atmosphere clear_atmos = init_atmos(aod, grefl);
556    
557     int is_summer = (month >= SUMMER_START && month <= SUMMER_END);
558     if (s_latitude < 0) {
559     is_summer = !is_summer;
560     }
561     set_rayleigh_density_profile(&clear_atmos, lstag, is_summer, s_latitude);
562    
563 greg 2.2 /* Load mie density data */
564 greg 2.1 DATARRAY *mie_dp = getdata(mie_path);
565     if (mie_dp == NULL) {
566     fprintf(stderr, "Error reading mie data\n");
567     return 0;
568     }
569     clear_atmos.beta_m = mie_dp;
570    
571 greg 2.2 char gsdir[PATH_MAX];
572     size_t siz = strlen(ddir);
573 greg 2.3 if (ISDIRSEP(ddir[siz - 1]))
574     ddir[siz - 1] = '\0';
575 greg 2.2 snprintf(gsdir, PATH_MAX, "%s%catmos_data", ddir, DIRSEP);
576     if (!make_directory(gsdir)) {
577     fprintf(stderr, "Failed creating atmos_data directory");
578     exit(1);
579     }
580     DpPaths clear_paths = get_dppaths(gsdir, aod, mie_name, lstag);
581 greg 2.1
582     if (getpath(clear_paths.tau, ".", R_OK) == NULL ||
583     getpath(clear_paths.scat, ".", R_OK) == NULL ||
584     getpath(clear_paths.scat1m, ".", R_OK) == NULL ||
585     getpath(clear_paths.irrad, ".", R_OK) == NULL) {
586 greg 2.2 printf("# Pre-computing...\n");
587 greg 2.1 if (!precompute(sorder, clear_paths, &clear_atmos, num_threads)) {
588 greg 2.2 fprintf(stderr, "Pre-compute failed\n");
589 greg 2.1 return 0;
590     }
591     }
592    
593     DATARRAY *tau_clear_dp = getdata(clear_paths.tau);
594     DATARRAY *irrad_clear_dp = getdata(clear_paths.irrad);
595     DATARRAY *scat_clear_dp = getdata(clear_paths.scat);
596     DATARRAY *scat1m_clear_dp = getdata(clear_paths.scat1m);
597    
598 greg 2.2 write_header(argc, argv, ccover, grefl, res);
599    
600 greg 2.1 if (!gen_spect_sky(tau_clear_dp, scat_clear_dp, scat1m_clear_dp,
601 greg 2.6 irrad_clear_dp, ccover, sundir, grefl, res, outname, ddir,
602     dirnorm, difhor)) {
603 greg 2.1 fprintf(stderr, "gen_spect_sky failed\n");
604     exit(1);
605     }
606    
607     freedata(mie_dp);
608     freedata(tau_clear_dp);
609     freedata(scat_clear_dp);
610     freedata(irrad_clear_dp);
611     freedata(scat1m_clear_dp);
612    
613     return 1;
614     }