163 #define MINDEGCHANGE 55 // Minimum change (degrees squared) in sum of zenith and azimuth angle squared
169 int i,
j,
nb, modnum =
input->atrem_model;
170 static int firstCall = 1;
172 static double prev_ddeg = -999, prev_max_senz, prev_min_senz;
173 static float **angle_limit, *ang_senz, *ang_solz;
174 static int n_senz, n_solz, so_ang, se_ang;
175 static int prev_modnum;
176 float limitang, *anglelimit;
181 if (firstCall == 1) {
184 prev_modnum = P.model;
187 printf(
"Reading geometry limiting angles for Atrem\n");
188 if (
get_angle_limits(&anglelimit, &ang_senz, &ang_solz, &n_senz, &n_solz)) {
189 printf(
"-E- %s line %d : Error reading angle_limit file.\n",
194 if ((angle_limit = (
float **) calloc(n_senz,
sizeof (
float *))) ==
NULL) {
195 printf(
"-E- : Error allocating memory to tindx\n");
199 for (
j = 0;
j < n_senz;
j++) {
200 if ((angle_limit[
j] = (
float *) calloc(n_solz,
sizeof (
float))) ==
NULL) {
201 printf(
"-E- : Error allocating memory to tindx\n");
204 for (
i = 0;
i < n_solz;
i++) {
205 angle_limit[
j][
i] = *(anglelimit +
j * (n_solz) +
i);
211 prev_max_senz =
l1rec->senz[ip];
212 prev_min_senz =
l1rec->senz[ip];
217 if (
l1rec->senz[ip] > prev_max_senz) prev_max_senz =
l1rec->senz[ip];
218 if (
l1rec->senz[ip] < prev_min_senz) prev_min_senz =
l1rec->senz[ip];
220 prev_ddeg =
fabs(prev_max_senz - prev_min_senz);
225 if (firstCall == 1 || prev_ddeg >= limitang || P.dogeom != 0) {
301 prev_max_senz =
l1rec->senz[ip];
302 prev_min_senz =
l1rec->senz[ip];
313 if (P.model != prev_modnum) {
316 printf(
"-E- %s line %d : Atmospheric data could not be initialized.\n",
321 prev_modnum = P.model;
327 if (
input->atrem_splitpaths) {
345 for (
i = 0;
i < P.nobs;
i++) {
358 float get_atrem(
float *tg_tot,
float *rhot, paramstr *P) {
360 double const1 = 0, const2 = 0, const3 = 0, const4 = 0, const5 = 0, const6 = 0;
361 double ratio_94c, ratio_94co, ratio_114c, ratio_114co;
374 for (
i = P->start_ndx[0]; i <= P->end_ndx[0];
i++) {
379 for (
i = P->start_ndx[1]; i <= P->end_ndx[1];
i++) {
386 for (
i = P->start_p94; i <= P->end_p94;
i++) {
391 ratio_94co = const3 / ((P->wt1 * const1) + (P->wt2 * const2));
392 ratio_94c = ratio_94co;
394 if (ratio_94co > 1.0) {
397 for (
i = P->start_ndx[0]; i <= P->end_ndx[0];
i++) {
398 const1 += (1.0 / rhot[
i]);
403 for (
i = P->start_ndx[1]; i <= P->end_ndx[1];
i++) {
404 const2 += (1.0 / rhot[
i]);
408 for (
i = P->start_p94; i <= P->end_p94;
i++) {
409 const3 += (1.0 / rhot[
i]);
413 ratio_94c = const3 / ((P->wt1 * const1) + (P->wt2 * const2));
419 for (
i = P->start_ndx[2]; i <= P->end_ndx[2];
i++) {
425 for (
i = P->start_ndx[3]; i <= P->end_ndx[3];
i++) {
431 for (
i = P->start_1p14; i <= P->end_1p14;
i++) {
446 ratio_114co = const6 / ((P->wt3 * const4) + (P->wt4 * const5));
447 ratio_114c = ratio_114co;
449 if (ratio_114co > 1.0) {
452 for (
i = P->start_ndx[2]; i <= P->end_ndx[2];
i++) {
453 const4 += (1.0 / rhot[
i]);
456 for (
i = P->start_ndx[3]; i <= P->end_ndx[3];
i++) {
457 const5 += (1.0 / rhot[
i]);
461 for (
i = P->start_1p14; i <= P->end_1p14;
i++) {
462 const6 += (1.0 / rhot[
i]);
465 ratio_114c = const6 / ((P->wt3 * const4) + (P->wt4 * const5));
470 double delta, deltab, fja, fjap1, fjb, fjbp1, vaptta, vapttb;
473 ja =
hunt(P->r0p94, P->nh2o, ratio_94c,
ja);
477 fja = (P->r0p94[
ja + 1] - ratio_94c) /
delta;
478 fjap1 = (ratio_94c - P->r0p94[
ja]) /
delta;
479 vaptta = fja * P->vaptot[
ja] + fjap1 * P->vaptot[
ja + 1];
480 if (ratio_94co > 1.0) vaptta = -vaptta;
482 if (
ja < 0) vaptta = P->vaptot[
ja + 1];
483 if (
ja > P->nh2o) vaptta = P->vaptot[
ja];
486 if (ratio_94co <= 1.0) {
487 for (
i = 0;
i < P->nobs;
i++) {
489 speca[
i] = fja * P->trntbl[
ja][
i] + fjap1 * P->trntbl[
ja + 1][
i];
491 if (
ja < 0) speca[
i] = P->trntbl[
ja + 1][
i];
497 if (ratio_94co > 1.0) {
498 for (
i = 0;
i < P->nobs;
i++) {
500 speca[
i] = 1.0 / (fja * P->trntbl[
ja][
i] + fjap1 * P->trntbl[
ja + 1][
i]);
502 if (
ja < 0) speca[
i] = 1.0 / P->trntbl[
ja + 1][
i];
510 jb =
hunt(&P->r1p14[0], P->nh2o, ratio_114c,
jb);
517 deltab = P->r1p14[
jb + 1] - P->r1p14[
jb];
518 fjb = (P->r1p14[
jb + 1] - ratio_114c) / deltab;
519 fjbp1 = (ratio_114c - P->r1p14[
jb]) / deltab;
520 vapttb = fjb * P->vaptot[
jb] + fjbp1 * P->vaptot[
jb + 1];
521 if (ratio_114co > 1.0) vapttb = -vapttb;
523 if (
jb < 0) vapttb = P->vaptot[
jb + 1];
527 if (ratio_114co <= 1.0) {
528 for (
i = 0;
i < P->nobs;
i++) {
530 specb[
i] = fjb * P->trntbl[
jb][
i] + fjbp1 * P->trntbl[
jb + 1][
i];
532 if (
jb < 0) specb[
i] = P->trntbl[
jb + 1][
i];
537 if (ratio_114co > 1.0) {
538 for (
i = 0;
i < P->nobs;
i++) {
540 specb[
i] = 1.0 / (fjb * P->trntbl[
jb][
i] + fjbp1 * P->trntbl[
jb + 1][
i]);
542 if (
jb < 0) specb[
i] = 1.0 / P->trntbl[
jb + 1][
i];
548 clmwvp = 0.5 * (vaptta + vapttb) / P->g_vap_equiv;
549 spec450 = 1.0 - 0.5 * (speca[P->idx450] + specb[P->idx450]);
553 for (
i = 0;
i < P->nobs;
i++) {
554 specav = 0.5 * (speca[
i] + specb[
i]);
555 tg_tot[
i] = specav + spec450;
627 int32_t
hunt(
float *xx, int32_t n,
double x, int32_t jlo) {
628 int32_t inc, jhi, jm;
631 ascnd = (xx[n - 1] >= xx[0]);
634 if (jlo >= 0 && jlo < n) {
636 if ((
x >= xx[jlo]) == ascnd) {
638 while (jhi < n && ((
x >= xx[jhi]) == ascnd)) {
649 while (jlo >= 0 && ((
x < xx[jlo]) == ascnd)) {
663 while (jhi - jlo != 1) {
665 jm = (jhi + jlo) / 2;
667 if ((
x >= xx[jm]) == ascnd) {
674 if (
x == xx[n - 1]) jlo = n - 2;
675 if (
x == xx[0]) jlo = 0;
683 printf(
"RJH: Initializing ATM for model number = %d\n",
model);
685 if (model < 0 || model >
MODELMAX) {
686 printf(
"-E- %sline %d: Invalid ATM Model number\n Value must be between 1 and 7\n: get_atrem_cor3\n",
692 for (
i = 0;
i <
nb;
i++) {
725 if (
fabs(
lat) < 30)
return (1);
731 if (lat < 60 && lat > 30)
return (3);
732 if (lat < -30 && lat >-60)
return (2);
733 if (
lat > 60)
return (5);
739 if (lat < 60 && lat > 30)
return (2);
740 if (lat < -30 && lat >-60)
return (3);
741 if (
lat > 60)
return (4);
757 int32_t
nb, atrem_opt =
input->atrem_opt, atrem_full =
input->atrem_full, atrem_geom =
input->atrem_geom;
758 int32_t atrem_splitpaths =
input->atrem_splitpaths, atrem_model =
input->atrem_model, gas_opt =
input->gas_opt;
764 int *
model, flag_gas;
767 fwhm = (
float *) calloc(1,
sizeof (
fwhm));
768 xppp = (
float *) calloc(1,
sizeof (
xppp));
770 if ((filedir = getenv(
"OCDATAROOT")) ==
NULL) {
771 printf(
"-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
799 printf(
"-E- %s line %d : Unable to determine 450 nm index from spectrum.\n",
823 if (atrem_model == 0) {
829 if (atrem_model <= 6) {
830 *
model = atrem_model;
833 printf(
"-E- %s line %d : Invalid atmospheric model, atrem_model = %d. Valid range is 0-6.\n",
834 __FILE__, __LINE__, atrem_model);
842 printf(
"-E- %s line %d : Atmospheric data could not be initialized.\n",
854 printf(
"-E- %s line %d : Elevation=%f must be less than the maximum elevation in the atmospheric model.\n",
862 printf(
"-E- %s line %d : Sensor altitude=%f must be greater than the bottom surface elevation.\n",
881 wndow1 = (
float *) calloc(1,
sizeof (
float));
882 wndow2 = (
float *) calloc(1,
sizeof (
float));
883 wndow3 = (
float *) calloc(1,
sizeof (
float));
884 wndow4 = (
float *) calloc(1,
sizeof (
float));
885 wp94c = (
float *) calloc(1,
sizeof (
float));
886 w1p14c = (
float *) calloc(1,
sizeof (
float));
910 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
911 "in the .94-um region1:%f\nValid values are 0.6-2.5\n",
getinput6_.wndow1);
912 printf(
"-E- %s line %d : See stderr output for details.\n",
917 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
918 "in the .94-um region2:%f\nValid values are 0.6-2.5\n",
getinput6_.wndow2);
919 printf(
"-E- %s line %d : See stderr output for details.\n",
924 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
926 printf(
"-E- %s line %d : See stderr output for details.\n",
931 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
932 "in the .94-um region3:%f\nValid values are 0.6-2.5\n",
getinput6_.wndow3);
933 printf(
"-E- %s line %d : See stderr output for details.\n",
938 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
939 "in the .94-um region4:%f\nValid values are 0.6-2.5\n",
getinput6_.wndow4);
940 printf(
"-E- %s line %d : See stderr output for details.\n",
945 fprintf(
stderr,
"Invalid wavelength position for first atmospheric window " \
947 printf(
"-E- %s line %d : See stderr output for details.\n",
964 if (atrem_splitpaths > 0 && atrem_full == 0) {
965 printf(
"ATREM: Turning on atrem_full because you selected atrem_splitpaths\n");
969 printf(
"ATREM: Warning : full_calc !=0. Atrem will calculate transmittance table for every pixel\n");
986 printf(
"ATREM: Warning : dogeom !=0. Geometry will be calculated every pixel\n");
988 P->dogeom = atrem_geom;
991 nb1 = (int32_t *) calloc(1,
sizeof (int32_t));
992 nb2 = (int32_t *) calloc(1,
sizeof (int32_t));
993 nb3 = (int32_t *) calloc(1,
sizeof (int32_t));
994 nb4 = (int32_t *) calloc(1,
sizeof (int32_t));
995 nbp94 = (int32_t *) calloc(1,
sizeof (int32_t));
996 nb1p14 = (int32_t *) calloc(1,
sizeof (int32_t));
1020 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1021 "the .94-um region:%d\nValid values are 1-50\n",
getinput7_.nb1);
1022 printf(
"-E- %s line %d : See stderr output for details.\n",
1023 __FILE__, __LINE__);
1028 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1029 "the .94-um region:%d\nValid values are 1-50\n",
getinput7_.nb2);
1030 printf(
"-E- %s line %d : See stderr output for details.\n",
1031 __FILE__, __LINE__);
1035 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1036 "the .94-um region:%d\nValid values are 1-90\n",
getinput7_.nbp94);
1037 printf(
"-E- %s line %d : See stderr output for details.\n",
1038 __FILE__, __LINE__);
1042 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1043 "the .94-um region:%d\nValid values are 1-50\n",
getinput7_.nb3);
1044 printf(
"-E- %s line %d : See stderr output for details.\n",
1045 __FILE__, __LINE__);
1049 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1050 "the .94-um region:%d\nValid values are 1-50\n",
getinput7_.nb4);
1051 printf(
"-E- %s line %d : See stderr output for details.\n",
1052 __FILE__, __LINE__);
1056 fprintf(
stderr,
"Invalid number of channels for first wavelength position in " \
1057 "the .94-um region:%d\nValid values are 1-90\n",
getinput7_.nbp94);
1058 printf(
"-E- %s line %d : See stderr output for details.\n",
1059 __FILE__, __LINE__);
1065 h2o = (int32_t *) calloc(1,
sizeof (int32_t));
1066 co2 = (int32_t *) calloc(1,
sizeof (int32_t));
1067 o3 = (int32_t *) calloc(1,
sizeof (int32_t));
1068 n2o = (int32_t *) calloc(1,
sizeof (int32_t));
1069 co = (int32_t *) calloc(1,
sizeof (int32_t));
1070 ch4 = (int32_t *) calloc(1,
sizeof (int32_t));
1071 o2 = (int32_t *) calloc(1,
sizeof (int32_t));
1072 no2 = (int32_t *) calloc(1,
sizeof (int32_t));
1105 if (atrem_opt > 0) {
1116 printf(
"ATREM Gas Options:H2O:1 CO2:%d O3:%d N2O:%d CO:%d CH4:%d O2:%d NO2:%d\n",
1123 printf(
"ATREM: cannot be used with gas_opt bit mask=%d (H2O)\n",
H2O_BIT);
1127 printf(
"ATREM: cannot be used with gas_opt bit mask=%d (NO2)\n",
NO2_BIT);
1132 printf(
"ATREM: cannot be used with gas_opt bit mask=%d (CO2)\n",
CO2_BIT);
1136 printf(
"ATREM: cannot be used with gas_opt bit mask=%d (O3)\n",
O3_BIT);
1141 printf(
"Error: Conflict using ATREM (gas_opt=16 bitmask) with atrem_opt=%d and gas_opt=%d. " \
1142 "\nPlease resolve. Refer to command line options for atrem_opt and gas_opt.\n", atrem_opt, gas_opt);
1147 vrto3 = (
float *) calloc(1,
sizeof (
float));
1148 sno2 = (
float *) calloc(1,
sizeof (
float));
1174 int get_angle_limits(
float **anglelimit,
float **insenz,
float **insolz,
int *n_senz,
int *n_solz) {
1177 char *
infile =
"atrem_angle_limit.nc";
1180 char name[H4_MAX_NC_NAME];
1181 char sdsname[H4_MAX_NC_NAME];
1186 int dimids[H4_MAX_VAR_DIMS];
1191 static float *angle_limit;
1193 if ((filedir = getenv(
"OCDATAROOT")) ==
NULL) {
1194 printf(
"-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
1202 printf(
"ATREM Angle_Limit FILE=%s\n",
filename);
1204 if (nc_open(
filename, NC_NOWRITE, &ncid) == NC_NOERR) {
1208 status = nc_inq_varid(ncid, sdsname, &sds_id);
1209 if (
status != NC_NOERR) {
1210 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1211 __FILE__, __LINE__, sdsname,
infile);
1215 status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1218 if (nc_inq_dimlen(ncid, dimids[0], &length) != NC_NOERR) {
1219 nc_inq_dim(ncid, dimids[0],
name, &length);
1221 "-E- %s line %d: could not get size of dimension \"%s\" in netCDF File.\n",
1222 __FILE__, __LINE__,
name);
1228 if ((
senz = (
float *) calloc(*n_senz,
sizeof (
float))) ==
NULL) {
1229 printf(
"-E- : Error allocating memory to senz\n");
1233 if (nc_get_var(ncid, sds_id,
senz) != NC_NOERR) {
1234 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1235 __FILE__, __LINE__, sdsname,
infile);
1241 status = nc_inq_varid(ncid, sdsname, &sds_id);
1242 if (
status != NC_NOERR) {
1243 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1244 __FILE__, __LINE__, sdsname,
infile);
1248 status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1250 if (
status != NC_NOERR) {
1251 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1252 __FILE__, __LINE__, sdsname,
infile);
1256 if (nc_inq_dimlen(ncid, dimids[0], &length) != NC_NOERR) {
1257 nc_inq_dim(ncid, dimids[0],
name, &length);
1259 "-E- %s line %d: could not get size of dimension \"%s\" in netCDF File.\n",
1260 __FILE__, __LINE__,
name);
1266 if ((
solz = (
float *) calloc(*n_solz,
sizeof (
float))) ==
NULL) {
1267 printf(
"-E- : Error allocating memory to solz\n");
1271 if (nc_get_var(ncid, sds_id,
solz) != NC_NOERR) {
1272 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1273 __FILE__, __LINE__, sdsname,
infile);
1277 strcpy(sdsname,
"angle_limit");
1279 status = nc_inq_varid(ncid, sdsname, &sds_id);
1280 if (
status != NC_NOERR) {
1281 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1282 __FILE__, __LINE__, sdsname,
infile);
1286 status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1288 if (
status != NC_NOERR) {
1289 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1290 __FILE__, __LINE__, sdsname,
infile);
1294 fprintf(
stderr,
"-E- %s line %d: Wrong number of dimensions for %s. Need 2 got %d.\n",
1295 __FILE__, __LINE__, sdsname, ndims);
1301 if ((angle_limit = (
float *) calloc((*n_senz) * (*n_solz),
sizeof (
float))) ==
NULL) {
1302 printf(
"-E- : Error allocating memory to angle_limit\n");
1313 if (nc_get_var(ncid, sds_id, angle_limit) != NC_NOERR) {
1314 fprintf(
stderr,
"-E- %s line %d: Error reading %s from %s.\n",
1315 __FILE__, __LINE__, sdsname,
infile);
1326 *insenz = (
float *)
senz;
1327 *insolz = (
float *)
solz;
1328 *insolz = (
float *)
solz;
1329 *anglelimit = (
float *) angle_limit;
1332 fprintf(
stderr,
"-E- %s line %d: Error opening infile = %s.\n",
1333 __FILE__, __LINE__,
infile);
1348 if (i < 0 || i >= n_senz)
i = 0;
1349 if (j < 0 || j >= n_solz)
j = 0;
1351 if (insenz >
senz[
i]) {
1352 while (i < n_senz && insenz >
senz[
i])
1354 if (
i >= n_senz)
i = n_senz - 1;
1356 while (
i >= 0 && insenz <
senz[
i])
1361 if (insolz >
solz[
j]) {
1362 while (j < n_solz && insolz >
solz[
j])
1364 if (
j >= n_solz)
j = n_solz - 1;
1366 while (
j >= 0 && insolz <
solz[
j])
1374 return (anglelimit[
i][
j]);