OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_atrem_corl1v2.c
Go to the documentation of this file.
1 /*
2  * get_atrem_cor2.c
3  *
4  * Created on: Feb 19, 2015
5  * Author: Rick Healy (richard.healy@nasa.gov)
6  * from Fortran Code by Bo Cai Gao
7  *
8  * * Notes about water vapor VMRS and related quantities: *
9  * *
10  * VAPVRT(60) - a table containing 60 column vapor values (in unit of cm) *
11  * *
12  * VAP_SLANT(I) = VAPVRT(I) * 2.0, VAP_SLANT is a new table for containing *
13  * two-way total vapor amounts. Here the number "2" can be *
14  * changed to other numbers, e.g., 2.5, without major *
15  * effects on retrieved water vapor values. *
16  * *
17  * G_VAP(I = 1,..., NL) = true vapor geometric factor for each layer in *
18  * the model atmosphere (after adjusting for the elevated *
19  * surface. *
20  * *
21  * VMRM(I) = VMRM(I)*G_VAP(I). The VMRS are multiplied by the geometrical *
22  * factor. We can calculate the vapor transmittance on the *
23  * Sun-surface-sensor path by assuming a vertical path in *
24  * the model atmosphere with geometric-factor-adjusted VMRS. *
25  * *
26  * CLMVAP = vertical column amount from ground to space in model atmosphere*
27  * CLMVAPP = vertical column amount from ground to aircraft or satellite *
28  * sensor in model atmosphere *
29  * Q = 2.152E25 = # of molecules above the surface at one atmosphere *
30  * (in unit of molecules/cm**2) *
31  * *
32  * VAP_SLANT_MDL= CLMVAP/COS(SOLZNI) + CLMVAPP/COS(OBSZNI) = total amount *
33  * of water vapor in the model atmosphere in the L-shaped *
34  * Sun-surface-plane ray path. *
35  * *
36  * G_VAP_EQUIV = VAP_SLANT_MDL / CLMVAP = the "equivalent" geometrical *
37  * factor corresponding to the total slant vapor amount *
38  * VAP_SLANT_MDL and the column vapor amount CLMVAP. *
39  * *
40  * SSH2O(I) (I = 1, ..., 60) - a pure scaling factor relative to the total *
41  * slant vapor amount of VAP_SLANT_MDL, and *
42  * SSH2O(I) = VAP_SLANT(I) / VAP_SLANT_MDL *
43  * *
44  * SH2O = one value of SSH2O(I). SH2O is used during generation of the *
45  * look-up table. *
46  * *
47  * VAPTT = VAP_SLANT_MDL*SH2O, is the absolute total vapor amount on the *
48  * L-shaped path corresponding to a spectrum stored in the *
49  * look-up table. *
50  * *
51  * CLMWVP = 0.5*(VAPTTA+VAPTTB)/G_VAP_EQUIV, is the retrieved column water *
52  * vapor amount from imaging spectrometer data. *
53  ********************************************************************************
54  *
55  * 03/01/2016 - Began converting rest of code to C
56  *
57  * 01/15/2016 - Split the solar and sensor paths directly inside atrem.
58  * specify with atrem_splitpaths. Only works with atrem_full on.
59  *
60  * 10/20/2015 - r.healy - added ATREM options to command line
61  * atrem_opt - select gases for transmittance calculation
62  * atrem_geom - turn on/off geometry recalculation
63  * 0 = geometry calculated on error angle limit
64  * 1 = recalculate every pixel
65  * atrem_full - turn on/off full calculation (k-dist otherwise)
66  * atrem_model - select atmospheric model (1-6)
67  * - 0= determine from latitude and day of year
68  *
69  * !* References: *
70 !* Gao, B.-C., K. Heidebrecht, and A. F. H. Goetz, Derivation of scaled *
71 !* surface reflectances from AVIRIS data, Remote Sens. Env., 44, *
72 !* 165-178, 1993. *
73 !* Gao, B.-C., and C. O. Davis, Development of an operational algorithm *
74 !* for removing atmospheric effects from HYDICE and HSI data, *
75 !* in SPIE'96 Conference Proceedings, Vol. 2819, 45-55, 1996. *
76 !* Gao, B.-C., and A. F. H. Goetz, Column atmospheric water vapor and *
77 !* vegetation liquid water retrievals from airborne imaging *
78 !* spectrometer data, J. Geophys. Res., 95, 3549-3564, 1990. *
79 !* Goetz, A. F. H., and M. Herring, The high resolution imaging *
80 !* spectrometer (HIRIS) for Eos, IEEE Trans. Geosci. Remote Sens., 27,*
81 !* 136-144, 1989. *
82 !* Goetz, A. F. H., G. Vane, J. Solomon, and B. N. Rock, Imaging *
83 !* spectrometry for Earth remote sensing, Science, 228, 1147-1153,1985*
84 !* Green, R. O., and B.-C. Gao, A Proposed Update to the Solar Irradiance*
85 !* Spectrum used in LOWTRAN and MODTRAN, in Summaries of the Fourth *
86 !* Annual JPL Airborne Geoscience Workshop, October 25-29, (Editor, *
87 !* R. O. Green), JPL Publ. 93-26, Vol. 1, pp. 81-84, Jet Propul. Lab, *
88 !* Pasadena, Calif., 1993. *
89 !* Kneizys, F. X., E. P. Shettle, L. W. Abreu, J. H. Chetwynd, G. P. *
90 !* Anderson, W. O. Gallery, J. E. A. Selby, and S. A. Clough, Users *
91 !* guide to LOWTRAN7, AFGL-TR-8-0177, Air Force Geophys. Lab., *
92 !* Bedford, Mass., 1988. *
93 !* Iqbal, M., An Introduction To Solar Radiation, Academic, San Diego, *
94 !* Calif., 1983. *
95 !* Malkmus, W., Random Lorentz band model with exponential-tailed S line *
96 !* intensity distribution function, J. Opt. Soc. Am., 57, 323-329,1967*
97 !* Press, W. H., B. P. Flannery, S. A. Teukolsky, and W. T. Vetterling, *
98 !* Numerical Recipes-The ART of Scientific Computing, Cambridge *
99 !* University Press, 1986. *
100 !* Rothman, L. S., et al., The HITRAN 2008 molecular spectroscopic *
101 !* database, JQSRT, 110, 533-572, 2009. *
102 !* Solomon, S., R. W. Portmann, R. W. Sanders, J. S. Daniel, W. Madsen, *
103 !* B. Bartram, and E. G. Dutton, On the role of nitrogen dioxide in *
104 !* the absorption of solar radiation, J. Geophys. Res., 104, *
105 !* 12047-12058, 1999. *
106 !* Tanre, D., C. Deroo, P. Duhaut, M. Herman, J. J. Morcrette, J. Perbos,*
107 !* and P. Y. Deschamps, Description of a computer code to simulate *
108 !* the satellite signal in the solar spectrum: the 5S code, Int. *
109 !* J. Remote Sens., 11, 659-668, 1990. *
110 !* Tanre, D., C. Deroo, P. Duhaut, M. Herman, J. J. Morcrette, J. Perbos,*
111 !* and P. Y. Deschamps, Simulation of the satellite signal in the *
112 !* solar spectrum (5S), Users' Guide (U. S. T. De Lille, 59655 *
113 !* Villeneu d'Ascq, France: Laboratoire d'Optique Atmospherique), *
114 !* 1986. *
115 !* Thuillier, G., et al., Solar irradiance reference spectra for two *
116 !* solar active levels, Adv. Space Res., 34, 256-261, 2004. *
117 !* Vane, G., R. O. Green, T. G. Chrien, H. T. Enmark, E. G. Hansen, and *
118 !* W. M. Porter, The Airborne Visible/Infrared Imaging Spectrometer, *
119 !* Remote Sens. Env., 44, 127-143, 1993. *
120 !* Vane, G. (Ed), Airborne visible/infrared imaging spectrometer *
121 !* (AVIRIS), JPL Publ. 87-38, Jet Propul. Lab, Pasadena, Calif., 1987.*
122 !* Vermote, E., D. Tanre, J. L. Deuze, M. Herman, and J. J. Morcrette, *
123 !* Second simulation of the satellite signal in the solar spectrum *
124 !* (6S), 6S User's Guide Version 1, NASA-GSFC, Greenbelt, Maryland, *
125 !* 134 pages, 1994. *
126 !* *
127 !********************************************************************************
128  *
129  */
130 
131 #include "atrem_corl1v2.h"
132 #include <sensorDefs.h>
133 #include <timeutils.h>
134 #include <math.h>
135 #define BUFSZ 100
136 #define MINDEGCHANGE 55 // Minimum change (degrees squared) in sum of zenith and azimuth angle squared
137 // for both solar and sensor angles before recalculating tran_table (transmittance table)
138 
139 int get_atrem_cor(int32_t sensorID, l1str *l1rec, int32_t ip, float *rhot, float *tg_tot, float *tg_sol, float *tg_sen) {
140 
141  static paramstr P;
142  int i, j, k, l, nb, modnum = input->atrem_model;
143  static int firstCall = 1;
144  int32_t nbands = l1rec->l1file->nbands;
145  static double prev_ddeg = -999, prev_max_senz, prev_min_senz;
146  static double start_time, tot_time = 0;
147  static int prevscan = -1;
148  static float **angle_limit, *ang_senz, *ang_solz;
149  static int n_senz, n_solz, so_ang, se_ang;
150  static int prev_modnum;
151  float limitang, *anglelimit;
152 
153  //Initialize input paramters
154 
155 
156  if (firstCall == 1) { //|| prev_dist > MINDEGCHANGE) {
157  //INIT
159  prev_modnum = P.model;
160 
161  if (P.dogeom == 0) {
162  printf("Reading geometry limiting angles for Atrem\n");
163  if (get_angle_limits(&anglelimit, &ang_senz, &ang_solz, &n_senz, &n_solz)) {
164  printf("-E- %s line %d : Error reading angle_limit file.\n",
165  __FILE__, __LINE__);
166  exit(FATAL_ERROR);
167  }
168 
169  if ((angle_limit = (float **) calloc(n_senz, sizeof (float *))) == NULL) {
170  printf("-E- : Error allocating memory to tindx\n");
171  exit(FATAL_ERROR);
172  }
173 
174  for (j = 0; j < n_senz; j++) {
175  if ((angle_limit[j] = (float *) calloc(n_solz, sizeof (float))) == NULL) {
176  printf("-E- : Error allocating memory to tindx\n");
177  exit(FATAL_ERROR);
178  }
179  for (i = 0; i < n_solz; i++) {
180  angle_limit[j][i] = *(anglelimit + j * (n_solz) + i);
181  //printf("RJH:2: angle_limit: %f %f %f\n",ang_solz[i],ang_senz[j],angle_limit[j][i]);
182 
183  }
184  }
185 
186  prev_max_senz = l1rec->senz[ip];
187  prev_min_senz = l1rec->senz[ip];
188  }
189  }
190 
191  if (P.dogeom == 0) {
192  if (l1rec->senz[ip] > prev_max_senz) prev_max_senz = l1rec->senz[ip];
193  if (l1rec->senz[ip] < prev_min_senz) prev_min_senz = l1rec->senz[ip];
194 
195  prev_ddeg = fabs(prev_max_senz - prev_min_senz);
196 
197  limitang = get_current_angle_limit(l1rec->senz[ip], l1rec->solz[ip], &se_ang, &so_ang, angle_limit, ang_senz, ang_solz, n_senz, n_solz);
198  //printf("RJH: prev_max_senz=%f prev_min_senz=%f limitang[%d]=%f prev_ddeg=%f senz=%f solz=%f \n",prev_max_senz,prev_min_senz,ip,limitang,prev_ddeg,l1rec->senz[ip],l1rec->solz[ip]);
199  }
200  if (firstCall == 1 || prev_ddeg >= limitang || P.dogeom != 0) {
201 
202  //printf("Calculating Transmittance table for Atrem correction, ip=%d\n",ip);
203  //start_time = now();
204  //printf("\nBegin get_atrem_cor processing at %s\n\n", ydhmsf(start_time,'L'));
205 
206 
207  geometry_l2gen_.splitpaths = 0;
208  geometry_l2gen_.senzn_l2 = l1rec->senz[ip];
209  geometry_l2gen_.senaz_l2 = l1rec->sena[ip];
210  geometry_l2gen_.solzn_l2 = l1rec->solz[ip];
211  getinput3_.vrto3 = l1rec->oz[ip];
212 
213  //geometry_(); //FORTRAN
214  geometry();
215  //printf("Processed geometry after %6.0f seconds\n",now()-start_time);
216 
217  //init_speccal_(); //FORTRAN
219  //printf("Processed init_speccal after %6.0f seconds\n",now()-start_time);
220 
221  //tran_table_(); //FORTRAN
222  tran_table();
223  //printf("Processed tran_table after %6.0f seconds\n",now()-start_time);
224 
225  P.nh2o = init_speccal3_.nh2o;
226  P.start_ndx[0] = init_speccal6_.ist1 - 1; // Fortran array index starts at 1, C at 0
227  P.start_ndx[1] = init_speccal6_.ist2 - 1;
228  P.end_ndx[0] = init_speccal6_.ied1 - 1;
229  P.end_ndx[1] = init_speccal6_.ied2 - 1;
230  P.start_p94 = init_speccal6_.istp94 - 1;
231  P.end_p94 = init_speccal6_.iedp94 - 1;
232  P.start_ndx[2] = init_speccal7_.ist3 - 1;
233  P.start_ndx[3] = init_speccal7_.ist4 - 1;
234  P.end_ndx[2] = init_speccal7_.ied3 - 1;
235  P.end_ndx[3] = init_speccal7_.ied4 - 1;
236  P.start_1p14 = init_speccal7_.ist1p14 - 1;
237  P.end_1p14 = init_speccal7_.ied1p14 - 1;
238  P.wt1 = init_speccal8_.wt1;
239  P.wt2 = init_speccal8_.wt2;
240  P.wt3 = init_speccal8_.wt3;
241  P.wt4 = init_speccal8_.wt4;
242  P.start2 = init_speccal10_.istrt2 - 1;
243  P.end2 = init_speccal10_.iend2 - 1;
244  P.ncv2 = init_speccal10_.ncv2;
245  P.finst2 = init_speccal10_.finst2;
246  P.natot = init_speccal11_.natot;
247  P.nbtot = init_speccal11_.nbtot;
248  P.nctot = init_speccal11_.nctot;
249  P.ndtot = init_speccal11_.ndtot;
250  P.g_vap_equiv = geometry3_.g_vap_equiv;
251  P.r0p94 = tran_table1_.r0p94;
252  P.r1p14 = tran_table1_.r1p14;
253  P.vaptot = tran_table1_.vaptot;
254  P.trntbl = tran_table1_.trntbl;
255 
256 
257  // printf("PARAM: nb: %d %d %d %d\n",P.nb1,P.nb2,P.nb3,P.nb4);
258  // printf("PARAM:nb: %d %d\n",P.nbp94,P.nb1p14);
259  // printf("PARAM:nh2o: %d\n",P.nh2o);
260  // printf("PARAM:nobs: %d\n",P.nobs);
261  // printf("PARAM:startndx: %d %d %d %d\n",P.start_ndx[0],P.start_ndx[1],P.start_ndx[2],P.start_ndx[3]);
262  // printf("PARAM:endndx: %d %d %d %d\n",P.end_ndx[0],P.end_ndx[1],P.end_ndx[2],P.end_ndx[3]);
263  // printf("PARAM:start_p94: %d\n",P.start_p94);
264  // printf("PARAM:end_p94: %d\n",P.end_p94);
265  // printf("PARAM:start_1p14: %d\n",P.start_1p14);
266  // printf("PARAM:end_1p14: %d\n",P.end_1p14);
267  // printf("PARAM:%d\n",P.start2);
268  // printf("PARAM:%d\n",P.end2);
269  //
270  // printf("PARAM:ncv2: %d\n",P.ncv2);
271  // printf("PARAM:ntot: %d %d %d %d\n",P.natot,P.nbtot,P.nctot,P.ndtot);
272  // printf("PARAM:wt: %f %f %f %f\n",P.wt1,P.wt2,P.wt3,P.wt4);
273  // printf("PARAM:delta: %f %f\n",P.delta,P.delta2);
274  // printf("PARAM:g_vap_equiv: %f \n",P.g_vap_equiv);
275  // printf("PARAM:ip=%d\n",ip);
276  // printf("PARAM:prev_dist=%f\n",prev_ddeg);
277  firstCall = 0;
278 
279  prev_max_senz = l1rec->senz[ip];
280  prev_min_senz = l1rec->senz[ip];
281  }
282 
283  // if (l1rec->iscan != prevscan) {
284  // prevscan = l1rec->iscan;
285  // }
286  if (modnum == 0) {
287  int16_t year, day;
288  double secs;
289  unix2yds(l1rec->scantime, &year, &day, &secs);
290  P.model = getModelNum(*l1rec->lat, day);
291  if (P.model != prev_modnum) {
292  nb = init_tpvmr_nc(P.model);
293  if (nb <= 0) {
294  printf("-E- %s line %d : Atmospheric data could not be initialized.\n",
295  __FILE__, __LINE__);
296  exit(FATAL_ERROR);
297  }
298  //model_adj_(); //FORTRAN
299  model_adjust();
300  prev_modnum = P.model;
301  }
302  }
303  l1rec->wv[ip] = get_atrem(tg_tot, rhot, &P); //returns water vapor(cm)
304 
305  // Calculate the separate path transmittances (solar and sensor) if selected
306  if (input->atrem_splitpaths) {
307  geometry_l2gen_.splitpaths = 1;
308  geometry_l2gen_.water_vapor = l1rec->wv[ip]; //Misunderstanding. This isn't used.
309  geometry_l2gen_.ja = P.ja;
310  geometry_l2gen_.jb = P.jb;
311  geometry_l2gen_.f1a = P.f1a;
312  geometry_l2gen_.f1b = P.f1b;
313  geometry_l2gen_.f2a = P.f2a;
314  geometry_l2gen_.f2b = P.f2b;
315 
316  // Call geometry with the indices from the tran_table
317  //geometry_(); //FORTRAN
318  geometry();
319 
320  // Don't need to call init_speccal since other trace gas transmittances don't depend on water vapor
321 
322  // recalculate transmittances based on separate solar/sensor paths using the tran_table indices from the first call
323  //tran_table_(); //FORTRAN
324  tran_table();
325 
326  for (i = 0; i < P.nobs; i++) {
327  tg_sol[i] = tran_table_l2gen_.tg_sol[i];
328  tg_sen[i] = tran_table_l2gen_.tg_sen[i];
329  }
330 
331  }
332  //printf("Water vapor[%d]=%f\n",ip,l1rec->wv[ip]);
333  //printf("Processed get_atrem after %6.0f seconds\n",now()-start_time);
334 
335 
336  return (0);
337 }
338 
339 float get_atrem(float *tg_tot, float *rhot, paramstr *P) {
340 
341  double const1 = 0, const2 = 0, const3 = 0, const4 = 0, const5 = 0, const6 = 0;
342  double ratio_94c, ratio_94co, ratio_114c, ratio_114co;
343  int32_t i, ja, jb;
344  float clmwvp;
345  /*
346  Arrays related to look-up table:
347  VAPTOT: TOTAL SUN-SURFACE-SENSOR PATH WATER VAPOR IN UNITS OF CM
348  R0P94 : Tc(0.94 um)/(WT1*Tc(0.86)+WT2*Tc(1.02))
349  R1P14 : Tc(1.14 um)/(WT3*Tc(1.05)+WT4*Tc(1.23))
350 
351  Calculating 3-channel ratios from an observed spectrum, using a
352  look-up table procedure to derive the column amount of water vapor
353  and to find the associated simulated transmittance spectrum.
354  */
355  for (i = P->start_ndx[0]; i <= P->end_ndx[0]; i++) {
356  const1 += rhot[i];
357  }
358  const1 /= P->nb1;
359 
360  for (i = P->start_ndx[1]; i <= P->end_ndx[1]; i++) {
361  const2 += rhot[i];
362  }
363  const2 /= P->nb2;
364 
365  // printf("const2=%f nb2=%d istr2=%d ind2=%d\n",const2,P->nb2,P->start_ndx[1],P->end_ndx[1]);
366 
367  for (i = P->start_p94; i <= P->end_p94; i++) {
368  const3 += rhot[i];
369  }
370  const3 /= P->nbp94;
371 
372  ratio_94co = const3 / ((P->wt1 * const1) + (P->wt2 * const2));
373  ratio_94c = ratio_94co;
374 
375  if (ratio_94co > 1.0) {
376  const1 = 0.0;
377 
378  for (i = P->start_ndx[0]; i <= P->end_ndx[0]; i++) {
379  const1 += (1.0 / rhot[i]);
380  }
381  const1 /= P->nb1;
382 
383  const2 = 0.0;
384  for (i = P->start_ndx[1]; i <= P->end_ndx[1]; i++) {
385  const2 += (1.0 / rhot[i]);
386  }
387  const2 /= P->nb2;
388  const3 = 0.0;
389  for (i = P->start_p94; i <= P->end_p94; i++) {
390  const3 += (1.0 / rhot[i]);
391  }
392  const3 /= P->nbp94;
393 
394  ratio_94c = const3 / ((P->wt1 * const1) + (P->wt2 * const2));
395  }
396 
397  debug_atrem.rp94 = ratio_94c;
398 
399  const4 = 0.0;
400  for (i = P->start_ndx[2]; i <= P->end_ndx[2]; i++) {
401  const4 += rhot[i];
402  }
403  const4 /= P->nb3;
404 
405  const5 = 0.0;
406  for (i = P->start_ndx[3]; i <= P->end_ndx[3]; i++) {
407  const5 += rhot[i];
408  }
409  const5 /= P->nb4;
410 
411  const6 = 0.0;
412  for (i = P->start_1p14; i <= P->end_1p14; i++) {
413  const6 += rhot[i];
414  }
415  const6 /= P->nb1p14;
416 
417  /* DEBUG
418  *
419  */
420  debug_atrem.cst1 = const1;
421  debug_atrem.cst2 = const2;
422  debug_atrem.cst3 = const3;
423  debug_atrem.cst4 = const4;
424  debug_atrem.cst5 = const5;
425  debug_atrem.cst6 = const6;
426 
427  ratio_114co = const6 / ((P->wt3 * const4) + (P->wt4 * const5));
428  ratio_114c = ratio_114co;
429 
430  if (ratio_114co > 1.0) {
431 
432  const4 = 0.0;
433  for (i = P->start_ndx[2]; i <= P->end_ndx[2]; i++) {
434  const4 += (1.0 / rhot[i]);
435  }
436  const4 /= P->nb3;
437  for (i = P->start_ndx[3]; i <= P->end_ndx[3]; i++) {
438  const5 += (1.0 / rhot[i]);
439  }
440  const5 /= P->nb4;
441  const6 = 0.0;
442  for (i = P->start_1p14; i <= P->end_1p14; i++) {
443  const6 += (1.0 / rhot[i]);
444  }
445  const6 /= P->nb1p14;
446  ratio_114c = const6 / ((P->wt3 * const4) + (P->wt4 * const5));
447  }
448 
449  debug_atrem.r1p14 = ratio_114c;
450 
451  double delta, deltab, fja, fjap1, fjb, fjbp1, vaptta, vapttb;
452  double speca[NBANDS], specb[NBANDS], specav, spec450;
453  ja = P->nh2o / 2;
454  ja = hunt(P->r0p94, P->nh2o, ratio_94c, ja);
455  // printf("xx[%d]=%f xx[%d]=%f JA=%d\n",ja-1,P->r0p94[ja-1],ja,P->r0p94[ja],ja);
456  if (ja >= 0 && ja < NH2OMAX) {
457  delta = P->r0p94[ja + 1] - P->r0p94[ja];
458  fja = (P->r0p94[ja + 1] - ratio_94c) / delta;
459  fjap1 = (ratio_94c - P->r0p94[ja]) / delta;
460  vaptta = fja * P->vaptot[ja] + fjap1 * P->vaptot[ja + 1];
461  if (ratio_94co > 1.0) vaptta = -vaptta;
462  } else {
463  if (ja < 0) vaptta = P->vaptot[ja + 1];
464  if (ja > P->nh2o) vaptta = P->vaptot[ja];
465  }
466 
467  if (ratio_94co <= 1.0) {
468  for (i = 0; i < P->nobs; i++) {
469  if (ja >= 0 && ja < NH2OMAXM1) {
470  speca[i] = fja * P->trntbl[ja][i] + fjap1 * P->trntbl[ja + 1][i];
471  } else {
472  if (ja < 0) speca[i] = P->trntbl[ja + 1][i];
473  if (ja >= NH2OMAXM1) speca[i] = P->trntbl[ja][i];
474  }
475  }
476  }
477 
478  if (ratio_94co > 1.0) {
479  for (i = 0; i < P->nobs; i++) {
480  if (ja >= 0 && ja < NH2OMAXM1) {
481  speca[i] = 1.0 / (fja * P->trntbl[ja][i] + fjap1 * P->trntbl[ja + 1][i]);
482  } else {
483  if (ja < 0) speca[i] = 1.0 / P->trntbl[ja + 1][i];
484  if (ja >= NH2OMAXM1) speca[i] = 1.0 / P->trntbl[ja][i];
485  }
486  }
487  }
488 
489  jb = ja;
490 
491  jb = hunt(&P->r1p14[0], P->nh2o, ratio_114c, jb);
492  //printf("RJH: 1p14 JB=%d\n",jb);
493 
494  debug_atrem.jac = ja;
495  debug_atrem.jbc = jb;
496 
497  if (jb >= 0 && jb < NH2OMAXM1) {
498  deltab = P->r1p14[jb + 1] - P->r1p14[jb];
499  fjb = (P->r1p14[jb + 1] - ratio_114c) / deltab;
500  fjbp1 = (ratio_114c - P->r1p14[jb]) / deltab;
501  vapttb = fjb * P->vaptot[jb] + fjbp1 * P->vaptot[jb + 1];
502  if (ratio_114co > 1.0) vapttb = -vapttb;
503  } else {
504  if (jb < 0) vapttb = P->vaptot[jb + 1];
505  if (jb <= NH2OMAXM1) vapttb = P->vaptot[jb];
506  }
507 
508  if (ratio_114co <= 1.0) {
509  for (i = 0; i < P->nobs; i++) {
510  if (jb >= 0 && jb < NH2OMAXM1) {
511  specb[i] = fjb * P->trntbl[jb][i] + fjbp1 * P->trntbl[jb + 1][i];
512  } else {
513  if (jb < 0) specb[i] = P->trntbl[jb + 1][i];
514  if (jb >= NH2OMAXM1) specb[i] = P->trntbl[jb][i];
515  }
516  }
517  }
518  if (ratio_114co > 1.0) {
519  for (i = 0; i < P->nobs; i++) {
520  if (jb >= 0 && jb < NH2OMAXM1) {
521  specb[i] = 1.0 / (fjb * P->trntbl[jb][i] + fjbp1 * P->trntbl[jb + 1][i]);
522  } else {
523  if (jb < 0) specb[i] = 1.0 / P->trntbl[jb + 1][i];
524  if (jb >= NH2OMAXM1) specb[i] = 1.0 / P->trntbl[jb][i];
525  }
526  }
527  }
528 
529  clmwvp = 0.5 * (vaptta + vapttb) / P->g_vap_equiv;
530  spec450 = 1.0 - 0.5 * (speca[P->idx450] + specb[P->idx450]); // should be 0.0
531 
532  // Derivation of surface reflectances
533 
534  for (i = 0; i < P->nobs; i++) {
535  specav = 0.5 * (speca[i] + specb[i]);
536  tg_tot[i] = specav + spec450;
537  //printf("RJH: Atrem: %d %f YY=%f %f %f\n",i,tg_tot[i],rhot[i],rhot[i]/specav,rhot[i]-rhot[i]/specav);
538  }
539 
540  P->ja = ja;
541  P->jb = jb;
542  P->f1a = fja;
543  P->f2a = fjap1;
544  P->f1b = fjb;
545  P->f2b = fjbp1;
546 
547 
548  /*
549  // Smooth the derived surface reflectance spectra
550  // rhot = yy from atrem fortran code
551  // tg_tot = vc from atrem fortran code
552  int ii,j;
553  double truncv;
554 
555  if (P->delta2 > P->delta) {
556 
557  // * First, replace radiances <= 0 near the spectral overlapping parts of the
558  // * four AVIRIS spectrometers by radiances in the nearby AVIRIS' channels.
559 
560  for (i=P->natot-3; i< P->natot+2; i++) {
561  if (rhot[i] <= 0.0) rhot[i] = rhot[i-1];
562  }
563  for (i=P->nbtot-3; i< P->nbtot+2; i++) {
564  if (rhot[i] <= 0.0) rhot[i] = rhot[i-1];
565  }
566  for (i=P->nctot-3; i< P->nctot+2; i++) {
567  if (rhot[i] <= 0.0) rhot[i] = rhot[i-1];
568  }
569  for (i=P->ndtot-3; i< P->ndtot+2; i++) {
570  if (rhot[i] <= 0.0) rhot[i] = rhot[i-1];
571  }
572  for (i=P->start2-1; i<P->end2; i++){
573  truncv = 0.0;
574  ii = i - P->ncv2 - 1;
575  for (j=ii; j<i+P->ncv2; j++) {
576  truncv += rhot[j]*P->finst2[j-ii+1];
577  }
578  rhot[i] = truncv;
579  }
580  }
581  */
582 
583  return (clmwvp);
584 
585 }
586 
587 /*********************************************************************************
588  * *
589  * Name: HUNT *
590  * Purpose: finds the element in array XX that is closest to value X. Array AA *
591  * must be monotonic, either increasing or decreasing. *
592  * Parameters: XX - array to search *
593  * N - number of elements in the array *
594  * X - element to search for closest match *
595  * JLO - index of the closest matching element *
596  * Algorithm: this subroutine was copied from Numerical Recipes *
597  * Modified for C and cleaned up by *
598  * Richard Healy SAIC/NASA-GSFC 2/19/2015 *
599  * (Who didn't realize it was a Numerical Recipe's function until finished) *
600  * Globals used: none *
601  * Global output: none *
602  * Return Codes: none *
603  * Special Considerations: none *
604  * *
605  **********************************************************************************
606  *
607  */
608 int32_t hunt(float *xx, int32_t n, double x, int32_t jlo) {
609  int32_t inc, jhi, jm;
610  int ascnd;
611 
612  ascnd = (xx[n - 1] >= xx[0]);
613 
614  inc = 1;
615  if (jlo >= 0 && jlo < n) {
616 
617  if ((x >= xx[jlo]) == ascnd) {
618  jhi = jlo + inc;
619  while (jhi < n && ((x >= xx[jhi]) == ascnd)) {
620  jlo = jhi;
621  inc += inc;
622  jhi = jlo + inc;
623  }
624  if (jhi >= n)
625  jhi = n;
626 
627  } else {
628  jhi = jlo;
629  jlo = jhi - inc;
630  while (jlo >= 0 && ((x < xx[jlo]) == ascnd)) {
631  jhi = jlo;
632  inc += inc;
633  jlo = jhi - inc;
634  }
635  if (jlo < 0)
636  jlo = -1;
637 
638  }
639 
640  } else {
641  jlo = 0;
642  jhi = n + 1;
643  }
644  while (jhi - jlo != 1) {
645 
646  jm = (jhi + jlo) / 2;
647 
648  if ((x >= xx[jm]) == ascnd) {
649  jlo = jm;
650  } else {
651  jhi = jm;
652  }
653  }
654 
655  if (x == xx[n - 1]) jlo = n - 2;
656  if (x == xx[0]) jlo = 0;
657 
658  return (jlo);
659 }
660 
661 int init_tpvmr(int model) {
662 
663  int i, nb;
664  printf("Initializing ATM for model number = %d\n", model);
665  model--;
666  if (model < 0 || model > MODELMAX) {
667  printf("-E- %sline %d: Invalid ATM Model number\n Value must be between 1 and 7\n: get_atrem_cor3\n",
668  __FILE__, __LINE__);
669  exit(FATAL_ERROR);
670  }
671  nb = tpvmr_init1_.tpvmr[0][model];
672 
673  for (i = 0; i < nb; i++) {
674  getinput3_.h[i] = tpvmr_init1_.tpvmr[1 + (4 * i)][model];
675  //Convert the atmospheric pressure from "mb" to "atm.":
676  getinput3_.p[i] = tpvmr_init1_.tpvmr[2 + (4 * i)][model] / 1013.;
677  getinput3_.t[i] = tpvmr_init1_.tpvmr[3 + (4 * i)][model];
678  //Convert the VMR from the ppm unit in the model to absolute unit
679  getinput3_.vmr[i] = tpvmr_init1_.tpvmr[4 + (4 * i)][model]*1.0E-06;
680  }
681 
682  for (i = nb; i < MODELMAX; i++) {
683  getinput3_.h[i] = 1000.;
684  getinput3_.p[i] = 0.0;
685  getinput3_.t[i] = 300;
686  getinput3_.vmr[i] = 0.0;
687  }
688  getinput3_.nb = nb;
689  getinput3_.nl = nb - 1;
690 
691 
692 
693  return nb;
694 }
695 
696 void get_tpvmr(size_t layers, size_t models, int sds_id,
697  char filename[FILENAME_MAX], char *varname, float* var_a) {
698  size_t start[3], count[3];
699  int retval;
700  int xid;
701  start[0] = 0;
702  start[1] = 0;
703  start[2] = 0;
704  count[0] = models;
705  count[1] = layers;
706  count[2] = 0;
707  retval = nc_inq_varid(sds_id, varname, &xid);
708  if (retval != NC_NOERR) {
709  fprintf(stderr,
710  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
711  __FILE__, __LINE__, filename, varname);
712  exit(FATAL_ERROR);
713  }
714  retval = nc_get_vara_float(sds_id, xid, start, count, var_a);
715  if (retval != NC_NOERR) {
716  fprintf(stderr,
717  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
718  __FILE__, __LINE__, filename, varname);
719  exit(FATAL_ERROR);
720  }
721 }
722 
724 
725  int i;
726  char *filedir;
727  char filename[FILENAME_MAX];
728  char *tpvmr_file = "atrem_tpvmr.nc";
729  int xid, yid, retval, sds_id;
730  static size_t models, layers;
731  static float *h, *p, *t, *vmr;
732 
733  if (!h) {
734 
735  if ((filedir = getenv("OCDATAROOT")) == NULL) {
736  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
737  return (-1);
738  }
739 
740  strcpy(filename, filedir);
741  strcat(filename, "/common/");
742  strcat(filename, tpvmr_file);
743  strcat(filename, "\0");
744  printf("Initializing arrays for Atrem atmospheric models\n");
745 
746  retval = nc_open(filename, NC_NOWRITE, &sds_id);
747  if (retval != NC_NOERR) {
748  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
749  __FILE__, __LINE__, filename);
750  exit(FATAL_ERROR);
751  }
752  // Now read in the absorption coefficients
753  retval = nc_inq_dimid(sds_id, "n_layers", &xid) \
754  + nc_inq_dimlen(sds_id, xid, &layers) \
755  + nc_inq_dimid(sds_id, "n_models", &yid) \
756  + nc_inq_dimlen(sds_id, yid, &models);
757 
758  if (retval) {
759  fprintf(stderr, "-E- %s line %d: nc_inq_dimid(%s) failed.%d %d %d \n",
760  __FILE__, __LINE__, filename, (int) layers, (int) models, retval);
761  exit(FATAL_ERROR);
762  }
763 
764  h = (float *) calloc(layers*models, sizeof (float));
765  if (!(h)) {
766  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for h.\n",
767  __FILE__, __LINE__);
768  exit(FATAL_ERROR);
769  }
770  p = (float *) calloc(layers*models, sizeof (float));
771  if (!(p)) {
772  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for p.\n",
773  __FILE__, __LINE__);
774  exit(FATAL_ERROR);
775  }
776  t = (float *) calloc(layers*models, sizeof (float));
777  if (!(t)) {
778  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for t.\n",
779  __FILE__, __LINE__);
780  exit(FATAL_ERROR);
781  }
782  vmr = (float *) calloc(layers*models, sizeof (float));
783  if (!(vmr)) {
784  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for vmr.\n",
785  __FILE__, __LINE__);
786  exit(FATAL_ERROR);
787  }
788  get_tpvmr(layers, models, sds_id, filename, "h", h);
789  get_tpvmr(layers, models, sds_id, filename, "p", p);
790  get_tpvmr(layers, models, sds_id, filename, "t", t);
791  get_tpvmr(layers, models, sds_id, filename, "vmr", vmr);
792  }
793 
794  printf("Initializing ATM for model number = %d\n", model);
795  model--;
796 
797  if (model < 0 || model > MODELMAX) {
798  printf("-E- %sline %d: Invalid ATM Model number\n Value must be between 1 and 7\n: get_atrem_cor3\n",
799  __FILE__, __LINE__);
800  exit(FATAL_ERROR);
801  }
802 
803  for (i = 0; i < layers; i++) {
804  getinput3_.h[i] = h[model * layers + i];
805  //Convert the atmospheric pressure from "mb" to "atm.":
806  getinput3_.p[i] = p[model * layers + i] / 1013.;
807  getinput3_.t[i] = t[model * layers + i] / 1013.;
808  //Convert the VMR from the ppm unit in the model to absolute unit
809  getinput3_.vmr[i] = vmr[model * layers + i]*1.0e-06;
810  }
811 
812  for (i = layers; i < MODELMAX; i++) {
813  getinput3_.h[i] = 1000.;
814  getinput3_.p[i] = 0.0;
815  getinput3_.t[i] = 300;
816  getinput3_.vmr[i] = 0.0;
817  }
818  getinput3_.nb = layers;
819  getinput3_.nl = layers - 1;
820 
821 
822 
823  return layers;
824 }
825 
826 int getModelNum(float lat, int32_t day) {
827  // Determine which atmospheric model to use
828  // 1 = tropical
829  // 2 = mid latitude summer
830  // 3 = mid latitude winter
831  // 4 = subarctic summer
832  // 5 = subarctic winter
833  // 6 = US standard 1962
834  int16 mon = (int) day / 31 + 1; // month of year (no need for perfection..at least according to the sea surface salinity reference algorithm)
835 
836  if (fabs(lat) < 30) return (1);
837  else {
838  switch (mon) {
839  case 12:
840  case 1:
841  case 2:
842  if (lat < 60 && lat > 30) return (3);
843  if (lat < -30 && lat >-60) return (2);
844  if (lat > 60) return (5);
845  return (4);
846  break;
847  case 6:
848  case 7:
849  case 8:
850  if (lat < 60 && lat > 30) return (2);
851  if (lat < -30 && lat >-60) return (3);
852  if (lat > 60) return (4);
853  return (5);
854  break;
855  default:
856  return (6);
857 
858  }
859 
860 
861  }
862 
863 
864 }
865 
866 int init_atrem(int32_t sensorID, paramstr *P, l1str *l1rec, int32_t nbands) {
867 
868  int32_t nb, atrem_opt = input->atrem_opt, atrem_full = input->atrem_full, atrem_geom = input->atrem_geom;
869  int32_t atrem_splitpaths = input->atrem_splitpaths, atrem_model = input->atrem_model, gas_opt = input->gas_opt;
870  float xi, *fwave, *fwhm, *xppp;
871  float v, nwave;
872  int cnt = 0, i, j, k, l;
873  char *filedir;
874  char filename[FILENAME_MAX];
875  int *model, flag_gas;
876 
877  model = (int *) calloc(1, sizeof (model));
878  fwhm = (float *) calloc(1, sizeof (fwhm));
879  xppp = (float *) calloc(1, sizeof (xppp));
880 
881  if ((filedir = getenv("OCDATAROOT")) == NULL) {
882  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
883  return (-1);
884  }
885 
886  strcpy(filename, filedir);
887  strcat(filename, "/");
888  strcat(filename, sensorDir[sensorID]);
889  strcat(filename, "/\0");
890 
891  //INIT - get_input_ must be called before any common block structures are filled in.
892  // It will also fill some of the parameters with default values
893  get_input_();
894 
895  strcpy(input_l2gen_.filename, filename);
896  input_l2gen_.dln = strlen(filename);
897  //printf("filedir=%s Filename=%s len=%d\n",filedir, filename,input_l2gen_.dln);
898 
899  if (!(fwhm = l1rec->l1file->fwhm)) {
900  nwave = rdatreminfo(sensorID, 0, "fwhm", (void **) &fwhm);
901  }
902  for (i = 0; i < nbands; i++) {
903  getinput4_.wavobs[i] = l1rec->l1file->fwave[i] / 1000.; // Convert nm to microns
904  getinput4_.fwhm[i] = fwhm[i];
905  //printf("->RJH:fwave(%d)=%f fwhm(%d) = %f \n",i+1,getinput4_.wavobs[i],i,fwhm[i]);
906  }
907 
908  P->idx450 = bindex_get(450); // get the index nearest the 450nm wavelength
909  if (P->idx450 < 0) {
910  printf("-E- %s line %d : Unable to determine 450 nm index from spectrum.\n",
911  __FILE__, __LINE__);
912  exit(FATAL_ERROR);
913  }
914  // for (i=0;i<nbands;i++) {
915  // getinput4_.fwhm[i] = fwhm[i];
916  // // printf("->RJH:fwave(%d)=%f fwhm(%d) = %f\n",i+1,getinput4_.wavobs[i],i,fwhm[i]);
917  // }
918  /*
919  // Determine which atmospheric model to use
920  // call to get_input sets h,p,t, and vmr arrays to default model 1
921  // 1 = tropical
922  // 2 = mid latitude summer
923  // 3 = mid latitude winter
924  // 4 = subarctic summer
925  // 5 = subarctic winter
926  // 6 = US standard 1962
927  // 7 = user defined model
928 
929  //INIT
930  //Get Atmospheric model to use
931  */
932  *model = 6;
933 
934  if (atrem_model == 0) {
935  int16_t year, day;
936  double secs;
937  unix2yds(l1rec->scantime, &year, &day, &secs);
938  *model = getModelNum(*l1rec->lat, day);
939  } else {
940  if (atrem_model <= 6) {
941  *model = atrem_model;
942  // nwave = rdatreminfo(sensorID, 0, "model", (void **)&model);
943  } else {
944  printf("-E- %s line %d : Invalid atmospheric model, atrem_model = %d. Valid range is 0-6.\n",
945  __FILE__, __LINE__, atrem_model);
946  exit(FATAL_ERROR);
947  }
948  }
949  P->model = *model;
950  nb = init_tpvmr_nc(P->model);
951 
952  if (nb <= 0) {
953  printf("-E- %s line %d : Atmospheric data could not be initialized.\n",
954  __FILE__, __LINE__);
955  exit(FATAL_ERROR);
956  }
957 
958  getinput5_.nobs = nbands; //l1rec->nbands;
959  getinput5_.dlt = 0; //used internally to the fortran routines
960  getinput5_.dlt2 = 0; //to determine what to use for the width of the bands
961  getinput5_.hsurf = 0; //mean surface elevation
962  getinput14_.xppp = 700; //Plane/Satellite altitude (km)
963 
964  if (getinput5_.hsurf < 0 || getinput5_.hsurf > getinput3_.h[nb - 2]) {
965  printf("-E- %s line %d : Elevation=%f must be less than the maximum elevation in the atmospheric model.\n",
966  __FILE__, __LINE__, getinput5_.hsurf);
967  exit(FATAL_ERROR);
968  }
969 
970  nwave = rdatreminfo(sensorID, 0, "xppp", (void **) &xppp);
971 
972  if (getinput14_.xppp < getinput5_.hsurf) {
973  printf("-E- %s line %d : Sensor altitude=%f must be greater than the bottom surface elevation.\n",
974  __FILE__, __LINE__, getinput14_.xppp);
975  exit(FATAL_ERROR);
976 
977  }
978  /*
979  // Get ranges on curve for the two atmospheric windows surrounding the 1.14-um
980  // water vapor absorption feature and the center point of the 1.14-um water
981  // vapor absorption feature. Enter:
982  // 1. the midpoint of third window (0.6-2.5)
983  // 2. number of points to average for third window (1-10)
984  // 3. the midpoint of fourth window (0.6-2.5)
985  // 4. number of points to average for fourth window (1-10)
986  // 5. the midpoint of 1.14-um absorption feature (0.6-2.5)
987  // 6. the number of points to average for the absorption feature (1-30)
988  */
989  // This is the default for HICO HS
990  float *wndow1 = 0, *wndow2 = 0, *wp94c = 0, *wndow3 = 0, *wndow4 = 0, *w1p14c = 0;
991 
992  wndow1 = (float *) calloc(1, sizeof (float));
993  wndow2 = (float *) calloc(1, sizeof (float));
994  wndow3 = (float *) calloc(1, sizeof (float));
995  wndow4 = (float *) calloc(1, sizeof (float));
996  wp94c = (float *) calloc(1, sizeof (float));
997  w1p14c = (float *) calloc(1, sizeof (float));
998 
999  getinput6_.wndow1 = 0.705;
1000  getinput6_.wndow2 = 0.745;
1001  getinput6_.wp94c = 0.725;
1002  getinput6_.wndow3 = 0.805;
1003  getinput6_.wndow4 = 0.845;
1004  getinput6_.w1p14c = 0.825;
1005 
1006  int32_t Nbands;
1007 
1008  nwave = rdatreminfo(sensorID, 0, "window1", (void **) &wndow1);
1009  nwave = rdatreminfo(sensorID, 0, "window2", (void **) &wndow2);
1010  nwave = rdatreminfo(sensorID, 0, "window3", (void **) &wndow3);
1011  nwave = rdatreminfo(sensorID, 0, "window4", (void **) &wndow4);
1012  nwave = rdatreminfo(sensorID, 0, "wp94c", (void **) &wp94c);
1013  nwave = rdatreminfo(sensorID, 0, "w1p14c", (void **) &w1p14c);
1014 
1015  getinput6_.wndow1 = *wndow1;
1016  getinput6_.wndow2 = *wndow2;
1017  getinput6_.wp94c = *wp94c;
1018  getinput6_.wndow3 = *wndow3;
1019  getinput6_.wndow4 = *wndow4;
1020  getinput6_.w1p14c = *w1p14c;
1021 
1022  if (getinput6_.wndow1 < 0.6 || getinput6_.wndow1 > 2.5) {
1023  fprintf(stderr, "Invalid wavelength position for first atmospheric window " \
1024  "in the .94-um region1:%f\nValid values are 0.6-2.5\n", getinput6_.wndow1);
1025  printf("-E- %s line %d : See stderr output for details.\n",
1026  __FILE__, __LINE__);
1027  exit(FATAL_ERROR);
1028  }
1029  if (getinput6_.wndow2 < 0.6 || getinput6_.wndow2 > 2.5) {
1030  fprintf(stderr, "Invalid wavelength position for second atmospheric window " \
1031  "in the .94-um region2:%f\nValid values are 0.6-2.5\n", getinput6_.wndow2);
1032  printf("-E- %s line %d : See stderr output for details.\n",
1033  __FILE__, __LINE__);
1034  exit(FATAL_ERROR);
1035  }
1036  if (getinput6_.wp94c <= getinput6_.wndow1 || getinput6_.wp94c >= getinput6_.wndow2) {
1037  fprintf(stderr, "Invalid wavelength position for first atmospheric window " \
1038  "in the .94-um region:%f\nValid range is: %f < value < %f \n", getinput6_.wp94c, getinput6_.wndow1, getinput6_.wndow2);
1039  printf("-E- %s line %d : See stderr output for details.\n",
1040  __FILE__, __LINE__);
1041  exit(FATAL_ERROR);
1042  }
1043  if (getinput6_.wndow3 < 0.6 || getinput6_.wndow3 > 2.5) {
1044  fprintf(stderr, "Invalid wavelength position for first atmospheric window " \
1045  "in the 1.14-um region3:%f\nValid values are 0.6-2.5\n", getinput6_.wndow3);
1046  printf("-E- %s line %d : See stderr output for details.\n",
1047  __FILE__, __LINE__);
1048  exit(FATAL_ERROR);
1049  }
1050  if (getinput6_.wndow4 < 0.6 || getinput6_.wndow4 > 2.5) {
1051  fprintf(stderr, "Invalid wavelength position for second atmospheric window " \
1052  "in the 1.14-um region4:%f\nValid values are 0.6-2.5\n", getinput6_.wndow4);
1053  printf("-E- %s line %d : See stderr output for details.\n",
1054  __FILE__, __LINE__);
1055  exit(FATAL_ERROR);
1056  }
1057  if (getinput6_.w1p14c <= getinput6_.wndow3 || getinput6_.w1p14c >= getinput6_.wndow4) {
1058  fprintf(stderr, "Invalid wavelength position for first atmospheric window " \
1059  "in the .94-um region:%f\nValid range is: %f < value < %f \n", getinput6_.w1p14c, getinput6_.wndow3, getinput6_.wndow4);
1060  printf("-E- %s line %d : See stderr output for details.\n",
1061  __FILE__, __LINE__);
1062  exit(FATAL_ERROR);
1063  }
1064 
1065  // Set full_calc to 1 to turn on explicit, full calculation of
1066  // water vapor correction. Setting value to 0 turns on speedy
1067  // h2o absorption calculation and sets all other gas options to 0
1068 
1069  // int32_t *full_calc;
1070  // full_calc = (int32_t *) calloc(1,sizeof(int32_t));
1071  // if (atrem_full != 0) {
1072  // *full_calc = (atrem_full < 0? 0:1);
1073  // } else {
1074  // nwave = rdatreminfo(sensorID, 0, "full_calc", (void **) &full_calc);
1075  // }
1076 
1077  if (atrem_splitpaths > 0 && atrem_full == 0) {
1078  printf("ATREM: Turning on atrem_full because you selected atrem_splitpaths\n");
1079  atrem_full = 1;
1080  }
1081  if (atrem_full > 0)
1082  printf("ATREM: Warning : full_calc !=0. Atrem will calculate transmittance table for every pixel\n");
1083 
1084  // getinput5_.full_calc = *full_calc;
1085 
1086  getinput5_.full_calc = atrem_full;
1087 
1088  // int32_t *dogeom;
1089  // dogeom = (int32_t *) calloc(1,sizeof(int32_t));
1090  // if (atrem_geom != 0) {
1091  // *dogeom = (atrem_geom < 0? 0:1);
1092  // } else {
1093  // nwave = rdatreminfo(sensorID, 0, "dogeom", (void **) &dogeom);
1094  // }
1095  //
1096  // P->dogeom = *dogeom;
1097 
1098  if (atrem_geom > 0)
1099  printf("ATREM: Warning : dogeom !=0. Geometry will be calculated every pixel\n");
1100 
1101  P->dogeom = atrem_geom;
1102  //Default for HICO HS
1103  int32_t *nb1, *nb2, *nb3, *nb4, *nbp94, *nb1p14;
1104  nb1 = (int32_t *) calloc(1, sizeof (int32_t));
1105  nb2 = (int32_t *) calloc(1, sizeof (int32_t));
1106  nb3 = (int32_t *) calloc(1, sizeof (int32_t));
1107  nb4 = (int32_t *) calloc(1, sizeof (int32_t));
1108  nbp94 = (int32_t *) calloc(1, sizeof (int32_t));
1109  nb1p14 = (int32_t *) calloc(1, sizeof (int32_t));
1110 
1111  getinput7_.nb1 = 3;
1112  getinput7_.nb2 = 3;
1113  getinput7_.nb3 = 3;
1114  getinput7_.nb4 = 3;
1115  getinput7_.nbp94 = 5;
1116  getinput7_.nb1p14 = 5;
1117 
1118  nwave = rdatreminfo(sensorID, 0, "nb1", (void **) &nb1);
1119  nwave = rdatreminfo(sensorID, 0, "nb2", (void **) &nb2);
1120  nwave = rdatreminfo(sensorID, 0, "nb3", (void **) &nb3);
1121  nwave = rdatreminfo(sensorID, 0, "nb4", (void **) &nb4);
1122  nwave = rdatreminfo(sensorID, 0, "nbp94", (void **) &nbp94);
1123  nwave = rdatreminfo(sensorID, 0, "nb1p14", (void **) &nb1p14);
1124 
1125  getinput7_.nb1 = *nb1;
1126  getinput7_.nb2 = *nb2;
1127  getinput7_.nb3 = *nb3;
1128  getinput7_.nb4 = *nb4;
1129  getinput7_.nbp94 = *nbp94;
1130  getinput7_.nb1p14 = *nb1p14;
1131 
1132  if (getinput7_.nb1 < 1 || getinput7_.nb1 > 50) {
1133  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1134  "the .94-um region:%d\nValid values are 1-50\n", getinput7_.nb1);
1135  printf("-E- %s line %d : See stderr output for details.\n",
1136  __FILE__, __LINE__);
1137  exit(FATAL_ERROR);
1138  }
1139 
1140  if (getinput7_.nb2 < 1 || getinput7_.nb2 > 50) {
1141  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1142  "the .94-um region:%d\nValid values are 1-50\n", getinput7_.nb2);
1143  printf("-E- %s line %d : See stderr output for details.\n",
1144  __FILE__, __LINE__);
1145  exit(FATAL_ERROR);
1146  }
1147  if (getinput7_.nbp94 < 1 || getinput7_.nbp94 > 90) {
1148  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1149  "the .94-um region:%d\nValid values are 1-90\n", getinput7_.nbp94);
1150  printf("-E- %s line %d : See stderr output for details.\n",
1151  __FILE__, __LINE__);
1152  exit(FATAL_ERROR);
1153  }
1154  if (getinput7_.nb3 < 1 || getinput7_.nb3 > 50) {
1155  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1156  "the .94-um region:%d\nValid values are 1-50\n", getinput7_.nb3);
1157  printf("-E- %s line %d : See stderr output for details.\n",
1158  __FILE__, __LINE__);
1159  exit(FATAL_ERROR);
1160  }
1161  if (getinput7_.nb4 < 1 || getinput7_.nb4 > 50) {
1162  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1163  "the .94-um region:%d\nValid values are 1-50\n", getinput7_.nb4);
1164  printf("-E- %s line %d : See stderr output for details.\n",
1165  __FILE__, __LINE__);
1166  exit(FATAL_ERROR);
1167  }
1168  if (getinput7_.nb1p14 < 1 || getinput7_.nb1p14 > 110) {
1169  fprintf(stderr, "Invalid number of channels for first wavelength position in " \
1170  "the .94-um region:%d\nValid values are 1-90\n", getinput7_.nbp94);
1171  printf("-E- %s line %d : See stderr output for details.\n",
1172  __FILE__, __LINE__);
1173  exit(FATAL_ERROR);
1174  }
1175 
1176  //INIT
1177  int32_t *h2o, *co2, *o3, *n2o, *co, *ch4, *o2, *no2;
1178  h2o = (int32_t *) calloc(1, sizeof (int32_t));
1179  co2 = (int32_t *) calloc(1, sizeof (int32_t));
1180  o3 = (int32_t *) calloc(1, sizeof (int32_t));
1181  n2o = (int32_t *) calloc(1, sizeof (int32_t));
1182  co = (int32_t *) calloc(1, sizeof (int32_t));
1183  ch4 = (int32_t *) calloc(1, sizeof (int32_t));
1184  o2 = (int32_t *) calloc(1, sizeof (int32_t));
1185  no2 = (int32_t *) calloc(1, sizeof (int32_t));
1186 
1187  *h2o = 1;
1188 
1189  getinput1_.h2o = 1;
1190  getinput1_.co2 = 0;
1191  getinput1_.o3 = 0;
1192  getinput1_.n2o = 0;
1193  getinput1_.co = 0;
1194  getinput1_.ch4 = 0;
1195  getinput1_.o2 = 0;
1196  getinput1_.no2 = 0;
1197 
1198  // nwave = rdatreminfo(sensorID, 0, "h2o", (void **) &h2o);
1199  nwave = rdatreminfo(sensorID, 0, "co2", (void **) &co2);
1200  nwave = rdatreminfo(sensorID, 0, "o3", (void **) &o3);
1201  nwave = rdatreminfo(sensorID, 0, "n2o", (void **) &n2o);
1202  nwave = rdatreminfo(sensorID, 0, "co", (void **) &co);
1203  nwave = rdatreminfo(sensorID, 0, "ch4", (void **) &ch4);
1204  nwave = rdatreminfo(sensorID, 0, "o2", (void **) &o2);
1205  nwave = rdatreminfo(sensorID, 0, "no2", (void **) &no2);
1206 
1207 
1208  getinput1_.co2 = *co2;
1209  getinput1_.o3 = *o3;
1210  getinput1_.n2o = *n2o;
1211  getinput1_.co = *co;
1212  getinput1_.ch4 = *ch4;
1213  getinput1_.o2 = *o2;
1214  getinput1_.no2 = *no2;
1215 
1216  // The typical ozone amount is: 0.28-0.55 (atm-cm). The built-in NO2
1217  // column amount is 5.0E+15 molecules/cm^2.
1218  if (atrem_opt > 0) {
1219  getinput1_.co2 = (atrem_opt & ATREM_CO2) > 0;
1220  getinput1_.o3 = (atrem_opt & ATREM_O3) > 0;
1221  getinput1_.n2o = (atrem_opt & ATREM_N2O) > 0;
1222  getinput1_.co = (atrem_opt & ATREM_CO) > 0;
1223  getinput1_.ch4 = (atrem_opt & ATREM_CH4) > 0;
1224  getinput1_.o2 = (atrem_opt & ATREM_O2) > 0;
1225  getinput1_.no2 = (atrem_opt & ATREM_NO2) > 0;
1226 
1227  }
1228 
1229  printf("ATREM Gas Options:H2O:1 CO2:%d O3:%d N2O:%d CO:%d CH4:%d O2:%d NO2:%d\n",
1230  getinput1_.co2, getinput1_.o3, getinput1_.n2o, getinput1_.co, getinput1_.ch4, getinput1_.o2, getinput1_.no2);
1231 
1232  // Now check to make sure the same gas option isn't selected from the l2gen gas option.
1233 
1234  flag_gas = 0;
1235  if (gas_opt & H2O_BIT) {
1236  printf("ATREM: cannot be used with gas_opt bit mask=%d (H2O)\n", H2O_BIT);
1237  flag_gas = 1;
1238  }
1239  if (getinput1_.no2 == 1 && (gas_opt & NO2_BIT)) {
1240  printf("ATREM: cannot be used with gas_opt bit mask=%d (NO2)\n", NO2_BIT);
1241  flag_gas = 1;
1242 
1243  }
1244  if (getinput1_.co2 == 1 && (gas_opt & CO2_BIT)) {
1245  printf("ATREM: cannot be used with gas_opt bit mask=%d (CO2)\n", CO2_BIT);
1246  flag_gas = 1;
1247  }
1248  if (getinput1_.o3 == 1 && (gas_opt & O3_BIT)) {
1249  printf("ATREM: cannot be used with gas_opt bit mask=%d (O3)\n", O3_BIT);
1250  flag_gas = 1;
1251  }
1252 
1253  if (flag_gas) {
1254  printf("Error: Conflict using ATREM (gas_opt=16 bitmask) with atrem_opt=%d and gas_opt=%d. " \
1255  "\nPlease resolve. Refer to command line options for atrem_opt and gas_opt.\n", atrem_opt, gas_opt);
1256  exit(1);
1257  }
1258 
1259  float *vrto3, *sno2;
1260  vrto3 = (float *) calloc(1, sizeof (float));
1261  sno2 = (float *) calloc(1, sizeof (float));
1262 
1263  getinput3_.vrto3 = 0.34; //total column ozone amount (atm-cm)
1264  getinput3_.sno2 = 1.0; //NO2 scaling factor (to 5.E+15 molecules/cm^2)
1265 
1266  nwave = rdatreminfo(sensorID, 0, "vrto3", (void **) &vrto3);
1267  nwave = rdatreminfo(sensorID, 0, "sno2", (void **) &sno2);
1268 
1269  getinput3_.vrto3 = *vrto3; //total column ozone amount (atm-cm)
1270  getinput3_.sno2 = *sno2; //NO2 scaling factor (to 5.E+15 molecules/cm^2)
1271 
1272  //model_adj_(); //FORTRAN
1273  model_adjust();
1274 
1275  P->nb1 = getinput7_.nb1;
1276  P->nb2 = getinput7_.nb2;
1277  P->nb3 = getinput7_.nb3;
1278  P->nb4 = getinput7_.nb4;
1279  P->nbp94 = getinput7_.nbp94;
1280  P->nb1p14 = getinput7_.nb1p14;
1281  P->nobs = getinput5_.nobs;
1282  P->delta = getinput5_.dlt;
1283  P->delta2 = getinput5_.dlt2;
1284 
1285  return nwave;
1286 }
1287 
1288 int get_angle_limits(float **anglelimit, float **insenz, float **insolz, int *n_senz, int *n_solz) {
1289 
1290  char filename[FILENAME_MAX];
1291  char *infile = "atrem_angle_limit.nc";
1292  char *filedir;
1293 
1294  char name[H4_MAX_NC_NAME];
1295  char sdsname[H4_MAX_NC_NAME];
1296  int ncid, grpid, ndims, nvars, ngatts, unlimdimid;
1297  int32 sd_id;
1298  int32 sds_id;
1299  int32 rank;
1300  int32 sds_index;
1301  int32 nt;
1302  int32 dims[H4_MAX_VAR_DIMS];
1303  int32 nattrs;
1304  int status;
1305  nc_type rh_type; /* variable type */
1306  int dimids[H4_MAX_VAR_DIMS]; /* dimension IDs */
1307  int natts; /* number of attributes */
1308  int nsz; /* number of dims */
1309  size_t length;
1310  int i, j;
1311 
1312  static float *senz, *solz;
1313  static float *angle_limit;
1314 
1315  if ((filedir = getenv("OCDATAROOT")) == NULL) {
1316  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
1317  return (-1);
1318  }
1319  strcpy(filename, filedir);
1320  strcat(filename, "/common/");
1321  strcat(filename, infile);
1322  strcat(filename, "\0");
1323 
1324  printf("ATREM Angle_Limit FILE=%s\n", filename);
1325 
1326  if (nc_open(filename, NC_NOWRITE, &ncid) == NC_NOERR) {
1327 
1328  strcpy(sdsname, "senz");
1329 
1330  status = nc_inq_varid(ncid, sdsname, &sds_id);
1331  if (status != NC_NOERR) {
1332  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1333  __FILE__, __LINE__, sdsname, infile);
1334  exit(1);
1335  }
1336 
1337  status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1338  &natts);
1339 
1340  if (nc_inq_dimlen(ncid, dimids[0], &length) != NC_NOERR) {
1341  nc_inq_dim(ncid, dimids[0], name, &length);
1342  fprintf(stderr,
1343  "-E- %s line %d: could not get size of dimension \"%s\" in netCDF File.\n",
1344  __FILE__, __LINE__, name);
1345  exit(1);
1346  }
1347 
1348  *n_senz = length;
1349 
1350  if ((senz = (float *) calloc(*n_senz, sizeof (float))) == NULL) {
1351  printf("-E- : Error allocating memory to senz\n");
1352  exit(FATAL_ERROR);
1353  }
1354 
1355  if (nc_get_var(ncid, sds_id, senz) != NC_NOERR) {
1356  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1357  __FILE__, __LINE__, sdsname, infile);
1358  exit(1);
1359  }
1360 
1361  strcpy(sdsname, "solz");
1362 
1363  status = nc_inq_varid(ncid, sdsname, &sds_id);
1364  if (status != NC_NOERR) {
1365  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1366  __FILE__, __LINE__, sdsname, infile);
1367  exit(1);
1368  }
1369 
1370  status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1371  &natts);
1372  if (status != NC_NOERR) {
1373  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1374  __FILE__, __LINE__, sdsname, infile);
1375  exit(1);
1376  }
1377 
1378  if (nc_inq_dimlen(ncid, dimids[0], &length) != NC_NOERR) {
1379  nc_inq_dim(ncid, dimids[0], name, &length);
1380  fprintf(stderr,
1381  "-E- %s line %d: could not get size of dimension \"%s\" in netCDF File.\n",
1382  __FILE__, __LINE__, name);
1383  exit(1);
1384  }
1385 
1386  *n_solz = length;
1387 
1388  if ((solz = (float *) calloc(*n_solz, sizeof (float))) == NULL) {
1389  printf("-E- : Error allocating memory to solz\n");
1390  exit(FATAL_ERROR);
1391  }
1392 
1393  if (nc_get_var(ncid, sds_id, solz) != NC_NOERR) {
1394  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1395  __FILE__, __LINE__, sdsname, infile);
1396  exit(1);
1397  }
1398 
1399  strcpy(sdsname, "angle_limit");
1400 
1401  status = nc_inq_varid(ncid, sdsname, &sds_id);
1402  if (status != NC_NOERR) {
1403  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1404  __FILE__, __LINE__, sdsname, infile);
1405  exit(1);
1406  }
1407 
1408  status = nc_inq_var(ncid, sds_id, 0, &rh_type, &ndims, dimids,
1409  &natts);
1410  if (status != NC_NOERR) {
1411  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1412  __FILE__, __LINE__, sdsname, infile);
1413  exit(1);
1414  }
1415  if (ndims != 2) {
1416  fprintf(stderr, "-E- %s line %d: Wrong number of dimensions for %s. Need 2 got %d.\n",
1417  __FILE__, __LINE__, sdsname, ndims);
1418  exit(1);
1419 
1420  }
1421  // printf("ANGLE_LIMIT: %s n_senz=%d n_solz=%d\n",infile,*n_senz,*n_solz);
1422 
1423  if ((angle_limit = (float *) calloc((*n_senz) * (*n_solz), sizeof (float))) == NULL) {
1424  printf("-E- : Error allocating memory to angle_limit\n");
1425  exit(FATAL_ERROR);
1426  }
1427 
1428  // for (i=0; i< *n_senz;i++) {
1429  // if ( (anglelimit[i] = (float *)calloc((*n_solz) ,sizeof(float))) == NULL) {
1430  // printf("-E- : Error allocating memory to tindx\n");
1431  // exit(FATAL_ERROR);
1432  // }
1433  // }
1434 
1435  if (nc_get_var(ncid, sds_id, angle_limit) != NC_NOERR) {
1436  fprintf(stderr, "-E- %s line %d: Error reading %s from %s.\n",
1437  __FILE__, __LINE__, sdsname, infile);
1438  exit(1);
1439  }
1440 
1441  // for (j=0;j<*n_senz;j++)
1442  // for (i=0;i<*n_solz;i++) {
1443  // //anglelimit[j][i] = *(angle_limit+j*(*n_solz)+i);
1444  // printf("RJH: angle_limt: %f %f %f\n",solz[i],senz[j],*(angle_limit+j*(*n_solz)+i));
1445  //
1446  // }
1447 
1448  *insenz = (float *) senz;
1449  *insolz = (float *) solz;
1450  *insolz = (float *) solz;
1451  *anglelimit = (float *) angle_limit;
1452 
1453  } else {
1454  fprintf(stderr, "-E- %s line %d: Error opening infile = %s.\n",
1455  __FILE__, __LINE__, infile);
1456  return (1);
1457  }
1458 
1459 
1460  return (0);
1461 
1462 }
1463 
1464 float get_current_angle_limit(float insenz, float insolz, int *ii, int *jj, float **anglelimit, float *senz, float *solz, int n_senz, int n_solz) {
1465  float anglim;
1466  int i, j;
1467 
1468  i = *ii;
1469  j = *jj;
1470 
1471  if (i < 0 || i >= n_senz) i = 0;
1472  if (j < 0 || j >= n_solz) j = 0;
1473 
1474  if (insenz > senz[i]) {
1475  while (i < n_senz && insenz > senz[i])
1476  i++;
1477  if (i >= n_senz) i = n_senz - 1;
1478  } else {
1479  while (i >= 0 && insenz < senz[i])
1480  i--;
1481  if (i < 0) i = 0;
1482  }
1483 
1484  if (insolz > solz[j]) {
1485  while (j < n_solz && insolz > solz[j])
1486  j++;
1487  if (j >= n_solz) j = n_solz - 1;
1488  } else {
1489  while (j >= 0 && insolz < solz[j])
1490  j--;
1491  if (j < 0) j = 0;
1492  }
1493 
1494  *ii = i;
1495  *jj = j;
1496 
1497  return (anglelimit[i][j]);
1498 }
1499 
1500 /********************************************************************************
1501 !* *
1502 !* Name: FINDMATCH *
1503 !* Purpose: finds the closest match for ELEM in LIST *
1504 !* Parameters: LIST - array of values to match ELEM to. Elements is array *
1505 !* should increase in value. *
1506 !* Algorithm: linearly compare ELEM to each element. When ELEM is smaller *
1507 !* than the LIST(I), then it is assumed to be closest to LIST(I-1) *
1508 !* or LIST(I). The one that has the smallest absolute difference *
1509 !* to ELEM is returned as the closest match. *
1510 !* Globals used: none *
1511 !* Global output: none *
1512 !* Return Codes: the closest matching element index *
1513 !* Special Considerations: none *
1514 !* *
1515 !********************************************************************************/
1516 
1517 int32_t findMatch(float *list, int32_t nobs, float elem) {
1518  int i;
1519  float diff1, diff2;
1520 
1521  for (i = 0; i < nobs; i++)
1522  if (list[i] > elem) break;
1523 
1524  diff1 = fabs(list[i - 1] - elem);
1525  diff2 = fabs(list[i] - elem);
1526 
1527  if (diff1 < diff2)
1528  return (i - 1);
1529  else
1530  return (i);
1531 
1532 }
1533 
1534 /*
1535 !********************************************************************************
1536 !* *
1537 !* Name: channelRatio *
1538 !* Purpose: Calculate 3-channel ratios. *
1539 !* Parameters: none *
1540 !* Algorithm: The 0.94-um water vapor absorption channel is ratioed against *
1541 !* the linear combination of two window channels near 0.86 and *
1542 !* 1.03 um to obtain one channel ratio for the 0.94-um band. *
1543 !* Similar calculation is done for the 1.14-um water vapor band. *
1544 !* Globals used: NB1,NB2,NBP94,NB3,NB4,NB1P14 - number of points used in *
1545 !* channel ratios for both the .94- and 1.14-um regions*
1546 !* IST1,IED1,IST2,IED2,ISTP94,IEDP94 - 3-channel ratioing *
1547 !* parameters for the 0.94-um water vapor band *
1548 !* IST3,IED3,IST4,IED4,IST1P14,IED1P14 - 3-channel ratioing *
1549 !* parameters for the 1.14-um water vapor band. *
1550 !* WT1,WT2,WT3,WT4,JA - Relative weights for the four window *
1551 !* channels used in channel-ratioing calculations. JA *
1552 !* is an output parameter from a table searching *
1553 !* routine. *
1554 !* TRNCAL - Atmospheric transmittance spectra. *
1555 !* Global output:R094,R114 - 3-channel ratio values for the 0.94- and 1.14-um *
1556 !* water vapor bands. *
1557 !* Return Codes: none *
1558 !* Special Considerations: none *
1559 !* *
1560 !********************************************************************************
1561  */
1563 
1564  float const1[NH2OMAX], const2[NH2OMAX], const3[NH2OMAX], const4[NH2OMAX], const5[NH2OMAX], const6[NH2OMAX];
1565  int32_t nb1 = getinput7_.nb1, nb2 = getinput7_.nb2, nbp94 = getinput7_.nbp94, \
1566  nb3 = getinput7_.nb3, nb4 = getinput7_.nb4, nb1p14 = getinput7_.nb1p14;
1567  int32_t ist1 = init_speccal6_.ist1, ied1 = init_speccal6_.ied1, ist2 = init_speccal6_.ist2, \
1568  ied2 = init_speccal6_.ied2, istp94 = init_speccal6_.istp94, iedp94 = init_speccal6_.iedp94;
1569  int32_t ist3 = init_speccal7_.ist3, ied3 = init_speccal7_.ied3, ist4 = init_speccal7_.ist4, \
1570  ied4 = init_speccal7_.ied4, ist1p14 = init_speccal7_.ist1p14, ied1p14 = init_speccal7_.ied1p14;
1571  float wt1 = init_speccal8_.wt1, wt2 = init_speccal8_.wt2, wt3 = init_speccal8_.wt3, wt4 = init_speccal8_.wt4;
1572 
1573  int i, j;
1574 
1575  // Calculate average of spectra over window and water vapor absorption regions.
1576 
1577  for (j = 0; j < NH2OMAX; j++) {
1578  const1[j] = 0.0;
1579  const2[j] = 0.0;
1580  const3[j] = 0.0;
1581  const4[j] = 0.0;
1582  const5[j] = 0.0;
1583  const6[j] = 0.0;
1584 
1585  for (i = ist1 - 1; i < ied1; i++)
1586  const1[j] = const1[j] + tran_table1_.trntbl[j][i];
1587 
1588  const1[j] /= nb1;
1589 
1590  for (i = ist2 - 1; i < ied2; i++)
1591  const2[j] = const2[j] + tran_table1_.trntbl[j][i];
1592  const2[j] /= nb2;
1593 
1594  for (i = istp94 - 1; i < iedp94; i++)
1595  const3[j] = const3[j] + tran_table1_.trntbl[j][i];
1596  const3[j] /= nbp94;
1597 
1598  tran_table1_.r0p94[j] = const3[j] / (wt1 * const1[j] + wt2 * const2[j]);
1599 
1600  for (i = ist3 - 1; i < ied3; i++)
1601  const4[j] = const4[j] + tran_table1_.trntbl[j][i];
1602  const4[j] /= nb3;
1603 
1604  for (i = ist4 - 1; i < ied4; i++)
1605  const5[j] = const5[j] + tran_table1_.trntbl[j][i];
1606  const5[j] /= nb4;
1607 
1608  for (i = ist1p14 - 1; i < ied1p14; i++)
1609  const6[j] = const6[j] + tran_table1_.trntbl[j][i];
1610  const6[j] /= nb1p14;
1611 
1612  tran_table1_.r1p14[j] = const6[j] / (wt3 * const4[j] + wt4 * const5[j]);
1613  }
1614 
1615 
1616 }
1617 
1618 void kdistgasabs(float *kcdf, float *abscf, float*waveno, float *wavobs, int32_t nphi, int32_t n_layers, int32_t nbands) {
1619  //
1620  // R. Healy 3/2016 - converted from fortran kdist_gas_obs in atrem code which is based on Amir Ibrahim's
1621  // Matlab code
1622  // Construct k coefficients from gas transmission coefficients (from Amir Ibrahim's Matlab Code)
1623  //
1624  // abscf[nlayers][np_hi] (IN) :: the absorption coefficients
1625  // waveno[np_hi] (IN) :: wave number of the spectrum
1626  // wavobs[nwave] (IN) :: wavelengths of the instrument detector
1627  // np_hi (IN) :: Number of high resolution spectral points,
1628  // covering 3000 cm-1 to 18,000 cm-1 at
1629  // point spacing of 0.05 cm-1
1630  // nlayers (IN) :: number of atmospheric layers
1631  // nwave (IN) :: number of wavelengths of the instrument
1632  // kcdf[7][nwave][nlayers] (OUT):: K-Coefficients
1633 
1634  float **alayers, g7[7] = {0, 0.379, 0.6, 0.81, 0.9548, 0.9933, 1};
1635  float *diflam, *UV_lam, *IR_lam, *UV_dlam, *lam, *wn; //,*ir_dlam
1636  float *dwave, *dwn, *g_i, *k_i, *g, *kg, *logk, *kint[7], **k7[7], *kk;
1637  int32_t **wavel_window, *binnum;
1638  float dlam, wmin, wmax, swav;
1639  float Q = {2.15199993E+25}; // Q=# of molecules above the surface at one atmosphere (molecules/cm**2)
1640  float AvN = {6.0225E+23};
1641  int kwavdn, kwavup, nbins;
1642  int32_t nsamp;
1643  int k, ks, i, j, n, ndxwuv, ndxwir, ndxtot, iw;
1644 
1645  alayers = (float **) malloc(n_layers * sizeof (float *));
1646  for (i = 0; i < n_layers; i++) {
1647  if ((alayers[i] = (float *) malloc(nphi * sizeof (float))) == NULL) {
1648  printf("%s, %d - E - unable to allocate memory in kdistgasabs\n",
1649  __FILE__, __LINE__);
1650  exit(EXIT_FAILURE);
1651  }
1652  for (n = 0; n < nphi; n++)
1653  alayers[i][n] = *(abscf + i * n_layers + n) * Q * 28.966 / AvN / 1.0e-6;
1654  //alayers[i][n] = abscf[i][n]*Q*28.966/ AvN / 1.0e-6;
1655  }
1656 
1657  diflam = (float *) malloc(nbands * sizeof (float));
1658 
1659  dlam = 9999.;
1660  wmin = 9999;
1661  wmax = -9999;
1662  for (i = 0; i < nbands - 1; i++) {
1663  diflam[i] = wavobs[i + 1] - wavobs[i];
1664  if (dlam > diflam[i]) dlam = diflam[i];
1665  if (wmin > wavobs[i]) wmin = wavobs[i];
1666  if (wmax < wavobs[i]) wmax = wavobs[i];
1667  }
1668 
1669  diflam[nbands - 1] = diflam[nbands - 2];
1670 
1671  if (wmin > wavobs[nbands - 1]) wmin = wavobs[nbands - 1];
1672  if (wmax < wavobs[nbands - 1]) wmax = wavobs[nbands - 1];
1673 
1674  ndxwuv = (wmin - 0.0001 - 0.3) / dlam + 1;
1675  ndxwir = (3.1 - (wmax + 0.0001)) / diflam[nbands - 1] + 1;
1676  ndxtot = nbands + ndxwuv + ndxwir;
1677 
1678  UV_lam = (float *) malloc(ndxwuv * sizeof (float));
1679  IR_lam = (float *) malloc(ndxwir * sizeof (float));
1680  UV_dlam = (float *) malloc(ndxwuv * sizeof (float));
1681  lam = (float *) malloc(ndxtot * sizeof (float));
1682  dwave = (float *) malloc(ndxtot * sizeof (float));
1683  dwn = (float *) malloc(ndxtot * sizeof (float));
1684  wn = (float *) malloc(ndxtot * sizeof (float));
1685  wavel_window = (int **) malloc(2 * sizeof (int *));
1686  binnum = (int32_t *) malloc(n_layers * sizeof (int32_t));
1687 
1688  for (i = 0; i < 2; i++)
1689  wavel_window[i] = (int *) malloc(ndxtot * sizeof (int));
1690 
1691  k = ndxtot - 1;
1692  swav = 0.3;
1693 
1694  for (i = 0; i < ndxwuv; i++) {
1695  UV_lam[i] = swav;
1696  UV_dlam[i] = diflam[0];
1697  swav = swav + dlam;
1698  lam[k] = UV_lam[i];
1699  dwn[k] = 10000. * dlam / pow(lam[k], 2);
1700  wn[k] = 10000. / lam[k];
1701  k--;
1702  }
1703  swav = wmin - 1;
1704  for (i = 0; i < nbands; i++) {
1705  lam[k] = swav;
1706  dwn[k] = 10000. * diflam[i] / pow(lam[k], 2);
1707  wn[k] = 10000. / lam[k];
1708  swav = swav + diflam[i];
1709  k--;
1710  }
1711 
1712  swav = wmax + 0.0001;
1713 
1714  for (i = 0; i < ndxwir; i++) {
1715  IR_lam[i] = swav;
1716  //ir_dlam[i] = diflam[nbands];
1717  swav = swav + diflam[nbands - 1];
1718  lam[k] = IR_lam[i];
1719  dwn[k] = 10000. * diflam[nbands - 1] / pow(lam[k], 2);
1720  wn[k] = 10000. / lam[k];
1721  k--;
1722  }
1723 
1724  for (i = 0; i < 7; i++) {
1725  kint[i] = (float *) malloc(ndxtot * sizeof (float));
1726  k7[i] = (float **) malloc(ndxtot * sizeof (float *));
1727  for (k = 0; k < ndxtot; k++)
1728  k7[i][k] = (float *) malloc(n_layers * sizeof (float));
1729  }
1730 
1731  iw = nbands - 1; // index for wavelngths for output array kcdf
1732 
1733  for (i = ndxwir; i < ndxtot - ndxwuv; i++) {
1734  kwavdn = -999;
1735  kwavup = -999;
1736 
1737  for (k = 0; k < nphi; k++) {
1738  if (kwavdn < 0 && waveno[k]> (wn[i] - dwn[i] / 2.0)) kwavdn = k;
1739  if (kwavup < 0 && waveno[k]> (wn[i] + dwn[i] / 2.0)) kwavup = k;
1740  }
1741 
1742  wavel_window[0][i] = kwavdn;
1743  wavel_window[1][i] = kwavup;
1744 
1745  if (kwavup < 0 || kwavdn < 0)
1746  nsamp = 1;
1747  else
1748  nsamp = kwavup - kwavdn + 1;
1749 
1750  nbins = nsamp;
1751  g_i = (float *) malloc((nbins + 1) * sizeof (float));
1752  k_i = (float *) malloc((nbins + 1) * sizeof (float));
1753  kk = (float *) malloc((nsamp + 1) * sizeof (float));
1754  logk = (float *) malloc((nbins + 1) * sizeof (float));
1755 
1756  for (k = 0; k < n_layers; k++) {
1757  if (kwavdn < 0 || kwavup < 0)
1758  for (j = 0; j < nsamp + 1; j++)
1759  kk[j] = 0;
1760  else
1761  n = kwavdn - 1;
1762  for (j = 0; j < nsamp && n < nphi; j++) {
1763  kk[j] = alayers[k][n];
1764  n++;
1765  }
1766  binnum[k] = nbins;
1767  ecdf_(k_i, g_i, &binnum[k], kk, &nsamp);
1768 
1769  for (j = 0; j < nbins + 1; j++)
1770  logk[j] = log10(k_i[j]);
1771 
1772  for (j = 0; j < 7; j++) {
1773 
1774  kint[j][i] = linterp(g_i, logk, binnum[k], g7[j]);
1775  k7[j][i][k] = pow(10, kint[j][i]);
1776 
1777  if (i >= ndxwir && i < ndxtot - ndxwuv) {
1778  if (isnan(k7[j][i][k])) k7[j][i][k] = 0;
1779 
1780  //kcdf[j][iw][k] = k7[j][i][k];
1781  // *(kcdf+j*nbands*7+iw*n_layers+k) = k7[j][i][k];
1782  *(kcdf + j * nbands * n_layers + iw * n_layers + k) = k7[j][i][k];
1783  }
1784  }
1785 
1786  }
1787 
1788  free(logk);
1789  free(g_i);
1790  free(k_i);
1791  free(kk);
1792 
1793  if (i >= ndxwir && i < ndxtot - ndxwuv) iw--;
1794 
1795  }
1796 
1797  free(UV_lam);
1798  free(IR_lam);
1799  free(UV_dlam);
1800  //free ( ir_dlam );
1801  free(lam);
1802  free(dwave);
1803  free(dwn);
1804  free(wn);
1805  free(wavel_window[0]);
1806  free(wavel_window[1]);
1807  for (i = 0; i < 7; i++) {
1808  for (k = 0; k < ndxtot; k++)
1809  free(k7[i][k]);
1810  free(k7[i]);
1811  free(kint[i]);
1812  }
1813  for (i = 0; i < n_layers; i++)
1814  free(alayers[i]);
1815  free(alayers);
1816 }
1817 
1818 /*
1819  * Converted from Fortran by R. Healy (SAIC) 3/2016
1820 !********************************************************************************
1821 !* *
1822 !* Name: model_adjust *
1823 !* Purpose: resets the bottom boundary of the input model if the surface *
1824 !* elevation is greater than 0, and calculate the column water vapor *
1825 !* amount in the selected model. *
1826 !* Parameters: none *
1827 !* Algorithm: If the surface elevation > 0, the bottom layer temperature and *
1828 !* water vapor volume mixing ratio are obtained through linear *
1829 !* interpolation, while the bottom layer pressure is obtained *
1830 !* through exponential interpolation. *
1831 !* Globals used: H, T, P, VMR, NB, NL, HSURF - these values are adjusted if *
1832 !* HSURF > 0 *
1833 !* Global output: CLMVAP - Column water vapor amount in unit of cm. *
1834 !* Q - Number of molecules above the surface at one *
1835 !* atmosphere in units of molecules/cm**2 *
1836 !* Return Codes: none *
1837 !* Special Considerations: none *
1838 !* *
1839 !********************************************************************************
1840  */
1841 
1843 
1844  float *h = getinput3_.h, *t = getinput3_.t, *p = getinput3_.p, *vmr = getinput3_.vmr;
1845  float v = getinput3_.v, \
1846  taer55 = getinput3_.taer55, vrto3 = getinput3_.vrto3, sno2 = getinput3_.sno2;
1847  int32_t nl = getinput3_.nl, model = getinput3_.model, iaer = getinput3_.iaer, nb = getinput3_.nb,\
1848  nobs = getinput5_.nobs, fullcalc = getinput5_.full_calc;
1849  float hsurf = getinput5_.hsurf, dlt = getinput5_.dlt, dlt2 = getinput5_.dlt2;
1850  float xpss = getinput14_.xpss, xppp = getinput14_.xppp;
1851 
1852  static float hp[MODELMAX], tp[MODELMAX], pp[MODELMAX], vmrp[MODELMAX];
1853 
1854  float radius_earth = 6380.0, dhk, dhs, tsurf, vmrs, psurf, amtvrt, damtvrt, hplane;
1855  float q, tplane, pplane, vmrsp, dhss, dhkk, amtvrtp, damtvrtp;
1856  int32_t kk, i, k_surf;
1857 
1858  q = 2.152e25;
1859  model_adj1_.q = q;
1860 
1861  //Determine index of H() such that H(index) < HSURF < H(index+1)
1862 
1863  for (i = 0; i < nb; i++)
1864  if (hsurf == h[i]) hsurf = h[i] + 0.0001;
1865 
1866  // Determine index of H() such that H(index) < HSURF < H(index+1)
1867  locate_pos_(h, &nb, &hsurf, &k_surf);
1868 
1869  // K_SURF is an index relative to the original model atmosphere (0 - 100 km)
1870  if (k_surf < 0) {
1871  fprintf(stderr, "***WARNING: Surface elevation smaller then lowest boundary of the model atmosphere.\n");
1872  k_surf = 0;
1873  } else {
1874  dhk = h[k_surf + 1] - h[k_surf];
1875  dhs = hsurf - h[k_surf];
1876  //linear interpolation for surface temperature (TSURF) and VMR ( VMRS)
1877  tsurf = t[k_surf]+(dhs / dhk)*(t[k_surf + 1] - t[k_surf]);
1878  vmrs = vmr[k_surf]+(dhs / dhk)*(vmr[k_surf + 1]);
1879  //exponential interpolation for surface pressure (PSURF)
1880  psurf = p[k_surf] * exp(-log(p[k_surf]));
1881  h[0] = hsurf;
1882  p[0] = psurf;
1883  t[0] = tsurf;
1884  vmr[0] = vmrs;
1885 
1886  nb -= k_surf;
1887  nl = nb - 1;
1888 
1889  for (i = 1; i < nb; i++) {
1890  h[i] = h[i + k_surf];
1891  p[i] = p[i + k_surf];
1892  t[i] = t[i + k_surf];
1893  vmr[i] = vmr[i + k_surf];
1894  }
1895  //Zero out pressures and VMRS of top atmospheric layers.
1896  for (i = nb; i < MODELMAX; i++) {
1897  h[i] = 1000;
1898  p[i] = 0.0;
1899  t[i] = 300.;
1900  vmr[i] = 0.0;
1901  }
1902  }
1903  amtvrt = 0.0;
1904 
1905  for (i = 0; i < nl; i++) {
1906  damtvrt = (q) *(p[i] - p[i + 1])*(vmr[i] + vmr[i + 1]) / 2.0;
1907  amtvrt += damtvrt;
1908  }
1909 
1910  model_adj1_.clmvap = amtvrt / 3.34e22;
1911 
1912  fprintf(stderr, "--RJH: Model_adjust: Column vapor amount in model atmosphere from ground\n");
1913  fprintf(stderr, "--RJH: Model_adjust: to space = %f cm\n", model_adj1_.clmvap);
1914  /*
1915  Setting the upward atmospheric path's T, P, and VMR profiles:
1916 
1917  1st duplicate the entire atmospheric profiles from the downward path
1918  to the upward path
1919 
1920  */
1921 
1922  for (i = 0; i < MODELMAX; i++) {
1923  hp[i] = h[i];
1924  tp[i] = t[i];
1925  pp[i] = p[i];
1926  vmrp[i] = vmr[i];
1927  }
1928  // Set the highest plane altitude to the upper bound of model atmosphere
1929  hplane = xppp;
1930 
1931  if (hplane >= 100.0) hplane = 100.0 - 0.0001;
1932  //Do special processing if the plane height (HPLANE) is greater than HP(1)
1933  if (hplane > hp[0]) {
1934  // Reset Plane altitude HPLANE (= XPPP) to a larger value if
1935  // HPLANE.EQ.HP(I) to avoid possible problems in table
1936  // searching using LOCATE
1937  for (i = 0; i < MODELMAX; i++)
1938  if (hplane == hp[i]) hplane = hp[i] - 0.0001;
1939  //Determine index of HP() such that HP(index) < HPLANE < H(index+1)
1940  locate_pos_(hp, &nb, &hplane, &kk);
1941 
1942  if (kk < 0)
1943  printf("WARNING: Plane altitude less then lowest boundary of the model atmosphere.\n");
1944  else {
1945  dhkk = hp[kk + 1] - hp[kk];
1946  dhss = hplane - hp[kk];
1947  //linear interpolation for plane temperature (TPLANE) and VMR ( VMRSP)
1948  tplane = tp[kk] + (dhss / dhkk)*(tp[kk + 1] - tp[kk]);
1949  vmrsp = vmrp[kk] + (dhss / dhkk)*(vmrp[kk + 1] - vmrp[kk]);
1950  //exponential interpolation for plane pressure (PPLANE)
1951  pplane = pp[kk] * exp(-log(pp[kk] / pp[kk + 1]) * dhss / dhkk);
1952  hp[kk + 1] = hplane;
1953  pp[kk + 1] = pplane;
1954  tp[kk + 1] = tplane;
1955  vmrp[kk + 1] = vmrsp;
1956  //Zero out pressures and VMRP of top atmospheric layers
1957  if (kk < MODELMAX - 2) {
1958  for (i = kk + 2; i < MODELMAX; i++) {
1959  hp[i] = 1000;
1960  pp[i] = 0.0;
1961  tp[i] = 300.;
1962  vmrp[i] = 0.0;
1963  }
1964  }
1965  }
1966  }
1967  amtvrtp = 0.0;
1968  for (i = 0; i < kk; i++) {
1969  damtvrtp = (q) *(pp[i] - pp[i + 1])*(vmrp[i] + vmrp[i + 1]) / 2.0;
1970  amtvrtp += damtvrtp;
1971  }
1972  model_adj3_.clmvapp = amtvrtp / 3.34e22;
1973  fprintf(stderr, "--RJH: Model_adjust: Column vapor amount below plane");
1974  fprintf(stderr, "--RJH: Model_adjust: = %f cm\n", model_adj3_.clmvapp);
1975 
1976  //Indices and parameters for the plane layer
1977  //model_adj3_.k_plane = kk;model_adj4_.k_surf = k_surf; // For final C version
1978  printf("RJH: MODEL_ADJUST - be sure to change next line to model_adj3_.k_plane = kk;model_adj4_.k_surf = k_surf once final conversion to C is complete\n ");
1979  model_adj3_.k_plane = kk + 1;
1980  model_adj4_.k_surf = k_surf + 1;
1981 
1982  model_adj3_.dvap_plane = q * (pp[kk] - pp[kk + 1]) * (vmrp[kk] + vmrp[kk + 1]) / 2.0 / 3.34e22;
1983  model_adj3_.dvap_layer = q * (p[kk] - p[kk + 1]) * (vmr[kk] + vmr[kk + 1]) / 2.0 / 3.34e22;
1984  model_adj3_.dp_plane = pp[kk] - pp[kk + 1];
1985  model_adj3_.dp_layer = p[kk] - p[kk + 1];
1986 
1987 }
1988 
1989 /*
1990  * ********************************************************************************
1991 !* *
1992 !* Name: LOCATE *
1993 !* Purpose: given an array XX of length N, and given a value X, returns a value*
1994 !* J such that X is between XX(J) and XX(J+1). XX must be monotonic, *
1995 !* Parameters: XX - monotonic array of values *
1996 !* N - number of elements in XX *
1997 !* X - value that will be matched to the XX array *
1998 !* J - index into the XX array where XX(J) <= X <= XX(J+1) *
1999 !* Algorithm: bisectional table searching, copied from Numerical Recipes. *
2000 !* Globals used: none *
2001 !* Global output: none *
2002 !* Return Codes: J=0 or J=N is returned to indicate that X is out of range *
2003 !* Special Considerations: none *
2004 !* *
2005 !********************************************************************************
2006  */
2007 void locate_pos_(float *xx, int32_t *n1, float *x1, int32_t *jj) {
2008  int32_t j, ju, jl, jm, n = *n1;
2009  float x = *x1;
2010 
2011  // fprintf(stderr,"locate_pos: n=%d x=%f\n",n,x);
2012  jl = -1;
2013  ju = n;
2014  while ((ju - jl) > 1) {
2015  jm = (ju + jl) / 2;
2016  // fprintf(stderr,"jm=%d\n",jm);
2017  if ((xx[n - 1] > xx[0]) && (x > xx[jm]))
2018  jl = jm;
2019  else
2020  ju = jm;
2021  }
2022  // fprintf(stderr,"jl=%d ju=%d\n",jl,ju);
2023  if (x == xx[0])
2024  j = -1;
2025  else if (x == xx[n - 1])
2026  j = n - 2;
2027  else
2028  j = jl;
2029 
2030  *jj = j;
2031  // fprintf(stderr,"Locate end: j=%d jl=%d ju=%d\n",*jj,jl,ju);
2032  // return j;
2033 }
2034 
2035 /* Converted from Fortran by R. Healy 3/2016
2036  *
2037 !********************************************************************************
2038 !* *
2039 !* Name: GEOMETRY *
2040 !* Purpose: Calculates the solar and the observational geometric factors. *
2041 !* Parameters: none *
2042 !* Algorithm: The solar geometry was obtained based on the latitude, longitude,*
2043 !* GMT time using programs written by W. Mankin at National Center *
2044 !* for Atmospheric Research in Boulder, Colorado. The *
2045 !* geometric factors for CO2, O3, N2O, CO, CH4, and O2 are based *
2046 !* only on the solar and observational angles. Sixty artificial *
2047 !* geometric factors for H2O are set up to produce a transmittance *
2048 !* table for different atmospheric water vapor amounts. *
2049 !* Globals used: VRTO3 - Column O3 amount in units of atm-cm *
2050 !* IMN,IDY,IYR,IH,IM,IS - time and date of data measurements *
2051 !* XLATD,XLATM,XLATS,LATHEM - Latitude of measured area *
2052 !* XLONGD,XLONGM,XLONGS,LNGHEM - Longitude of measured area *
2053 !* CLMVAP - Column water vapor in unit of cm in the model atmosphere *
2054 !* Global output: *
2055 !* SOLZNI,SOLAZ,OBSZNI,OBSPHI,IDAY - Solar zenith angle, solar azimuth *
2056 !* angle, observational zenith angle, observational azimuth angle, *
2057 !* and the day number in the year *
2058 !* GCO2,GO3,GN2O,GCO,GCH4,GO2,SSH2O,GGEOM,TOTLO3 - Geometric factors for *
2059 !* different gases, and total O3 amount in the sun-surface ray path. *
2060 !* The geometric factor is defined as: if the vertical column amount *
2061 !* of the gas is equal 1, then GGAS is equal to the total amount of *
2062 !* the gas in the combined Sun-surface-sensor ray path. *
2063 !* Return Codes: none *
2064 !* Special Considerations: none *
2065 !* *
2066 !********************************************************************************
2067  */
2068 void geometry() {
2069  float vap_slant[NH2OMAX];
2070  int md[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, leap_year;
2071  float ggeom;
2072  /*
2073  The VAPVRT array contains 60 column water vapor values used for generating
2074  a table of transmittance spectra with different amount of water vapor.
2075  The values in VAPVRT is designed so that there is approximately 2% change
2076  in the .94-um H2O channel ratio for column water vapor in the range .4-6 cm.
2077  */
2078  float vapvrt[NH2OMAX] = {.00, .02, .06, .11, .16, .21, .26, .31, .36, .40, \
2079  .43, .46, .50, .54, .58, .62, .66, .70, .75, .80, \
2080  .86, .92, .98, 1.06, 1.14, 1.22, 1.3, 1.4, 1.5, 1.6, \
2081  1.7, 1.8, 1.9, 2.05, 2.2, 2.35, 2.55, 2.75, 2.95, 3.2, \
2082  3.5, 3.8, 4.1, 4.4, 4.7, 5.0, 5.3, 5.6, 6.0, 6.4, \
2083  7.0, 7.7, 8.5, 9.4, 10.4, 11.6, 13.0, 15.0, 25.0, 50.};
2084  float hplane = getinput14_.xppp;
2085  float obszni = geometry_l2gen_.senzn_l2, obsphi = geometry_l2gen_.senaz_l2, solzni = geometry_l2gen_.solzn_l2;
2086  float clmvap = model_adj1_.clmvap, clmvapp = model_adj3_.clmvapp;
2087  float *ssh2o = geometry2_.ssh2o;
2088  float dvap_plane = model_adj3_.dvap_plane, dp_plane = model_adj3_.dp_plane, dvap_layer = model_adj3_.dvap_layer, dp_layer = model_adj3_.dp_layer;
2089  float mu, mu0;
2090  int i, j, k_plane = model_adj3_.k_plane, splitpaths = geometry_l2gen_.splitpaths;
2091  float vap_sol, vap_sen;
2092 
2093  /*
2094 
2095  VAP_SLANT is a new array for containing two-way total vapor amounts
2096  Here the number "2" can be changed to other numbers, e.g., 2.5,
2097  without any major effects in derived water vapor values from
2098  imaging spectrometer data.
2099 
2100  */
2101 
2102  for (i = 0; i < NH2OMAX; i++)
2103  vap_slant[i] = vapvrt[i] * (float) 2.0;
2104 
2105  obszni /= RAD_DEG;
2106  obsphi /= RAD_DEG;
2107  solzni /= RAD_DEG;
2108 
2109  mu0 = (float) 1. / cos(solzni);
2110  mu = (float) 1. / cos(obszni);
2111  ggeom = mu0 + mu;
2112 
2113  geometry5_.mu0 = mu0;
2114  geometry5_.mu = mu;
2115  geometry2_.ggeom = ggeom;
2116  geometry1_.obszni = obszni;
2117  geometry1_.obsphi = obsphi;
2118  geometry1_.solzni = solzni;
2119 
2120  printf("RJH:GGEOM =%f OBSZNI = %f OBSPHI = %f solzni=%f degrees :: MU0=%f, MU = %f\n", \
2121  ggeom, obszni, obsphi, solzni, mu0, mu);
2122  geometry2_.gco2 = ggeom;
2123 
2124  geometry2_.go3 = ggeom;
2125  if (hplane < 27.) geometry2_.go3 = ggeom - (float) 1. / cos(obszni);
2126 
2127  geometry2_.gn2o = ggeom;
2128  geometry2_.gco = ggeom;
2129  geometry2_.gch4 = ggeom;
2130  geometry2_.go2 = ggeom;
2131 
2132  geometry2_.totlo3 = geometry2_.go3 * getinput3_.vrto3;
2133 
2134  printf("RJH: TOTLO3 = %f %f\n", geometry2_.totlo3, getinput3_.vrto3);
2135 
2136  /*
2137  * Initialize newly created geometrical factors for each atmospheric
2138  layers (here G_VAP and G_OTHER are true geometrical factors that
2139  account for the actual Sun-surface-plane path lengths in the
2140  model atmosphere):
2141  *
2142  */
2143  printf("RJH: GEOMETRY - be sure to change line to k_plane NOT k_plane-1 once final conversion to C is complete\n ");
2144  //---For layers below the plane layer---
2145  //for (i=0;i<k_plane;i++) {
2146  for (i = 0; i < k_plane - 1; i++) {
2147  geometry3_.g_vap[i] = ggeom;
2148  geometry3_.g_other[i] = ggeom;
2149  }
2150 
2151  printf("RJH: GEOMETRY - be sure to change line to k_plane+1 NOT k_plane once final conversion to C is complete\n ");
2152  /*---For layers above the plane layer */
2153  // for (i=k_plane+1;i<MODELMAX;i++) {
2154  for (i = k_plane; i < MODELMAX; i++) {
2155  geometry3_.g_vap[i] = ggeom - (float) 1. / cos(obszni);
2156  geometry3_.g_other[i] = ggeom - (float) 1. / cos(obszni);
2157  }
2158  /* ---Special treatment for the plane layer to take account the
2159  "shorter" upward path length
2160  */
2161  printf("RJH: GEOMETRY - be sure to change line to k_plane NOT k_plane-1 once final conversion to C is complete\n ");
2162  /*
2163  geometry3_.g_vap[k_plane] = ggeom - 1./cos(obszni) \
2164  + dvap_plane/dvap_layer/cos(obszni);
2165  geometry3_.g_other[k_plane] = ggeom - 1./cos(obszni) \
2166  + dp_plane/dp_layer/cos(obszni);
2167  */
2168  geometry3_.g_vap[k_plane - 1] = ggeom - 1. / cos(obszni) \
2169  + dvap_plane / dvap_layer / cos(obszni);
2170  geometry3_.g_other[k_plane - 1] = ggeom - 1. / cos(obszni) \
2171  + dp_plane / dp_layer / cos(obszni);
2172  /*
2173  Calculate the water vapor SCALING factor relative to the total amount
2174  of water vapor in the model atmosphere in the L-shaped
2175  Sun-surface-plane ray path.
2176  */
2177  geometry4_.vap_slant_mdl = clmvap / cos(solzni) + clmvapp / cos(obszni);
2178  vap_sol = clmvapp*mu0;
2179  vap_sen = clmvapp*mu;
2180  printf("VAP_SLANT_MDL = %f cm\n", geometry4_.vap_slant_mdl);
2181 
2182  /*
2183  The "equivalent" geometrical factor corresponding to the total
2184  slant vapor amount of VAP_SLANT_MDL':
2185  */
2186 
2187  geometry3_.g_vap_equiv = geometry4_.vap_slant_mdl / clmvap;
2188 
2189  printf("G_VAP_EQUIV = %f clmvap=%f VAP_SOL=%f,VAP_SEN=%f \n", geometry3_.g_vap_equiv, clmvap, \
2190  vap_sol, vap_sen);
2191 
2192  for (i = 0; i < NH2OMAX; i++) {
2193  ssh2o[i] = vap_slant[i] / geometry4_.vap_slant_mdl;
2194  printf("SSH2O(%d)=%f splitpaths=%d\n", i, ssh2o[i], splitpaths);
2195  // if (geometry_l2gen_.water_vapor > 0) {
2196  if (splitpaths) {
2197  geometry5_.ssh2o_s[0][i] = vapvrt[i] / vap_sol;
2198  geometry5_.ssh2o_s[1][i] = vapvrt[i] / vap_sen;
2199  printf("SSH2O_S(1): %d %g %g | %g | %g \n", i, geometry5_.ssh2o_s[0][i], vapvrt[i], vap_sol, solzni * RAD_DEG);
2200  printf("SSH2O_S(2): %d %g %g | %g | %g \n", i, geometry5_.ssh2o_s[1][i], vapvrt[i], vap_sen, obszni * RAD_DEG);
2201  }
2202  // } else if (splitpaths != 0) {
2203  // printf("ATREM: Split paths is not working because WaterVapor is 0\n");
2204  // }
2205  }
2206  /*
2207  Calculate the number of days that have passed in this year. Take leap year
2208  into account.
2209  */
2210  geometry1_.day = md[getinput8_.imn] + getinput8_.idy;
2211  leap_year = getinput8_.iyr - (4 * (getinput8_.iyr / 4));
2212  if ((!leap_year) && (geometry1_.day > 59) && (getinput8_.imn != 2)) geometry1_.day++;
2213 
2214 }
2215 
2216 void get_abscf_data(int levels, int bands, int sds_id, char filename[FILENAME_MAX], float* abscf, char *varname) {
2217  size_t start[3], count[3];
2218  int retval;
2219  int xid;
2220 
2221  start[0] = 0;
2222  start[1] = 0;
2223  start[2] = 0;
2224  count[0] = levels;
2225  count[1] = bands;
2226  count[2] = 0;
2227  retval = nc_inq_varid(sds_id, varname, &xid);
2228  if (retval != NC_NOERR) {
2229  fprintf(stderr,
2230  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2231  __FILE__, __LINE__, filename, varname);
2232  exit(FATAL_ERROR);
2233  }
2234  retval = nc_get_vara_float(sds_id, xid, start, count, abscf);
2235  if (retval != NC_NOERR) {
2236  fprintf(stderr,
2237  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2238  __FILE__, __LINE__, filename, varname);
2239  exit(FATAL_ERROR);
2240  }
2241 
2242  return;
2243 }
2244 
2245 void apply_gas_trans(int32_t k_surf, int levels, int bands, float* abscf, float* dp, float* vmrm, float *tran_hi) {
2246  static float *sumcf;
2247  int32_t i, j;
2248  float Q = 2.152e25;
2249 
2250  if ((sumcf = (float *) calloc(bands, sizeof (float))) == NULL) {
2251  printf("-E- : Error allocating memory to sumcf\n");
2252  exit(FATAL_ERROR);
2253  }
2254 
2255  printf("RJH: INIT_SPECCAL - be sure to change below line to i=k_surf and i - k_surf (NOT i - k_surf + 1) once final conversion to C is complete\n ");
2256 
2257  for (i = 0; i < bands; i++)
2258  sumcf[i] = 0.;
2259 
2260  for (i = k_surf - 1; i < levels; i++)
2261  for (j = 0; j < bands; j++)
2262  sumcf[j] -= abscf[bands * i + j] * dp[i - k_surf + 1] * vmrm[i - k_surf + 1];
2263 
2264  for (i = 0; i < bands; i++)
2265  tran_hi[i] *= exp(sumcf[i] * Q * (float) 28.966 / (float) 6.0225E+23 / (float) 1.0E-06);
2266 
2267  free(sumcf);
2268 }
2269 
2270 /* Ported from Fortran code by R. Healy 3/17/2016
2271  * Comments from Fortran Code - unless noted otherwise
2272 !********************************************************************************
2273 !* *
2274 !* Name: INIT_SPECCAL *
2275 !* Purpose: initialize global data for spectrum calculations. *
2276 !* Parameters: none *
2277 !* Algorithm: initialize data. *
2278 !* Globals used: AH2O, APH2O, BH2O, BPH2O, SODLT, SOGAM, O3CF - Band model *
2279 !* parameters for spectral calculations. *
2280 !* WNDOW1, WNDOW2, WP94C, WNDOW3, WNDOW4, W1P14C - Center *
2281 !* positions of window and water vapor absorption *
2282 !* channels used in 3-channel ratio calculations. *
2283 !* NB1, NB2, NBP94, NB3, NB4, NB1P14 - Number of narrow channels *
2284 !* to form broader window and absorption channels. *
2285 !* Global output: *
2286 !* IH2OLQ,RLQAMT,NGASTT,NH2O,VSTART,VEND - Flag for including liquid *
2287 !* water, liquid water amount (cm), total number of gases *
2288 !* (typically 8), number of water vapor values, starting *
2289 !* and ending wavelengths in internal calculations. *
2290 !* NO3PT,NCV,NCVHAF,NCVTOT,VMIN,ISTART,IEND - Number of O3 abs. coef. *
2291 !* points, parameters for gaussian function and spectral *
2292 !* calculations. *
2293 !* ISTCAL,IEDCAL,DP,PM,TM,VMRM - Parameters for spectral calculations *
2294 !* IST1,IED1,IST2,IED2,ISTP94,IEDP94 - 3-channel ratioing parameters for *
2295 !* the 0.94-um water vapor band. *
2296 !* IST3,IED3,IST4,IED4,IST1P14,IED1P14 - 3-channel ratioing parameters for *
2297 !* the 1.14-um water vapor band. *
2298 !* WT1,WT2,WT3,WT4,JA - Relative weights for the four window channels *
2299 !* used in channel-ratioing calculations. JA is a *
2300 !* output parameter from a table searching routine. *
2301 !* NCV2,NCVHF2,NCVTT2,ISTRT2,IEND2,FINST2 - Parameters for smoothing *
2302 !* output reflectance spectra. *
2303 !* NATOT,NBTOT,NCTOT,NDTOT - Number of channels for the four AVIRIS' *
2304 !* grating spectrometers (A, B, C, and D). *
2305 !* Return Codes: None. *
2306 !* Special Considerations: Some parameters may need to be fine-tuned. *
2307 !* *
2308 !********************************************************************************
2309 !* Notes about water vapor VMRS and related quantities: *
2310 !* *
2311 !* VAPVRT(60) - a table containing 60 column vapor values (in unit of cm) *
2312 !* *
2313 !* VAP_SLANT(I) = VAPVRT(I) * 2.0, VAP_SLANT is a new table for containing *
2314 !* two-way total vapor amounts. Here the number "2" can be *
2315 !* changed to other numbers, e.g., 2.5, without major *
2316 !* effects on retrieved water vapor values. *
2317 !* *
2318 !* G_VAP(I = 1,..., NL) = true vapor geometric factor for each layer in *
2319 !* the model atmosphere (after adjusting for the elevated *
2320 !* surface. *
2321 !* *
2322 !* VMRM(I) = VMRM(I)*G_VAP(I). The VMRS are multiplied by the geometrical *
2323 !* factor. We can calculate the vapor transmittance on the *
2324 !* Sun-surface-sensor path by assuming a vertical path in *
2325 !* the model atmosphere with geometric-factor-adjusted VMRS. *
2326 !* *
2327 !* CLMVAP = vertical column amount from ground to space in model atmosphere*
2328 !* CLMVAPP = vertical column amount from ground to aircraft or satellite *
2329 !* sensor in model atmosphere *
2330 !* Q = 2.152E25 = # of molecules above the surface at one atmosphere *
2331 !* (in unit of molecules/cm**2) *
2332 !* *
2333 !* VAP_SLANT_MDL= CLMVAP/COS(SOLZNI) + CLMVAPP/COS(OBSZNI) = total amount *
2334 !* of water vapor in the model atmosphere in the L-shaped *
2335 !* Sun-surface-plane ray path. *
2336 !* *
2337 !* G_VAP_EQUIV = VAP_SLANT_MDL / CLMVAP = the "equivalent" geometrical *
2338 !* factor corresponding to the total slant vapor amount *
2339 !* VAP_SLANT_MDL and the column vapor amount CLMVAP. *
2340 !* *
2341 !* SSH2O(I) (I = 1, ..., 60) - a pure scaling factor relative to the total *
2342 !* slant vapor amount of VAP_SLANT_MDL, and *
2343 !* SSH2O(I) = VAP_SLANT(I) / VAP_SLANT_MDL *
2344 !* *
2345 !* SH2O = one value of SSH2O(I). SH2O is used during generation of the *
2346 !* look-up table. *
2347 !* *
2348 !* VAPTT = VAP_SLANT_MDL*SH2O, is the absolute total vapor amount on the *
2349 !* L-shaped path corresponding to a spectrum stored in the *
2350 !* look-up table. *
2351 !* *
2352 !* CLMWVP = 0.5*(VAPTTA+VAPTTB)/G_VAP_EQUIV, is the retrieved column water *
2353 !* vapor amount from imaging spectrometer data. *
2354 !********************************************************************************
2355  */
2357  int32_t co2 = getinput1_.co2, o2 = getinput1_.o2, n2o = getinput1_.n2o, co = getinput1_.co, ch4 = getinput1_.ch4, no2 = getinput1_.no2, o3 = getinput1_.o3;
2358  float *fwhm = getinput4_.fwhm, *wavobs = getinput4_.wavobs, *dp = init_speccal5_.dp, *tm = init_speccal5_.tm, *pm = init_speccal5_.pm, *vmrm = init_speccal5_.vmrm;
2359  float *finst2 = init_speccal10_.finst2;
2360  int32_t nobs = getinput5_.nobs;
2361  ;
2362  float totlo3 = geometry2_.totlo3; //=no2cf_init1_.rno2cf;
2363  float dlt2 = getinput5_.dlt2, wavcv2, dwvavr, sumins;
2364  float sno2 = getinput3_.sno2, vrto3 = getinput3_.vrto3, totno2;
2365  float go3 = geometry2_.go3, Q = model_adj1_.q;
2366  static float *abscf_co2, *abscf_o2, *abscf_n2o, *abscf_ch4, *abscf_co, const1, *o3cf, *rno2cf; //=o3cf_init1_.o3cf;
2367  static int firstCall = 1;
2368  int32_t i, j, k, k_surf = model_adj4_.k_surf, nl = getinput3_.nl;
2369  int32_t iwndw1, iwndw2, iwndw3, iwndw4, iwndw5, iwp94c, iw1p14c, nchnla, nchnlb, nchnlc, nchnld, nb1haf, nb2haf, nb3haf, nb4haf;
2370  char *abscf_file = "abscf_gas.nc";
2371  char *abscf_no2o3file = "abscf_no2o3.nc";
2372  static size_t ncf;
2373 
2374  char *filedir;
2375  char filename[FILENAME_MAX];
2376  size_t start[3], count[3];
2377  int xid, yid;
2378  int retval, sds_id;
2379  static size_t bands, levels;
2380 
2381  float vrtno2 = 5.0E+15, gno2, sclgas, sclco2, sclch4;
2382  float *sumcf;
2383  float tempf;
2384 
2385  if (firstCall) {
2386  const1 = 4.0 * log(2); // gaussian curve area constant
2387  init_speccal3_.nh2o = NH2OMAX; // number of water vapor values in table
2388  //Wavelength of medium resolution spectrum FWHM=.2 nm, .56-3.1 um
2389  for (i = 0; i < NP_MED; i++) {
2390  init_speccal12_.wavln_med[i] = (float) VSTART + i * (float) DWAVLN;
2391  /*
2392  Note: The grids of WAVNO_HI do not match the grids of 10000./WAVLN_MED.
2393  INDEX_MED is a specially designed index for finding close matches
2394  between the two kinds of grids.
2395  */
2396  init_speccal13_.index_med[i] = ((float) 10000. / init_speccal12_.wavln_med[i] - (float) 3000.) / (float) DWAVNO + 1;
2397  /*
2398  Note: WAVLN_MED_INDEX(I) is very close to WAVLN_MED(I),
2399  and WAVLN_MED_INDEX(I) >= WAVLN_MED(I)
2400 
2401 
2402  */
2403  init_speccal13_.wavln_med_index[i] = (float) 10000. / ((init_speccal13_.index_med[i] - (float) 1.)*(float) DWAVNO + (float) 3000.);
2404  // tempf = 10000.*DLT_MED/(init_speccal13_.wavln_med_index[i]*init_speccal13_.wavln_med_index[i]);
2405  // init_speccal14_.fwhm_wavno[i] = tempf;
2406  // init_speccal14_.ncvhf_wavno[i] = ( FACDLT * tempf / DWAVNO + 1.);
2407  // init_spectest_.fwhm_wavno[i] = tempf;
2408  // init_spectest_.ncvhf_wavno[i] = ( FACDLT * tempf / DWAVNO + 1.);
2409  // init_spectest_.tempf = tempf;
2410  }
2411  //Wavelength of medium resolution spectrum FWHM=.2 nm, .3-3.1 um
2412  for (i = 0; i < NP_STD; i++)
2413  init_speccal12_.wavln_std[i] = (float) 0.3 + i * (float) DWAVLN;
2414  /*
2415  Initialize arrays for smoothing medium resolution spectrum (DLT_MED = 0.2 nm,
2416  and point spacing DWAVLN = 0.0001 micron) to coarser spectral
2417  resolution data from imaging spectrometers.
2418 
2419  NCVHF(I) = ( FACDLT * FWHM(I) / DWAVLN + 1.)
2420 
2421  */
2422  for (i = 0; i < nobs; i++)
2423  init_speccal15_.ncvhf[i] = (float) FACDLT * fwhm[i] / (float) DWAVLN + (float) 1.0;
2424 
2425  // parameters and arrays to smooth output surface reflectance spectrum
2426  wavcv2 = FACDLT*dlt2;
2427  /*
2428  * Find the largest value in the FWHM array, and use this value in calculation
2429  of indices for smoothing output reflectance spectra. This smoothing
2430  algorithm should work well with grating spectrometers having nearly
2431  constant spectral resolutions, but not so well for prism spectrometers
2432  having variable spectral resolution.
2433  */
2434  dwvavr = fwhm[0];
2435 
2436  for (i = 1; i < nobs; i++)
2437  if (dwvavr < fwhm[i]) dwvavr = fwhm[i];
2438 
2439  init_speccal10_.ncv2 = wavcv2 / dwvavr;
2440  init_speccal10_.ncvhf2 = init_speccal10_.ncv2 + 1;
2441  init_speccal10_.ncvtt2 = init_speccal10_.ncv2 + 1;
2442 
2443  if (dlt2 != 0) {
2444  sumins = 0;
2445  for (i = init_speccal10_.ncvhf2 - 1; i < init_speccal10_.ncvtt2; i++) {
2446  finst2[i] = exp(-const1 * pow((i - init_speccal10_.ncvhf2 + 1) * dwvavr / dlt2, 2));
2447  sumins += finst2[i];
2448  }
2449  for (i = 0; i < init_speccal10_.ncvhf2 - 1; i++) {
2450  finst2[i] = finst2[init_speccal10_.ncvtt2 - i - 1];
2451  sumins += finst2[i];
2452  }
2453  sumins *= dwvavr;
2454 
2455  for (i = 0; i < init_speccal10_.ncvtt2; i++) {
2456  finst2[i] *= (dwvavr / sumins);
2457  }
2458  }
2459 
2460  init_speccal10_.istrt2 = init_speccal10_.ncvhf2;
2461  init_speccal10_.iend2 = nobs - init_speccal10_.ncvhf2;
2462 
2463  /* number of channels of the four AVIRIS spectrometers. These are used
2464  in removing null AVIRIS radiance values in the overlap portions of two
2465  adjacent spectrometers.
2466 
2467  Note by R.Healy - The Aviris correction isn't being used in l2gen yet. (3/2016)
2468  There are no sensor specific modifications being applied. Atrem has only been
2469  tested on HICO data.
2470  */
2471  nchnla = 32;
2472  nchnlb = 64;
2473  nchnlc = 64;
2474  nchnld = 64;
2475 
2476  init_speccal11_.natot = nchnla;
2477  init_speccal11_.nbtot = nchnla + nchnlb;
2478  init_speccal11_.nctot = nchnla + nchnlb + nchnlc;
2479  init_speccal11_.ndtot = nchnla + nchnlb + nchnlc + nchnld;
2480 
2481  /* Resetting window wavelength positions and calculating weights for
2482  window and absorption channels used in 3-channel ratioing.
2483  Note that the C version of this function returns 0 based indices
2484  */
2485  iwndw1 = findMatch(wavobs, nobs, getinput6_.wndow1);
2486  iwndw2 = findMatch(wavobs, nobs, getinput6_.wndow2);
2487 
2488  getinput6_.wndow1 = wavobs[iwndw1];
2489  getinput6_.wndow2 = wavobs[iwndw2];
2490 
2491  if ((getinput7_.nb1 % 2) == 0) getinput7_.nb1 += 1;
2492  if ((getinput7_.nb2 % 2) == 0) getinput7_.nb2 += 1;
2493 
2494  nb1haf = (getinput7_.nb1 - 1) / 2;
2495  nb2haf = (getinput7_.nb2 - 1) / 2;
2496 
2497  // Adding one to all the indexes because of legacy fortran - subtracted in get_atrem_cor
2498  init_speccal6_.ist1 = iwndw1 - nb1haf + 1;
2499  init_speccal6_.ied1 = iwndw1 + nb1haf + 1;
2500  init_speccal6_.ist2 = iwndw2 - nb2haf + 1;
2501  init_speccal6_.ied2 = iwndw2 + nb2haf + 1;
2502 
2503  iwp94c = findMatch(wavobs, nobs, getinput6_.wp94c);
2504  getinput6_.wp94c = wavobs[iwp94c];
2505 
2506  if ((getinput7_.nbp94 % 2) == 0) getinput7_.nbp94 += 1;
2507 
2508  nb3haf = (getinput7_.nbp94 - 1) / 2;
2509  init_speccal6_.istp94 = iwp94c - nb3haf + 1;
2510  init_speccal6_.iedp94 = iwp94c + nb3haf + 1;
2511 
2512  init_speccal8_.wt1 = (getinput6_.wndow2 - getinput6_.wp94c) / (getinput6_.wndow2 - getinput6_.wndow1);
2513  init_speccal8_.wt2 = (getinput6_.wp94c - getinput6_.wndow1) / (getinput6_.wndow2 - getinput6_.wndow1);
2514 
2515  iwndw4 = findMatch(wavobs, nobs, getinput6_.wndow3);
2516  iwndw5 = findMatch(wavobs, nobs, getinput6_.wndow4);
2517 
2518  getinput6_.wndow3 = wavobs[iwndw4];
2519  getinput6_.wndow4 = wavobs[iwndw5];
2520 
2521  if ((getinput7_.nb3 % 2) == 0) getinput7_.nb3 += 1;
2522  if ((getinput7_.nb4 % 2) == 0) getinput7_.nb4 += 1;
2523 
2524  nb3haf = (getinput7_.nb3 - 1) / 2;
2525  nb4haf = (getinput7_.nb4 - 1) / 2;
2526 
2527  init_speccal7_.ist3 = iwndw4 - nb3haf + 1;
2528  init_speccal7_.ied3 = iwndw4 + nb3haf + 1;
2529  init_speccal7_.ist4 = iwndw5 - nb4haf + 1;
2530  init_speccal7_.ied4 = iwndw5 + nb4haf + 1;
2531 
2532  iw1p14c = findMatch(wavobs, nobs, getinput6_.w1p14c);
2533  getinput6_.w1p14c = wavobs[iw1p14c];
2534 
2535  if ((getinput7_.nb1p14 % 2) == 0) getinput7_.nb1p14 += 1;
2536 
2537  nb3haf = (getinput7_.nb1p14 - 1) / 2;
2538  init_speccal7_.ist1p14 = iw1p14c - nb3haf + 1;
2539  init_speccal7_.ied1p14 = iw1p14c + nb3haf + 1;
2540 
2541  init_speccal8_.wt3 = (getinput6_.wndow4 - getinput6_.w1p14c) / (getinput6_.wndow4 - getinput6_.wndow3);
2542  init_speccal8_.wt4 = (getinput6_.w1p14c - getinput6_.wndow3) / (getinput6_.wndow4 - getinput6_.wndow3);
2543 
2544  // Open the netcdf4 input file
2545  if ((filedir = getenv("OCDATAROOT")) == NULL) {
2546  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
2547  exit(FATAL_ERROR);
2548  }
2549 
2550  strcpy(filename, filedir);
2551  strcat(filename, "/common/");
2552  strcat(filename, abscf_file);
2553  retval = nc_open(filename, NC_NOWRITE, &sds_id);
2554  if (retval != NC_NOERR) {
2555  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
2556  __FILE__, __LINE__, filename);
2557  exit(FATAL_ERROR);
2558  }
2559  // Now read in the absorption coefficients
2560  retval = nc_inq_dimid(sds_id, "level", &xid) \
2561  || nc_inq_dimlen(sds_id, xid, &levels) \
2562  || nc_inq_dimid(sds_id, "band", &yid) \
2563  || nc_inq_dimlen(sds_id, yid, &bands);
2564 
2565  if (retval) {
2566  fprintf(stderr, "-E- %s line %d: nc_inq_dimid(%s) failed.%d %d %d \n",
2567  __FILE__, __LINE__, filename, (int) levels, (int) bands, retval);
2568  exit(FATAL_ERROR);
2569  }
2570 
2571  abscf_o2 = (float *) calloc(levels*bands, sizeof (float));
2572  if (!(abscf_o2)) {
2573  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_n2o.\n",
2574  __FILE__, __LINE__);
2575  exit(FATAL_ERROR);
2576  }
2577 
2578  abscf_co2 = (float *) calloc(levels*bands, sizeof (float));
2579  if (!(abscf_co2)) {
2580  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_co2.\n",
2581  __FILE__, __LINE__);
2582  exit(FATAL_ERROR);
2583  }
2584  abscf_co = (float *) calloc(levels*bands, sizeof (float));
2585  if (!(abscf_co)) {
2586  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_co.\n",
2587  __FILE__, __LINE__);
2588  exit(FATAL_ERROR);
2589  }
2590  abscf_ch4 = (float *) calloc(levels*bands, sizeof (float));
2591  if (!(abscf_ch4)) {
2592  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_ch4.\n",
2593  __FILE__, __LINE__);
2594  exit(FATAL_ERROR);
2595  }
2596  abscf_n2o = (float *) calloc(levels*bands, sizeof (float));
2597  if (!(abscf_n2o)) {
2598  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_n2o.\n",
2599  __FILE__, __LINE__);
2600  exit(FATAL_ERROR);
2601  }
2602 
2603  get_abscf_data(levels, bands, sds_id, filename, abscf_o2, "abscf_o2");
2604  get_abscf_data(levels, bands, sds_id, filename, abscf_co2, "abscf_co2");
2605  get_abscf_data(levels, bands, sds_id, filename, abscf_co, "abscf_co");
2606  get_abscf_data(levels, bands, sds_id, filename, abscf_ch4, "abscf_ch4");
2607  get_abscf_data(levels, bands, sds_id, filename, abscf_n2o, "abscf_n2o");
2608 
2609  nc_close(sds_id);
2610 
2611  strcpy(filename, filedir);
2612  strcat(filename, "/common/");
2613  strcat(filename, abscf_no2o3file);
2614  strcat(filename, "\0");
2615  retval = nc_open(filename, NC_NOWRITE, &sds_id);
2616  if (retval != NC_NOERR) {
2617  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
2618  __FILE__, __LINE__, filename);
2619  exit(FATAL_ERROR);
2620  }
2621  // Now read in the absorption coefficients
2622  retval = nc_inq_dimid(sds_id, "ncf", &xid) \
2623  || nc_inq_dimlen(sds_id, xid, &ncf);
2624 
2625  if (retval) {
2626  fprintf(stderr, "-E- %s line %d: nc_inq_dimid(%s) failed. %d %d \n",
2627  __FILE__, __LINE__, filename, (int) ncf, retval);
2628  exit(FATAL_ERROR);
2629  }
2630 
2631  o3cf = (float *) calloc(ncf, sizeof (float));
2632  if (!(o3cf)) {
2633  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_o3.\n",
2634  __FILE__, __LINE__);
2635  exit(FATAL_ERROR);
2636  }
2637  rno2cf = (float *) calloc(ncf, sizeof (float));
2638  if (!(o3cf)) {
2639  fprintf(stderr, "-E- %s line %d: Failed to allocate memory for abscf_no2.\n",
2640  __FILE__, __LINE__);
2641  exit(FATAL_ERROR);
2642  }
2643 
2644  start[0] = 0;
2645  start[1] = 0;
2646  start[2] = 0;
2647  count[0] = ncf;
2648  count[1] = 0;
2649  count[2] = 0;
2650 
2651  retval = nc_inq_varid(sds_id, "o3cf", &xid);
2652 
2653  if (retval != NC_NOERR) {
2654  fprintf(stderr,
2655  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2656  __FILE__, __LINE__, filename, "o3cf");
2657  exit(FATAL_ERROR);
2658  }
2659  retval = nc_get_vara_float(sds_id, xid, start, count, o3cf);
2660  if (retval != NC_NOERR) {
2661  fprintf(stderr,
2662  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2663  __FILE__, __LINE__, filename, "o3cf");
2664  exit(FATAL_ERROR);
2665  }
2666 
2667  retval = nc_inq_varid(sds_id, "no2cf", &xid);
2668 
2669  if (retval != NC_NOERR) {
2670  fprintf(stderr,
2671  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2672  __FILE__, __LINE__, filename, "no2cf");
2673  exit(FATAL_ERROR);
2674  }
2675  retval = nc_get_vara_float(sds_id, xid, start, count, rno2cf);
2676  if (retval != NC_NOERR) {
2677  fprintf(stderr,
2678  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
2679  __FILE__, __LINE__, filename, "no2cf");
2680  exit(FATAL_ERROR);
2681  }
2682 
2683 
2684  nc_close(sds_id);
2685 
2686  firstCall = 0;
2687  }
2688 
2689  // Initialize the TRAN_HI array for high resolution spectrum:
2690  for (i = 0; i < bands; i++)
2691  init_speccal1_.tran_hi_others[i] = 1.0;
2692 
2693  /*
2694  Calculate medium resolution O3 transmittances (0.2 nm, 2-way) with
2695  a point spacing of 0.1 nm between 0.3 and 0.8 micron.
2696  */
2697  if (o3) {
2698  for (i = 0; i < NO3PT; i++) {
2699  init_speccal16_.tran_o3_std[i] = exp(-totlo3 * o3cf[i]);
2700  //printf("TRAN_O3_STD %d %g %f %f\n",i+1,init_speccal16_.tran_o3_std[i],totlo3,o3cf[i]);
2701  }
2702  } else {
2703  /* If NO2 is not intended to be included in total atmospheric gaseous
2704  transmittance calculations, assigning TRAN_NO2_STD = 1.0:
2705  */
2706  for (i = 0; i < NO3PT; i++)
2707  init_speccal16_.tran_o3_std[i] = 1.0;
2708 
2709  }
2710  /*
2711  Calculate medium resolution NO2 transmittances (0.2 nm, 2-way) with
2712  a point spacing of 0.1 nm between 0.3 and 0.8 micron.
2713  */
2714 
2715  vrtno2 = 5.0E+15;
2716  vrtno2 *= sno2;
2717 
2718  gno2 = go3;
2719  totno2 = gno2 * vrtno2;
2720 
2721  if (no2) {
2722  for (i = 0; i < NO2PT; i++) {
2723  init_speccal17_.tran_no2_std[i] = exp(-totno2 * rno2cf[i]);
2724  //printf("TRAN_NO2_STD %d %g %g %g\n",i+1,init_speccal17_.tran_no2_std[i],totno2,rno2cf[i]);
2725  }
2726  } else {
2727  /* If NO2 is not intended to be included in total atmospheric gaseous
2728  transmittance calculations, assigning TRAN_NO2_STD = 1.0:
2729  */
2730  for (i = 0; i < NO2PT; i++)
2731  init_speccal17_.tran_no2_std[i] = 1.0;
2732  }
2733 
2734  for (i = 0; i < nl; i++) {
2735  dp[i] = getinput3_.p[i] - getinput3_.p[i + 1];
2736  pm[i] = (getinput3_.p[i] + getinput3_.p[i + 1]) / (float) 2.0;
2737  tm[i] = (getinput3_.t[i] + getinput3_.t[i + 1]) / (float) 2.0;
2738  }
2739 
2740  /*
2741 
2742 !C
2743 !C Calculate high resolution transmittances (0.05 cm-1) of CO2, N2O, CO,
2744 !C CH4, and O2 in the 0.56 - 3.1 micron range, and save values for
2745 !C calculating total atmospheric transmittances later.
2746 !C Because water vapor amounts are allowed to vary,
2747 !C the high resolution water vapor transmittances are calculated
2748 !C in subroutines TRAN_TABLE and TRANCAL. TRAN_TABLE provides variable
2749 !C water vapor amounts, and calls TRANCAL for the calculation of
2750 !C corresponding vapor transmittance spectrum.
2751 !C
2752 
2753  */
2754 
2755  // For CO2 transmittance calculation -
2756  if (co2) {
2757  /*
2758  -- On 2/7/2013 B.-C. Gao made the modification - Increased SCLCO2 i
2759  -- from 1.0 to 1.1 to reflect the fact that the CO2 VMR reached the
2760  -- 2012 level of 390 ppmv.
2761  --
2762  */
2763  sclgas = 1.1;
2764  /*
2765  Scale the VMRM by the two-way path geometrical factors. The geometric
2766  factors, G_OTHER, varies with atmospheric layer number for
2767  aircraft observational geometries.
2768  */
2769  for (i = 0; i < nl; i++)
2770  vmrm[i] = sclgas * (float) 355.0 * (float) 1.e-6 * geometry3_.g_other[i];
2771 
2772  apply_gas_trans(k_surf, levels, bands, abscf_co2, dp, vmrm, init_speccal1_.tran_hi_others);
2773  // for (i = 0; i < bands; i++)
2774  // if (init_speccal1_.tran_hi_others[i]<1.0) printf("CO2: %d tran_hi_others=%f\n",i, init_speccal1_.tran_hi_others[i]);
2775 
2776  }
2777 
2778 
2779  /*
2780  --------------------------------------------
2781  For N2O transmittance calculation.
2782  */
2783  if (n2o) {
2784  sclgas = 0.3;
2785  for (i = 0; i < nl; i++)
2786  vmrm[i] = sclgas * (float) 1.e-6 * geometry3_.g_other[i];
2787 
2788  apply_gas_trans(k_surf, levels, bands, abscf_n2o, dp, vmrm, init_speccal1_.tran_hi_others);
2789  // for (i = 0; i < bands; i++)
2790  // if (init_speccal1_.tran_hi_others[i]<1.0)printf("N2O: %d tran_hi_others=%f\n",i, init_speccal1_.tran_hi_others[i]);
2791  }
2792  /*
2793  --------------------------------------------
2794  For CO transmittance calculation.
2795  */
2796  if (co) {
2797  sclgas = 0.1;
2798  for (i = 0; i < nl; i++)
2799  vmrm[i] = sclgas * (float) 1.e-6 * geometry3_.g_other[i];
2800 
2801  apply_gas_trans(k_surf, levels, bands, abscf_co, dp, vmrm, init_speccal1_.tran_hi_others);
2802  // for (i = 0; i < bands; i++)
2803  // if (init_speccal1_.tran_hi_others[i]<1.0)printf("CO: %d tran_hi_others=%f\n",i, init_speccal1_.tran_hi_others[i]);
2804  }
2805  /*
2806 --------------------------------------------
2807  For CH4 transmittance calculation.
2808  For assigning CH4 VMRM
2809  NOTE: The scaling factor of 0.8 for the CH4 VMRS was obtained by comparing
2810  transmittance spectra calculated using our program, which is based on
2811  the Malkmus narrow band spectral model, with a ratioed spectrum
2812  provided by G. C. Toon at Jet Propulsion Laboratory (JPL). The JPL
2813  ratio spectrum was obtained by ratioing a high resolution (0.005 cm-1)
2814  solar spectrum measured at ground level against a solar spectrum
2815  measured at an altitude of approximately 35 km with the same Fourier
2816  Transform spectrometer. The high resolution ratio spectrum was
2817  degraded to a resolution of 10 nm during our derivation of the
2818  scaling factor for the CH4 VMRS.
2819 
2820  sclch4=0.8;
2821  */
2822  if (ch4) {
2823  sclgas = 1.0;
2824  for (i = 0; i < nl; i++)
2825  vmrm[i] = sclgas * (float) 1.6 * (float) 1.0e-6 * geometry3_.g_other[i]; //I don't know why sclgas=1 and then it's multiplied by 1.6 - rjh
2826 
2827  apply_gas_trans(k_surf, levels, bands, abscf_ch4, dp, vmrm, init_speccal1_.tran_hi_others);
2828  // for (i = 0; i < bands; i++)
2829  // if (init_speccal1_.tran_hi_others[i]<1.0)printf("CH4: %d tran_hi_others=%f\n",i, init_speccal1_.tran_hi_others[i]);
2830 
2831  }
2832  if (o2) {
2833  /*
2834  * ***Modified by Bo-Cai Gao on 2/7/2013 to increase O2 absorption
2835  --- coefficients by the factor SCL_O2 for wavelengths > 1.2 micron
2836  --- in order to model properly the atmospheric O2 band centered
2837  --- near 1.265 micron.
2838  *
2839  */
2840  sclgas = 0.21;
2841 
2842  if ((sumcf = (float *) calloc(bands, sizeof (float))) == NULL) {
2843  printf("-E- : Error allocating memory to sumcf\n");
2844  exit(FATAL_ERROR);
2845  }
2846 
2847  for (i = 0; i < nl; i++)
2848  vmrm[i] = sclgas * geometry3_.g_other[i];
2849 
2850  for (i = 0; i < bands; i++)
2851  sumcf[i] = 0.;
2852  /*
2853  * ***Modified by Bo-Cai Gao on 2/7/2013 to increase O2 absorption
2854  --- coefficients by the factor SCL_O2 for wavelengths > 1.2 micron
2855  --- i& < 1.3333 micron in order to model properly the atmospheric
2856  --- O2 band centered near 1.265 micron.
2857  *
2858  */
2859  sclgas = 2.60;
2860  printf("RJH: INIT_SPECCAL - be sure to change below line to i=k_surf and i - k_surf (NOT i - k_surf + 1) once final conversion to C is complete\n ");
2861 
2862  for (i = k_surf - 1; i < levels; i++)
2863  for (j = 0; j < bands; j++)
2864  sumcf[j] -= abscf_o2[bands * i + j] * dp[i - k_surf + 1] * vmrm[i - k_surf + 1];
2865 
2866  for (i = 0; i < 9000; i++)
2867  init_speccal1_.tran_hi_others[i] *= exp(sumcf[i] * Q * (float) 28.966 / (float) 6.0225E+23 / (float) 1.0E-06);
2868  for (i = 9000; i < 106600; i++)
2869  init_speccal1_.tran_hi_others[i] *= exp(sumcf[i] * Q * sclgas * (float) 28.966 / (float) 6.0225E+23 / (float) 1.0E-06);
2870  for (i = 106600; i < NP_HI; i++)
2871  init_speccal1_.tran_hi_others[i] *= exp(sumcf[i] * Q * (float) 28.966 / (float) 6.0225E+23 / (float) 1.0E-06);
2872  // for (i = 0; i < bands; i++) {
2873  // printf("OX: %d tran_hi_others %f\n",i, init_speccal1_.tran_hi_others[i]);
2874  // if (i==94923) {
2875  // printf("OX: %d %f %f\n",i,exp(sumcf[i]*Q*sclgas* (float)28.966 / (float)6.0225E+23 /(float) 1.0E-06),sumcf[i]);
2876  // for (k=k_surf-1; k<levels;k++)
2877  // printf("OX: ABSCF: %d %f %f %f\n",k,abscf_o2[bands * k + i],dp[k-k_surf+1],vmrm[k-k_surf+1]); }
2878  // }
2879  free(sumcf);
2880  }
2881 }
2882 
2883 /*
2884  * Converted to C 4/2016 - R. Healy
2885 !********************************************************************************
2886 !* *
2887 !* Name: TRAN_TABLE *
2888 !* Purpose: This subroutine generates a table consisting of 60 atmospheric *
2889 !* transmittance spectra at the solar and observational *
2890 !* geometry and with 60 column water vapor values. The table also *
2891 !* includes the total amounts of column water vapor used in the *
2892 !* calculations, and the 3-channel ratios calculated from the window *
2893 !* and absorption channels in and around the 0.94- and 1.14-um water *
2894 !* vapor bands. *
2895 !* Parameters: none *
2896 !* Algorithm: For each of the 60 water vapor amounts, calculate the *
2897 !* atmospheric transmittance, and save *
2898 !* Globals Used: NH2O - number of column water vapor values *
2899 !* VAPTT - geometrically adjusted water vapor total *
2900 !* R094 - channel ratio for .94 um region *
2901 !* R114 - channel ratio for 1.14 um region *
2902 !* TRNCAL - atmospheric transmittance spectra *
2903 !* Global Output: VAPTOT() - array containing geometrically adjusted water *
2904 !* vapor values *
2905 !* ROP94() - array containing channel ratios for .94 um region *
2906 !* R1P14() - array containing channel ratios for 1.14 um region*
2907 !* TRNTBL() - 2 dimensional array containing one transmittance *
2908 !* spectrum for each column water vapor amount *
2909 !* Return Codes: none *
2910 !* Special Considerations: none *
2911 !* *
2912 !********************************************************************************
2913 !********************************************************************************
2914 !* TRANCAL combined with TRAN_TABLE by R. Healy 4/28/2015 *
2915 !* Name: TRANCAL *
2916 !* Purpose: This program calculates combined transmittances of H2O, CO2, O3, *
2917 !* N2O, CO, CH4, and O2. *
2918 !* Parameters: none. *
2919 !* Algorithm: The calculations were based on the line-by-line absorption *
2920 !* parameters supplied by William R. Ridgway of NASA/GSFC. *
2921 !* Global output:VAPTT - geometrically adjusted water vapor total. *
2922 !* R094 - channel ratio for 0.94 um region. *
2923 !* R114 - channel ratio for 1.14 um region. *
2924 !* TRNCAL - total transmittances of all gases that match the *
2925 !* resolutions of imaging spectrometers. *
2926 !* Return Codes: none. *
2927 !* Special Considerations: The high resolution (0.05 cm-1) line-by-line *
2928 !* absorption parameters cover the 0.555 - 3.33 micron spectral range *
2929 !* (3000 - 18000 cm-1). The medium resolution ozone absorption *
2930 !* coefficients covers the 0.3-0.8 um spectral range. The line-by-line *
2931 !* high resolution spectra were first smoothed to medium resolution *
2932 !* spectra (resolution = 0.2 nm, wavelength spacing = 0.1 nm) covering *
2933 !* the 0.56 - 3.1 micron spectral region. The medium resolution spectra *
2934 !* of O3 and other gases are combined (in SUBROUTINE TRAN_SMOOTH) to form *
2935 !* a single medium resolution spectrum from 0.3 to 3.1 micron. This *
2936 !* combined spectrum (medium resolution) is then smoothed to lower *
2937 !* resolutions to match the resolutions of imaging spectrometers. The *
2938 !* smoothing is also done in SUBROUTINE TRAN_SMOOTH. *
2939 !* *
2940 !********************************************************************************
2941  */
2942 
2943 void tran_table() {
2944 
2945  int32_t co2 = getinput1_.co2, o2 = getinput1_.o2, n2o = getinput1_.n2o, co = getinput1_.co, ch4 = getinput1_.ch4, no2 = getinput1_.no2, o3 = getinput1_.o3;
2946  float *fwhm = getinput4_.fwhm, *wavobs = getinput4_.wavobs, *dp = init_speccal5_.dp, *tm = init_speccal5_.tm, *pm = init_speccal5_.pm, *vmrm = init_speccal5_.vmrm;
2947  float *finst2 = init_speccal10_.finst2, *vmr = getinput3_.vmr;
2948  int32_t nobs = getinput5_.nobs, nh2o = init_speccal3_.nh2o, fullcalc = getinput5_.full_calc;
2949  int32_t nb = getinput3_.nb, nl = getinput3_.nl, splitpaths = geometry_l2gen_.splitpaths, ja = geometry_l2gen_.ja, jb = geometry_l2gen_.jb;
2950  float totlo3 = geometry2_.totlo3, *rno2cf = no2cf_init1_.rno2cf;
2951  float dlt2 = getinput5_.dlt2, wavcv2, dwvavr, sumins;
2952  float sno2 = getinput3_.sno2, vrto3 = getinput3_.vrto3, totno2;
2953  float go3 = geometry2_.go3, Q = model_adj1_.q;
2954  float mu = geometry5_.mu, mu0 = geometry5_.mu0, *ssh2o = geometry2_.ssh2o, *g_vap = geometry3_.g_vap;
2955  float dvap_plane = model_adj3_.dvap_plane, dp_plane = model_adj3_.dp_plane, dvap_layer = model_adj3_.dvap_layer, dp_layer = model_adj3_.dp_layer;
2956  int32_t k_plane = model_adj3_.k_plane, k_surf = model_adj4_.k_surf;
2957  float *vaptot = tran_table1_.vaptot;
2958  int i, j, k, m, n;
2959  static int firstCall = 1;
2960 
2961  static float *abscf_h2o;
2962  static float *tran_hi, *wavno_hi;
2963 
2964  char *filedir;
2965  char *abscf_file = "abscf_gas.nc";
2966  char filename[FILENAME_MAX];
2967  size_t start[3], count[3];
2968  int xid, yid;
2969  int retval, sds_id;
2970  static size_t bands, levels;
2971 
2972  static int32_t n_g = 7, doSmooth;
2973  float tg[7] = {0.0, 0.379, 0.5106, 0.81, 0.9548, 0.9933, 1.0}, f1, f2;
2974 
2975  static float *tkcdf;
2976  static float *sum_kd, *sumcf, **sumcf_s;
2977  float vmrm_s[2][MODELMAX];
2978 
2979  if (firstCall) {
2980 
2981  if (fullcalc)
2982  printf("ATREM: **WARNING** Full_calc is on. Processing will be extremely slow...\n");
2983  else
2984  printf("ATREM: Full_calc is off. Processing using k-distribution method...\n");
2985 
2986  doSmooth = co2 || n2o || co || ch4 || o2 || o3 || no2;
2987 
2988  // Open the netcdf4 input file
2989  if ((filedir = getenv("OCDATAROOT")) == NULL) {
2990  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
2991  exit(FATAL_ERROR);
2992  }
2993 
2994  strcpy(filename, filedir);
2995  strcat(filename, "/common/");
2996  // strcpy(filename,input_l2gen_.filename);
2997  strcat(filename, abscf_file);
2998  strcat(filename, "\0");
2999  retval = nc_open(filename, NC_NOWRITE, &sds_id);
3000  if (retval != NC_NOERR) {
3001  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
3002  __FILE__, __LINE__, filename);
3003  exit(FATAL_ERROR);
3004  }
3005  // Now read in the absorption coefficients
3006  retval = nc_inq_dimid(sds_id, "level", &xid) \
3007  || nc_inq_dimlen(sds_id, xid, &levels) \
3008  || nc_inq_dimid(sds_id, "band", &yid) \
3009  || nc_inq_dimlen(sds_id, yid, &bands);
3010 
3011  if (retval) {
3012  fprintf(stderr, "-E- %s line %d: nc_inq_dimid(%s) failed. %d %d %d \n",
3013  __FILE__, __LINE__, filename, (int) levels, (int) bands, retval);
3014  exit(FATAL_ERROR);
3015  }
3016 
3017  if (!(abscf_h2o = (float *) malloc(levels * bands * sizeof (float)))) {
3018  printf("-E- : Error allocating memory to abscf_h2o\n");
3019  exit(FATAL_ERROR);
3020  }
3021 
3022 
3023  start[0] = 0;
3024  start[1] = 0;
3025  start[2] = 0;
3026  count[0] = levels;
3027  count[1] = bands;
3028  count[2] = 0;
3029 
3030  retval = nc_inq_varid(sds_id, "abscf_h2o", &xid);
3031 
3032  if (retval != NC_NOERR) {
3033  fprintf(stderr,
3034  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
3035  __FILE__, __LINE__, filename, "abscf_h2o");
3036  exit(FATAL_ERROR);
3037  }
3038  retval = nc_get_vara_float(sds_id, xid, start, count, abscf_h2o);
3039  if (retval != NC_NOERR) {
3040  fprintf(stderr,
3041  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
3042  __FILE__, __LINE__, filename, "abscf_h2o");
3043  exit(FATAL_ERROR);
3044  }
3045 
3046  if (!wavno_hi && !(wavno_hi = (float *) malloc(NP_HI * sizeof (float *)))) {
3047  printf("-E- : Error allocating memory to wavno_hi\n");
3048  exit(FATAL_ERROR);
3049  }
3050 
3051  retval = nc_inq_varid(sds_id, "waveno", &xid);
3052 
3053  count[0] = bands;
3054  count[1] = 0;
3055 
3056  retval = nc_get_vara_float(sds_id, xid, start, count, wavno_hi);
3057  if (retval != NC_NOERR) {
3058  fprintf(stderr,
3059  "-E- %s line %d: nc_get_vara_float failed for file, %s field, %s.\n",
3060  __FILE__, __LINE__, filename, "wavno_hi");
3061  exit(FATAL_ERROR);
3062  }
3063 
3064  nc_close(sds_id);
3065 
3066  if (!(tkcdf = (float *) calloc(n_g * nobs * levels, sizeof (float)))) {
3067  printf("-E- : Error allocating memory to tkcdf\n");
3068  exit(FATAL_ERROR);
3069  }
3070 
3071  if (!(sum_kd = (float *) calloc(nobs, sizeof (float)))) {
3072  printf("-E- : Error allocating memory to sum_kd\n");
3073  exit(FATAL_ERROR);
3074  }
3075 
3076  }
3077 
3078  /*
3079  ! Moved from INIT_SPECAL because it seems more appropriate here. - rjh 01/04/2016
3080  !C Initial water vapor VMRs for repeated use in other subroutines and
3081  !C adjust layered water vapor VMRM with geometrical factors.
3082  */
3083  if (firstCall) printf("RJH: TRAN_CAL - be sure to remove below 2 lines (k_surf--;k_plane--) once final conversion to C is complete\n ");
3084  k_plane--; // RJH - this is a relic of the fortran code - may want change this throughout the code later
3085  k_surf--; // Ditto
3086 
3087  for (i = 0; i < nl; i++) {
3088  vmrm[i] = (vmr[i] + vmr[i + 1]) / (float) 2.0;
3089  /*
3090  Scale the VMRM by the two-way path geometrical factors. The geometric
3091  factors, G_VAP, varies with atmospheric layer number for
3092  aircraft observational geometries.
3093  */
3094  if (splitpaths) { // perform the split path calculations
3095  vmrm_s[0][i] = vmrm[i] * mu0;
3096  if (i < k_plane)
3097  vmrm_s[1][i] = vmrm[i] * mu;
3098  else {
3099  if (i == k_plane)
3100  vmrm_s[1][i] = vmrm[i] * mu * dvap_plane / dvap_layer;
3101  else
3102  vmrm_s[1][i] = 0.;
3103 
3104  }
3105  }
3106  vmrm[i] *= g_vap[i];
3107  }
3108 
3109  if (firstCall || fullcalc) {
3110  // For each water vapor amount, calculate the geometrically adjusted water
3111  // vapor amount, the channel ratios, and the transmittance spectrum.
3112  if (!sumcf && !(sumcf = (float *) calloc(NP_HI, sizeof (float)))) { //FREE
3113  printf("-E- : Error allocating memory to sumcf\n");
3114  exit(FATAL_ERROR);
3115  }
3116  if (splitpaths) {
3117  if (!sumcf_s) {
3118  if (!(sumcf_s = (float **) malloc(2 * sizeof (float*)))) { //FREE
3119  printf("-E- : Error allocating memory to sumcf_s\n");
3120  exit(FATAL_ERROR);
3121  }
3122  for (i = 0; i < 2; i++) {
3123  if (!(sumcf_s[i] = (float *) calloc(NP_HI, sizeof (float)))) { //FREE
3124  printf("-E- : Error allocating memory to sumcf_s\n");
3125  exit(FATAL_ERROR);
3126  }
3127  }
3128  }
3129  }
3130  for (i = 0; i < bands; i++) {
3131  sumcf[i] = 0;
3132  if (splitpaths) {
3133  sumcf_s[0][i] = 0;
3134  sumcf_s[1][i] = 0;
3135  }
3136  for (j = k_surf; j < levels; j++) {
3137  sumcf[i] -= abscf_h2o[bands * j + i] * dp[j - k_surf] * vmrm[j - k_surf];
3138  // printf("sumcf[%d]=%g abscf_h2o[%d][%d]=%g %f %f \n ",i,sumcf[i],j,i,abscf_h2o[bands*j+i],dp[j-k_surf],vmrm[j-k_surf]);
3139  if (splitpaths) {
3140  sumcf_s[0][i] -= abscf_h2o[bands * j + i] * dp[j - k_surf] * vmrm_s[0][j - k_surf];
3141  sumcf_s[1][i] -= abscf_h2o[bands * j + i] * dp[j - k_surf] * vmrm_s[1][j - k_surf];
3142  }
3143  }
3144  }
3145 
3146  if (!tran_hi && !(tran_hi = (float *) malloc(NH2OMAX * NP_HI * sizeof (float *)))) {
3147  printf("-E- : Error allocating memory to tran_hi\n");
3148  exit(FATAL_ERROR);
3149  }
3150 
3151  for (i = 0; i < nh2o; i++) {
3152  for (j = 0; j < bands; j++) {
3153  tran_hi[i * NP_HI + j] = exp(sumcf[j] * ssh2o[i] * Q * (float) 28.966 / (float) 6.0225e+23 / (float) 1.0e-6);
3154  }
3155 
3156  // Total amount of water vapor (in unit of cm) corresponding to the spectrum.
3157 
3158  vaptot[i] = geometry4_.vap_slant_mdl * ssh2o[i];
3159  }
3160 
3161  if (splitpaths) {
3162  for (j = 0; j < 2; j++) {
3163  for (i = 0; i < bands; i++) {
3164  // printf("TRAN_TABLE: SSH2O_S JA: %d %g \n", ja, geometry5_.ssh2o_s[j][ja]);
3165  // printf("TRAN_TABLE: SSH2O_S JA+1: %d %g \n",ja+1,geometry5_.ssh2o_s[j][ja+1]);
3166  // printf("TRAN_TABLE: SSH2O_S JB: %d %g \n", jb, geometry5_.ssh2o_s[j][jb]);
3167  // printf("TRAN_TABLE: SSH2O_S JB+1: %d %g \n",jb+1,geometry5_.ssh2o_s[j][jb+1]);
3168  tran_tables_.tran_hi_sa [j][i] = exp(sumcf_s[j][i] * geometry5_.ssh2o_s[j][ja - 1 ] * Q * (float) 28.966 / (float) 6.0225e+23 / (float) 1.0e-6);
3169  tran_tables_.tran_hi_sap1[j][i] = exp(sumcf_s[j][i] * geometry5_.ssh2o_s[j][ja] * Q * (float) 28.966 / (float) 6.0225e+23 / (float) 1.0e-6);
3170  tran_tables_.tran_hi_sb [j][i] = exp(sumcf_s[j][i] * geometry5_.ssh2o_s[j][jb - 1 ] * Q * (float) 28.966 / (float) 6.0225e+23 / (float) 1.0e-6);
3171  tran_tables_.tran_hi_sbp1[j][i] = exp(sumcf_s[j][i] * geometry5_.ssh2o_s[j][jb] * Q * (float) 28.966 / (float) 6.0225e+23 / (float) 1.0e-6);
3172  }
3173 
3174  }
3175  }
3176  }
3177 
3178  if (!fullcalc) {
3179  // Calculate the k-distrubition coefficients
3180 
3181  if (firstCall) {
3182  //kdist_gas_abs_(tkcdf,abscf_h2o,&nphi,wavno_hi,wavobs,&nobs) ; //FORTRAN
3183  kdistgasabs(tkcdf, abscf_h2o, wavno_hi, wavobs, bands, levels, nobs); //C
3184  }
3185  // Perform the k-distribution calculation Trapezoidal integral for transmittance over the NBANDS bands
3186 
3187  for (i = 0; i < nh2o; i++) {
3188  for (j = 0; j < nobs; j++) tran_table1_.tran_kd[i][j] = 1.0;
3189 
3190  for (j = k_surf; j < levels; j++) {
3191 
3192  //tkcdf[n_g][nobs][levels]
3193  for (n = 0; n < nobs; n++) {
3194  sum_kd[n] = 0.0;
3195  f1 = exp(-tkcdf[0 * nobs * levels + levels * n + j] * dp[j - k_surf] * vmrm[j - k_surf] * ssh2o[i]);
3196 
3197  for (k = 0; k < n_g - 1; k++) {
3198  f2 = exp(-tkcdf[(k + 1) * nobs * levels + levels * n + j] * dp[j - k_surf] * vmrm[j - k_surf] * ssh2o[i]);
3199  sum_kd[n] += (f1 + f2)*(tg[k + 1] - tg[k]) / (float) 2.0;
3200  f1 = f2;
3201  }
3202  tran_table1_.tran_kd[i][n] *= sum_kd[n];
3203  }
3204  }
3205  // Total amount of water vapor (in unit of cm) corresponding to the spectrum.
3206 
3207  vaptot[i] = geometry4_.vap_slant_mdl * ssh2o[i];
3208  }
3209  }
3210 
3211  if (fullcalc || firstCall) {
3212 
3213  // Smooth the high resolution spectra to resolutions of measured spectrum
3214  //tran_smooth_(tran_hi); //FORTRAN
3215  tran_smooth(tran_hi);
3216  if (!fullcalc) {
3217  free(wavno_hi);
3218  free(tran_hi);
3219  }
3220 
3221  }
3222 
3223  for (i = 0; i < nobs; i++) {
3224  tran_table1_.trntblo[i] = 1.0;
3225  tran_table_l2gen_.tg_solo[i] = 1.0;
3226  tran_table_l2gen_.tg_seno[i] = 1.0;
3227  }
3228 
3229  // if (doSmooth) tran_smooth_others_(); //FORTRAN
3230  if (doSmooth) tran_smooth_others();
3231 
3232  if (!fullcalc) {
3233 
3234  if (firstCall)
3235  for (k = 0; k < nobs; k++)
3236  printf("%d ATREM: FAST)TRNTBL=%f %f\n", k, tran_table1_.tran_kd[59][k] * tran_table1_.diff_tran[0][k], tran_table1_.trntblo[k]);
3237 
3238  for (i = 0; i < nh2o; i++) {
3239  for (k = 0; k < nobs; k++) {
3240  /*
3241  Multiplying the sensor resolution water vapor transmittance with combined
3242  transmittances of CO2, N2O, CO, CH4, and O2:
3243  */
3244  tran_table1_.trntbl[i][k] = tran_table1_.tran_kd[i][k] * tran_table1_.diff_tran[i][k] * tran_table1_.trntblo[k];
3245  if (firstCall)
3246  printf("ATREM: DIFF_TRAN: %d %d %f %f %f %f\n", i, k,
3247  tran_table1_.trntbl[i][k], tran_table1_.trntblo[k], tran_table1_.tran_kd[i][k], tran_table1_.diff_tran[i][k]);
3248  }
3249  }
3250 
3251  } else {
3252 
3253  /*
3254  Multiplying the sensor resolution water vapor transmittance with combined
3255  transmittances of CO2, N2O, CO, CH4, and O2:
3256  */
3257  for (k = 0; k < nobs; k++) {
3258  for (i = 0; i < nh2o; i++) {
3259  tran_table1_.trntbl[i][k] *= tran_table1_.trntblo[k];
3260  }
3261 
3262  if (splitpaths) {
3263  tran_table_l2gen_.tg_sol[k] *= tran_table_l2gen_.tg_solo[k];
3264  tran_table_l2gen_.tg_sen[k] *= tran_table_l2gen_.tg_seno[k];
3265  }
3266 
3267  }
3268  }
3269 
3270  //chnlratio_(); // FORTRAN
3271  channelRatio(); // C version
3272 
3273  firstCall = 0;
3274 
3275 
3276 
3277 }
3278 
3279 /* Converted to C from Fortran by R. Healy (richard.healy@nasa.gov) 4/2016
3280  *
3281 !********************************************************************************
3282 !* *
3283 !* Name: TRAN_SMOOTH *
3284 !* Purpose: This program is to smooth the line-by-line high resolution *
3285 !* spectrum to lower resolution spectrum that matches the resolutions *
3286 !* of imaging spectrometer data. *
3287 !* Parameters: none. *
3288 !* Algorithm: The smoothing is done in two stages. The 1st stage is to smooth *
3289 !* the high resolution spectrum to medium resolution spectrum at a *
3290 !* constant FWHM (0.2 nm) and a constant wavelength interval *
3291 !* (0.1 nm). The 2nd stage smoothing is to smooth the medium *
3292 !* resolution spectrum to resolutions of input imaging spectrometer *
3293 !* data. *
3294 !* Globals used: The global variables used are contained in the file *
3295 !* "COMMONS_INC" *
3296 !* Global output: TRNCAL - total transmittances of all gases that match the *
3297 !* resolutions of imaging spectrometers. *
3298 !* Return Codes: none. *
3299 !* *
3300 !********************************************************************************
3301  */
3302 void tran_smooth(float *tran_hi) {
3303 
3304  static int firstCall = 1;
3305 
3306  /*
3307  * Converted to C from Fortran by R. Healy (richard.healy@nasa.gov) 4/2016
3308  *
3309  First stage of smoothing - smooth line-by-line high resolution spectrum with
3310  over 300,000 points (point spacing of 0.05 cm-1) to medium resolution
3311  spectrum (resolution of 0.2 nm and point spacing of 0.1 nm) with about
3312  25,000 points.
3313 
3314  The smoothing of line-by-line spectrum is done in wavenumber domain. For
3315  a spectrum with a constant 0.2 nm resolution in wavelength domain, it has
3316  variable resolution in wavenumber domain. This effect is properly taken
3317  care of in the design of smoothing functions.
3318 
3319  Because the high resolution spectrum is in wavenumber units (cm-1), while
3320  the medium resolution spectrum is in wavelength units, the two kinds of
3321  grids do not automatically match. In order to match the grids, arrays
3322  of INDEX_MED and TRAN_MED_INDEX are specially designed. The desired
3323  medium resolution spectrum, TRAN_MED, at constant 0.1 nm point spacing
3324  and 0.2 nm resolution is obtained through linear interpolation of
3325  TRAN_MED_INDEX array.
3326 
3327  */
3328  int32_t i, j, k, m, n;
3329  float *wavln_med_index = init_speccal13_.wavln_med_index, *fwhm = getinput4_.fwhm, *wavln_std = init_speccal12_.wavln_std;
3330  float *wavobs = getinput4_.wavobs;
3331  static float **finstr_wavno, *fwhm_wavno;
3332  static int32_t ncvhf_wavno[NP_MED], ia[NBANDS], ia_p1;
3333  int32_t ncvtot_wavno, ncvtot, nobs = getinput5_.nobs, *ncvhf = init_speccal15_.ncvhf, *index_med = init_speccal13_.index_med;
3334 
3335  float *tran_med_sa_sol = tran_tables1_.tran_med_sa_sol, *tran_med_sap1_sol = tran_tables1_.tran_med_sap1_sol;
3336  float *tran_med_sa_sen = tran_tables1_.tran_med_sa_sen, *tran_med_sap1_sen = tran_tables1_.tran_med_sap1_sen;
3337  float *tran_med_sb_sol = tran_tables1_.tran_med_sb_sol, *tran_med_sbp1_sol = tran_tables1_.tran_med_sbp1_sol;
3338  float *tran_med_sb_sen = tran_tables1_.tran_med_sb_sen, *tran_med_sbp1_sen = tran_tables1_.tran_med_sbp1_sen;
3339  float *tran_med_index_sa_sol = tran_tables1_.tran_med_index_sa_sol, *tran_med_index_sap1_sol = tran_tables1_.tran_med_index_sap1_sol;
3340  float *tran_med_index_sa_sen = tran_tables1_.tran_med_index_sa_sen, *tran_med_index_sap1_sen = tran_tables1_.tran_med_index_sap1_sen;
3341  float *tran_med_index_sb_sol = tran_tables1_.tran_med_index_sb_sol, *tran_med_index_sbp1_sol = tran_tables1_.tran_med_index_sbp1_sol;
3342  float *tran_med_index_sb_sen = tran_tables1_.tran_med_index_sb_sen, *tran_med_index_sbp1_sen = tran_tables1_.tran_med_index_sbp1_sen;
3343  float *tran_std_sa_sol = tran_tables1_.tran_std_sa_sol, *tran_std_sap1_sol = tran_tables1_.tran_std_sap1_sol;
3344  float *tran_std_sa_sen = tran_tables1_.tran_std_sa_sen, *tran_std_sap1_sen = tran_tables1_.tran_std_sap1_sen;
3345  float *tran_std_sb_sol = tran_tables1_.tran_std_sb_sol, *tran_std_sbp1_sol = tran_tables1_.tran_std_sbp1_sol;
3346  float *tran_std_sb_sen = tran_tables1_.tran_std_sb_sen, *tran_std_sbp1_sen = tran_tables1_.tran_std_sbp1_sen;
3347  float *tg_sol = tran_table_l2gen_.tg_sol, *tg_sen = tran_table_l2gen_.tg_sen;
3348 
3349  float tran_ia[NH2OMAX], tran_iap1[NH2OMAX];
3350  float tran_ia_sa_sol, tran_ia_sa_sen, tran_ia_sap1_sol, tran_ia_sap1_sen;
3351  float tran_iap1_sa_sol, tran_iap1_sa_sen, tran_iap1_sap1_sol, tran_iap1_sap1_sen;
3352  float tran_ia_sb_sol, tran_ia_sb_sen, tran_ia_sbp1_sol, tran_ia_sbp1_sen;
3353  float tran_iap1_sb_sol, tran_iap1_sb_sen, tran_iap1_sbp1_sol, tran_iap1_sbp1_sen;
3354  float sumins, dlt, fj, fjm1, dlt_ia, fia, fia_p1;
3355  float **tran_std, **tran_med;
3356  float tg_sol_a, tg_sen_a, tg_sol_ap1, tg_sen_ap1;
3357  float tg_sol_b, tg_sen_b, tg_sol_bp1, tg_sen_bp1;
3358  float f1a = geometry_l2gen_.f1a, f2a = geometry_l2gen_.f2a;
3359  float f1b = geometry_l2gen_.f1b, f2b = geometry_l2gen_.f2b;
3360  int splitpaths = geometry_l2gen_.splitpaths;
3361  float tmpx;
3362 
3363  int32_t np_std = NP_STD, ndx1, ndx2;
3364 
3365  if (firstCall) {
3366  if (!(fwhm_wavno = (float *) malloc(NP_MED * sizeof (float)))) {
3367  printf("-E- : Error allocating memory to tran_std\n");
3368  exit(FATAL_ERROR);
3369  }
3370  if (!(finstr_wavno = (float **) malloc(NP_MED * sizeof (float*)))) {
3371  printf("-E- : Error allocating memory to tran_std\n");
3372  exit(FATAL_ERROR);
3373  }
3374  for (j = 0; j < NP_MED; j++) {
3375  if (!(finstr_wavno[j] = (float *) malloc(5000 * sizeof (float)))) {
3376  printf("-E- : Error allocating memory to tran_std\n");
3377  exit(FATAL_ERROR);
3378  }
3379  fwhm_wavno[j] = (float) 10000. * DLT_MED / (wavln_med_index[j] * wavln_med_index[j]);
3380  ncvhf_wavno[j] = (FACDLT * fwhm_wavno[j] / DWAVNO + 1.);
3381  ncvtot_wavno = 2 * ncvhf_wavno[j] - 1;
3382 
3383  sumins = 0;
3384  for (i = ncvhf_wavno[j] - 1; i < ncvtot_wavno; i++) {
3385  finstr_wavno[j][i] = exp(-CONST1 * pow((float) (i - ncvhf_wavno[j] + 1) * DWAVNO / fwhm_wavno[j], 2));
3386  sumins += finstr_wavno[j][i];
3387  // if (j==0) printf("A:finstr_wavno sumins: %d %g %g %d\n",i,sumins,finstr_wavno[j][i],i-ncvhf_wavno[j]+1);
3388  }
3389 
3390  for (i = 0; i < ncvhf_wavno[j] - 1; i++) {
3391  finstr_wavno[j][i] = finstr_wavno[j][ncvtot_wavno - i - 1];
3392  sumins += finstr_wavno[j][i];
3393  // if (j==0) printf("B:finstr_wavno sumins: %d %g %g %d\n",i,sumins,finstr_wavno[j][i],ncvtot_wavno-i-1);
3394  }
3395 
3396  sumins *= DWAVNO;
3397 
3398  for (i = 0; i < ncvtot_wavno; i++) {
3399  finstr_wavno[j][i] *= (DWAVNO / sumins);
3400  // printf("RJH: finstr_wavno %d %d %g %g \n",i,j,finstr_wavno[j][i],sumins);
3401  }
3402  }
3403 
3404  // Index searching...
3405  //
3406  //Calculate instrumental response functions...
3407 
3408  for (j = 0; j < nobs; j++) {
3409  sumins = 0.0;
3410  ncvtot = 2 * ncvhf[j] - 1;
3411  for (i = ncvhf[j] - 1; i < ncvtot; i++) {
3412  init_speccal15_.finstr[j][i] = exp(-CONST1 * pow((float) (i - ncvhf[j] + 1) * DWAVLN / fwhm[j], 2));
3413  sumins += init_speccal15_.finstr[j][i];
3414  // if (j==0) printf("c:A:finstr sumins: %d %g %g %d fwhm=%g %g %g %g %g %g\n",i,sumins,init_speccal15_.finstr[j][i],i-ncvhf[j]+1,fwhm[j],DWAVLN,
3415  // (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2),-CONST1*pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2),
3416  // exp(-CONST1*pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2)));
3417  }
3418 
3419  for (i = 0; i < ncvhf[j] - 1; i++) {
3420  init_speccal15_.finstr[j][i] = init_speccal15_.finstr[j][ncvtot - i - 1];
3421  sumins += init_speccal15_.finstr[j][i];
3422  // if (j==0) printf("c:B:finstr sumins: %d %g %g %d\n",i,sumins,init_speccal15_.finstr[j][i],ncvtot-i-1);
3423  }
3424 
3425  sumins *= DWAVLN;
3426 
3427  for (i = 0; i < ncvtot; i++)
3428  init_speccal15_.finstr[j][i] *= (DWAVLN / sumins);
3429 
3430  ia[j] = hunt(wavln_std, np_std, (double) wavobs[j], ia[j]);
3431  }
3432 
3433  firstCall = 0;
3434  }
3435 
3436  if (!(tran_std = (float **) malloc(NH2OMAX * sizeof (float *)))) {
3437  printf("-E- : Error allocating memory to tran_std\n");
3438  exit(FATAL_ERROR);
3439  }
3440  if (!(tran_med = (float **) malloc(NH2OMAX * sizeof (float *)))) {
3441  printf("-E- : Error allocating memory to tran_med\n");
3442  exit(FATAL_ERROR);
3443  }
3444 
3445  for (i = 0; i < NH2OMAX; i++) {
3446  if (!(tran_std[i] = (float *) calloc(NP_STD, sizeof (float *)))) {
3447  printf("-E- : Error allocating memory to tran_std\n");
3448  exit(FATAL_ERROR);
3449  }
3450  if (!(tran_med[i] = (float *) calloc(NP_MED, sizeof (float *)))) {
3451  printf("-E- : Error allocating memory to tran_med\n");
3452  exit(FATAL_ERROR);
3453  }
3454  }
3455  for (j = 0; j < NP_MED; j++) {
3456  for (i = 0; i < NH2OMAX; i++)
3457  init_speccal13_.tran_med_index[i][j] = 0.;
3458  if (splitpaths) {
3459  tran_med_index_sa_sen [j] = 0;
3461  tran_med_index_sb_sen [j] = 0;
3463  tran_med_index_sa_sol [j] = 0;
3465  tran_med_index_sb_sol [j] = 0;
3467  }
3468  ndx1 = index_med[j]-(ncvhf_wavno[j] - 1);
3469  ndx2 = index_med[j] + ncvhf_wavno[j] - 1;
3470 
3471  for (k = ndx1 - 1; k < ndx2; k++) {
3472  for (i = 0; i < NH2OMAX; i++)
3473  init_speccal13_.tran_med_index[i][j] += tran_hi[i * NP_HI + k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3474 
3475 
3476  // if (i==29)
3477  // printf(" TRAN_MED_INDEX: %d %d <%g> %g %g %d %d %d\n",j,k,init_speccal13_.tran_med_index[i][j],tran_hi[i*NP_HI+k],
3478  // finstr_wavno[j][k-index_med[j]+ncvhf_wavno[j]],
3479  // index_med[j],ncvhf_wavno[j],k-index_med[j]+ncvhf_wavno[j]);
3480  if (splitpaths) {
3481  //Note that the tran_hi_* arrays are 0 for solar path and 1 for sensor
3482  tran_med_index_sa_sol [j] += tran_tables_.tran_hi_sa [0][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3483  tran_med_index_sa_sen [j] += tran_tables_.tran_hi_sa [1][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3484  tran_med_index_sap1_sol[j] += tran_tables_.tran_hi_sap1[0][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3485  tran_med_index_sap1_sen[j] += tran_tables_.tran_hi_sap1[1][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3486  tran_med_index_sb_sol [j] += tran_tables_.tran_hi_sb [0][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3487  tran_med_index_sb_sen [j] += tran_tables_.tran_hi_sb [1][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3488  tran_med_index_sbp1_sol[j] += tran_tables_.tran_hi_sbp1[0][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3489  tran_med_index_sbp1_sen[j] += tran_tables_.tran_hi_sbp1[1][k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3490  // if (j==8204) printf("SPLIT: TRAN_MED_INDEX: %d %d <%g> %g %g %d %d %d %g\n",j,k,tran_med_index_sa_sol[j],tran_tables_.tran_hi_sa[0][k],
3491  // finstr_wavno[j][k-index_med[j]+ncvhf_wavno[j]],
3492  // index_med[j],ncvhf_wavno[j],k-index_med[j]+ncvhf_wavno[j],
3493  // tran_tables_.tran_hi_sa [0][k]*finstr_wavno[j][k-index_med[j]+ncvhf_wavno[j]]);
3494  }
3495  }
3496  }
3497  /*
3498  *
3499  Linear interpolation to get TRAN_MED from TRAN_MED_INDEX:
3500  (Note that WAVLN_MED_INDEX(J) >= WAVLN_MED(J) )
3501  *
3502  */
3503  for (i = 0; i < NH2OMAX; i++) {
3504  tran_med[i][0] = init_speccal13_.tran_med_index[i][0];
3505  tran_med[i][NP_MED - 1] = init_speccal13_.tran_med_index[i][NP_MED - 1];
3506  }
3507  if (splitpaths) {
3512 
3517 
3522 
3527  }
3528 
3529  for (j = 1; j < NP_MED - 1; j++) {
3530  if (wavln_med_index[j] <= init_speccal12_.wavln_med[j]) {
3531  for (i = 0; i < NH2OMAX; i++)
3532  tran_med[i][j] = init_speccal13_.tran_med_index[i][j];
3533  // printf(" TRAN_MED_WAVLN: %d %d <%g> <%g> %g %g\n",j,29,tran_med[29][j],init_speccal13_.tran_med_index[29][j],
3534  // wavln_med_index[j],init_speccal12_.wavln_med[j]);
3535  if (splitpaths) {
3544  }
3545  } else {
3547  fjm1 = (wavln_med_index[j] - init_speccal12_.wavln_med[j]) / dlt;
3548  fj = (init_speccal12_.wavln_med [j] - wavln_med_index[j - 1]) / dlt;
3549  for (i = 0; i < NH2OMAX; i++) {
3550  tran_med[i][j] = fjm1 * init_speccal13_.tran_med_index[i][j - 1] + fj * init_speccal13_.tran_med_index[i][j];
3551  // if (i==29)
3552  // printf(" TRAN_MED_INTERP: %d %d <%g> <%g> %g %g %g\n",j,i,init_speccal13_.tran_med_index[i][j-1],init_speccal13_.tran_med_index[i][j],
3553  // fjm1,fj,dlt);
3554  }
3555  if (splitpaths) {
3556  tran_med_sa_sol [j] = fjm1 * tran_med_index_sa_sol [j - 1] + fj * tran_med_index_sa_sol [j];
3557  tran_med_sa_sen [j] = fjm1 * tran_med_index_sa_sen [j - 1] + fj * tran_med_index_sa_sen [j];
3560  tran_med_sb_sol [j] = fjm1 * tran_med_index_sb_sol [j - 1] + fj * tran_med_index_sb_sol [j];
3561  tran_med_sb_sen [j] = fjm1 * tran_med_index_sb_sen [j - 1] + fj * tran_med_index_sb_sen [j];
3564  // printf("SPLIT: TRAN_MED_SA_SOL= %d <%g> <%g %g> %g %g\n",j,tran_med_sa_sol[j],
3565  // fjm1,fj,tran_med_index_sa_sol[j-1],tran_med_index_sa_sol[j]);
3566  }
3567  }
3568  }
3569 
3570  /*
3571  * --- Here multiplying O3 and NO2 spectra and other spectrum at medium resolution:
3572  *
3573  */
3574  for (j = 0; j < NH2OMAX; j++) {
3575  for (i = 0; i < NPSHIF; i++)
3576  tran_std[j][i] = 1.0;
3577  for (i = NPSHIF; i < NP_STD; i++)
3578  tran_std[j][i] = tran_med[j][i - NPSHIF];
3579 
3580  }
3581  if (splitpaths) {
3582  for (i = 0; i < NP_STD; i++) {
3583  tran_std_sa_sol [i] = 1.0;
3584  tran_std_sa_sen [i] = 1.0;
3585  tran_std_sap1_sol[i] = 1.0;
3586  tran_std_sap1_sen[i] = 1.0;
3587  tran_std_sb_sol [i] = 1.0;
3588  tran_std_sb_sen [i] = 1.0;
3589  tran_std_sbp1_sol[i] = 1.0;
3590  tran_std_sbp1_sen[i] = 1.0;
3591  }
3592  for (i = NPSHIF; i < NP_STD; i++) {
3601  // printf("%d TRAN_STD_SA_SOL= %g %g\n",i,tran_std_sa_sol[i],tran_med_sa_sol[i-NPSHIF]);
3602 
3603  }
3604  }
3605  /*
3606  * The 2nd stage of smoothing - smooth the medium resolution spectrum (resolution
3607  of 0.2 nm and point spacing of 0.1 nm) with about 25,000 points to match
3608  the coarser and variable resolution spectrum from imaging spectrometers.
3609 
3610  Initialize some index parameters:
3611 
3612  */
3613 
3614  for (j = 0; j < nobs; j++) {
3615 
3616  for (i = 0; i < NH2OMAX; i++) {
3617  tran_table1_.trntbl[i][j] = 0.0;
3618  tran_ia[i] = 0.0;
3619  tran_iap1[i] = 0.0;
3620  }
3621 
3622  if (splitpaths) {
3623  tg_sol[j] = 0.0;
3624  tg_sen[j] = 0.0;
3625  tran_ia_sa_sol = 0.0;
3626  tran_ia_sa_sen = 0.0;
3627  tran_ia_sap1_sol = 0.0;
3628  tran_ia_sap1_sen = 0.0;
3629  tran_iap1_sa_sol = 0.0;
3630  tran_iap1_sa_sen = 0.0;
3631  tran_iap1_sap1_sol = 0.0;
3632  tran_iap1_sap1_sen = 0.0;
3633  tran_ia_sb_sol = 0.0;
3634  tran_ia_sb_sen = 0.0;
3635  tran_ia_sbp1_sol = 0.0;
3636  tran_ia_sbp1_sen = 0.0;
3637  tran_iap1_sb_sol = 0.0;
3638  tran_iap1_sb_sen = 0.0;
3639  tran_iap1_sbp1_sol = 0.0;
3640  tran_iap1_sbp1_sen = 0.0;
3641 
3642  }
3643 
3644  // Smoothing ...
3645  for (k = ia[j]-(ncvhf[j] - 1); k < ia[j] + ncvhf[j]; k++) {
3646  for (i = 0; i < NH2OMAX; i++) {
3647  tran_ia[i] += tran_std[i][k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3648  // if(i==29) printf("TRAN_IA: %d %d %d %g %g %d %g %d\n",j,k,ia[j],tran_ia[i],tran_std[i][k],k-ia[j]+ncvhf[j]-1,init_speccal15_.finstr[j][k-ia[j]+ncvhf[j]-1],ncvhf[j]);
3649  }
3650  if (splitpaths) {
3651  tran_ia_sa_sol += tran_std_sa_sol [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3652  tran_ia_sa_sen += tran_std_sa_sen [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3653  tran_ia_sap1_sol += tran_std_sap1_sol[k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3654  tran_ia_sap1_sen += tran_std_sap1_sen[k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3655  tran_ia_sb_sol += tran_std_sb_sol [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3656  tran_ia_sb_sen += tran_std_sb_sen [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3657  tran_ia_sbp1_sol += tran_std_sbp1_sol[k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3658  tran_ia_sbp1_sen += tran_std_sbp1_sen[k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
3659  // printf("%d %d TRAN_IA_SA_SOL= %g %g %g %d\n",j,k,tran_ia_sa_sol, tran_std_sa_sol [k],init_speccal15_.finstr[j][k-ia[j]+ncvhf[j]-1],ia[j]);
3660  }
3661  }
3662 
3663  ia_p1 = ia[j] + 1;
3664  for (k = ia_p1 - (ncvhf[j] - 1); k < ia_p1 + ncvhf[j]; k++) {
3665  for (i = 0; i < NH2OMAX; i++) {
3666  tran_iap1[i] += tran_std[i][k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3667  }
3668  if (splitpaths) {
3669  tran_iap1_sa_sol += tran_std_sa_sol [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3670  tran_iap1_sa_sen += tran_std_sa_sen [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3671  tran_iap1_sap1_sol += tran_std_sap1_sol[k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3672  tran_iap1_sap1_sen += tran_std_sap1_sen[k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3673  tran_iap1_sb_sol += tran_std_sb_sol [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3674  tran_iap1_sb_sen += tran_std_sb_sen [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3675  tran_iap1_sbp1_sol += tran_std_sbp1_sol[k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3676  tran_iap1_sbp1_sen += tran_std_sbp1_sen[k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
3677  // printf("%d %d TRAN_IAP1_SA_SOL= %g %g %g\n",j,k,tran_iap1_sa_sol, tran_std_sa_sol [k],init_speccal15_.finstr[j][k-ia[j]+ncvhf[j]-1]);
3678  }
3679  }
3680 
3681  // Linear interpolation to get TRNCAL from TRAN_IA and TRAN_IAP1:
3682  dlt_ia = wavln_std[ia_p1] - wavln_std[ia[j]];
3683  fia = (wavln_std[ia_p1] - wavobs[j]) / dlt_ia;
3684  fia_p1 = (float) 1.0 - fia;
3685 
3686  for (i = 0; i < NH2OMAX; i++)
3687  tran_table1_.trntbl[i][j] = fia * tran_ia[i] + fia_p1 * tran_iap1[i];
3688 
3689  if (splitpaths) {
3690  tg_sol_a = fia * tran_ia_sa_sol + fia_p1*tran_iap1_sa_sol;
3691  tg_sol_ap1 = fia * tran_ia_sap1_sol + fia_p1*tran_iap1_sap1_sol;
3692  tg_sen_a = fia * tran_ia_sa_sen + fia_p1*tran_iap1_sa_sen;
3693  tg_sen_ap1 = fia * tran_ia_sap1_sen + fia_p1*tran_iap1_sap1_sen;
3694 
3695  tg_sol_b = fia * tran_ia_sb_sol + fia_p1*tran_iap1_sb_sol;
3696  tg_sol_bp1 = fia * tran_ia_sbp1_sol + fia_p1*tran_iap1_sbp1_sol;
3697  tg_sen_b = fia * tran_ia_sb_sen + fia_p1*tran_iap1_sb_sen;
3698  tg_sen_bp1 = fia * tran_ia_sbp1_sen + fia_p1*tran_iap1_sbp1_sen;
3699 
3700  tg_sol[j] = (float) 0.5 * (f1a * tg_sol_a + f2a * tg_sol_ap1 +
3701  f1b * tg_sol_b + f2b * tg_sol_bp1);
3702  tg_sen[j] = (float) 0.5 * (f1a * tg_sen_a + f2a * tg_sen_ap1 +
3703  f1b * tg_sen_b + f2b * tg_sen_bp1);
3704  // printf("%d %d TG_SOL_SA= %g %g %g %g %g %g %g <%g %g %g %g>\n",j,ia[j],tg_sol[j],tg_sol_a,tg_sol_ap1,
3705  // tran_ia_sa_sol,tran_iap1_sa_sol,
3706  // tran_ia_sap1_sol,tran_iap1_sap1_sol,
3707  // f1a,f2a,f1b,f2b);
3708  // printf("%d %d TG_SOL_SB= %g %g %g %g %g %g %g <%g %g %g %g>\n",j,ia[j],tg_sol[j],tg_sol_b,tg_sol_bp1,
3709  // tran_ia_sb_sol,tran_iap1_sb_sol,
3710  // tran_ia_sbp1_sol,tran_iap1_sbp1_sol,
3711  // f1a,f2a,f1b,f2b);
3712  }
3713 
3714  if (!getinput5_.full_calc) {
3715  for (k = 0; k < NH2OMAX; k++) {
3716  tran_table1_.diff_tran[k][j] = (tran_table1_.trntbl[k][j] - tran_table1_.tran_kd[k][j]) /
3717  tran_table1_.tran_kd[k][j]+(float) 1.0;
3718  // printf("RJH: TRAN2: %d %d %f %f %f\n",j,k,tran_table1_.tran_kd[k][j],tran_table1_.trntbl[k][j],tran_table1_.diff_tran[k][j]);
3719  }
3720  }
3721  } //nobs
3722 
3723  for (i = 0; i < NH2OMAX; i++) {
3724  free(tran_std[i]);
3725  free(tran_med[i]);
3726  }
3727  free(tran_std);
3728  free(tran_med);
3729 }
3730 
3731 /* Converted to C from Fortran by R. Healy (richard.healy@nasa.gov) 4/2016
3732  *
3733 !********************************************************************************
3734 !* *
3735 !* Name: TRAN_SMOOTH_OTHERS *
3736 !* Purpose: This program is to smooth the line-by-line high resolution *
3737 !* spectrum to lower resolution spectrum that matches the resolutions *
3738 !* of imaging spectrometer data - for other absorbing gases *
3739 !* Parameters: none. *
3740 !* Algorithm: The smoothing is done in two stages. The 1st stage is to smooth *
3741 !* the high resolution spectrum to medium resolution spectrum at a *
3742 !* constant FWHM (0.2 nm) and a constant wavelength interval *
3743 !* (0.1 nm). The 2nd stage smoothing is to smooth the medium *
3744 !* resolution spectrum to resolutions of input imaging spectrometer *
3745 !* data. *
3746 !* Globals used: The global variables used are contained in the file *
3747 !* "COMMONS_INC" *
3748 !* Global output: TRNCAL - total transmittances of all gases that match the *
3749 !* resolutions of imaging spectrometers. *
3750 !* Return Codes: none. *
3751 !* *
3752 !********************************************************************************
3753  */
3755 
3756  static int firstCall = 1;
3757 
3758  /*
3759  * Converted to C from Fortran by R. Healy (richard.healy@nasa.gov) 4/2016
3760  *
3761  First stage of smoothing - smooth line-by-line high resolution spectrum with
3762  over 300,000 points (point spacing of 0.05 cm-1) to medium resolution
3763  spectrum (resolution of 0.2 nm and point spacing of 0.1 nm) with about
3764  25,000 points.
3765 
3766  The smoothing of line-by-line spectrum is done in wavenumber domain. For
3767  a spectrum with a constant 0.2 nm resolution in wavelength domain, it has
3768  variable resolution in wavenumber domain. This effect is properly taken
3769  care of in the design of smoothing functions.
3770 
3771  Because the high resolution spectrum is in wavenumber units (cm-1), while
3772  the medium resolution spectrum is in wavelength units, the two kinds of
3773  grids do not automatically match. In order to match the grids, arrays
3774  of INDEX_MED and TRAN_MED_INDEX are specially designed. The desired
3775  medium resolution spectrum, TRAN_MED, at constant 0.1 nm point spacing
3776  and 0.2 nm resolution is obtained through linear interpolation of
3777  TRAN_MED_INDEX array.
3778 
3779  */
3780  int32_t i, j, k, m, n;
3781  float *wavln_med_index = init_speccal13_.wavln_med_index, *fwhm = getinput4_.fwhm, *wavln_std = init_speccal12_.wavln_std;
3782  float *wavobs = getinput4_.wavobs;
3783  static float **finstr_wavno, *fwhm_wavno;
3784  static int32_t ncvhf_wavno[NP_MED], ia[NBANDS], ia_p1;
3785  int32_t ncvtot_wavno, ncvtot, nobs = getinput5_.nobs, *ncvhf = init_speccal15_.ncvhf, *index_med = init_speccal13_.index_med;
3786 
3787  float *trntblo = tran_table1_.trntblo;
3788  float *tg_solo = tran_table_l2gen_.tg_solo, *tg_seno = tran_table_l2gen_.tg_seno;
3789 
3790  float *tran_hi_others = init_speccal1_.tran_hi_others;
3791  float tran_ia, tran_iap1;
3792  float tran_ias_sol, tran_ias_sen, tran_iap1s_sol, tran_iap1s_sen;
3793  float sumins, dlt, fj, fjm1, dlt_ia, fia, fia_p1;
3794  // Transmittance of medium resolution data
3795  float *tran_std_o, *tran_med_o, *tran_med_index_o;
3796  float *tran_std_os_sol, *tran_std_os_sen;
3797  float *tran_med_os_sol, *tran_med_os_sen, *tran_med_index_os_sol, *tran_med_index_os_sen;
3798  int splitpaths = geometry_l2gen_.splitpaths;
3799  float airmass, airm, mu = geometry5_.mu, mu0 = geometry5_.mu0;
3800  float tran_hi_others_sol, tran_hi_others_sen;
3801 
3802 
3803  int32_t np_std = NP_STD, ndx1, ndx2;
3804 
3805  if (firstCall) {
3806  if (!(fwhm_wavno = (float *) malloc(NP_MED * sizeof (float)))) {
3807  printf("-E- : Error allocating memory to tran_std\n");
3808  exit(FATAL_ERROR);
3809  }
3810  if (!(finstr_wavno = (float **) malloc(NP_MED * sizeof (float*)))) {
3811  printf("-E- : Error allocating memory to tran_std\n");
3812  exit(FATAL_ERROR);
3813  }
3814  for (j = 0; j < NP_MED; j++) {
3815  if (!(finstr_wavno[j] = (float *) malloc(5000 * sizeof (float)))) {
3816  printf("-E- : Error allocating memory to tran_std\n");
3817  exit(FATAL_ERROR);
3818  }
3819 
3820  fwhm_wavno[j] = (float) 10000. * DLT_MED / (wavln_med_index[j] * wavln_med_index[j]);
3821  ncvhf_wavno[j] = (FACDLT * fwhm_wavno[j] / DWAVNO + 1.);
3822  ncvtot_wavno = 2 * ncvhf_wavno[j] - 1;
3823 
3824  sumins = 0;
3825  for (i = ncvhf_wavno[j] - 1; i < ncvtot_wavno; i++) {
3826  finstr_wavno[j][i] = exp(-CONST1 * pow((float) (i - ncvhf_wavno[j] + 1) * DWAVNO / fwhm_wavno[j], 2));
3827  sumins += finstr_wavno[j][i];
3828  // if (j==0) printf("A:finstr_wavno sumins: %d %g %g %d\n",i,sumins,finstr_wavno[j][i],i-ncvhf_wavno[j]+1);
3829  }
3830 
3831  for (i = 0; i < ncvhf_wavno[j] - 1; i++) {
3832  finstr_wavno[j][i] = finstr_wavno[j][ncvtot_wavno - i - 1];
3833  sumins += finstr_wavno[j][i];
3834  // if (j==0) printf("B:finstr_wavno sumins: %d %g %g %d\n",i,sumins,finstr_wavno[j][i],ncvtot_wavno-i-1);
3835  }
3836 
3837  sumins *= DWAVNO;
3838 
3839  for (i = 0; i < ncvtot_wavno; i++) {
3840  finstr_wavno[j][i] *= (DWAVNO / sumins);
3841  // printf("RJH: finstr_wavno %d %d %g %g \n",i,j,finstr_wavno[j][i],sumins);
3842  }
3843  }
3844 
3845  //Calculate instrumental response functions...
3846 
3847  for (j = 0; j < nobs; j++) {
3848  sumins = 0.0;
3849  ncvtot = 2 * ncvhf[j] - 1;
3850  // if (j==0) printf("NCVTOT: %d %d\n",ncvtot,ncvhf[j]);
3851  for (i = ncvhf[j] - 1; i < ncvtot; i++) {
3852  init_speccal15_.finstr[j][i] = exp(-CONST1 * pow((float) (i - ncvhf[j] + 1) * DWAVLN / fwhm[j], 2));
3853  sumins += init_speccal15_.finstr[j][i];
3854  // if (j==0) printf("c:A:finstr sumins: %d %g %g %d fwhm=%g %g %g %g %g %g\n",i,sumins,init_speccal15_.finstr[j][i],i-ncvhf[j]+1,fwhm[j],DWAVLN,
3855  // (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2),-CONST1*pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2),
3856  // exp(-CONST1*pow( (float) (i-ncvhf[j]+1)*DWAVLN/fwhm[j],2)));
3857  }
3858 
3859  for (i = 0; i < ncvhf[j] - 1; i++) {
3860  init_speccal15_.finstr[j][i] = init_speccal15_.finstr[j][ncvtot - i - 1];
3861  sumins += init_speccal15_.finstr[j][i];
3862  // if (j==0) printf("c:B:finstr sumins: %d %g %g %d\n",i,sumins,init_speccal15_.finstr[j][i],ncvtot-i-1);
3863  }
3864 
3865  sumins *= DWAVLN;
3866 
3867  for (i = 0; i < ncvtot; i++)
3868  init_speccal15_.finstr[j][i] *= (DWAVLN / sumins);
3869 
3870  ia[j] = hunt(wavln_std, np_std, (double) wavobs[j], ia[j]);
3871  }
3872 
3873  firstCall = 0;
3874  }
3875 
3876  airmass = 1.0 / mu0 + 1.0 / mu;
3877 
3878  /*
3879  * !!!High resolution transmittances for CO2, N2O, CO, CH4, and O2 should
3880  also be calculated for wavelength start = 0.56 micron.
3881  *
3882  */
3883 
3884  if (!(tran_std_o = (float *) calloc(NP_STD, sizeof (float)))) {
3885  printf("-E- : Error allocating memory to tran_std\n");
3886  exit(FATAL_ERROR);
3887  }
3888  if (!(tran_std_os_sol = (float *) calloc(NP_STD, sizeof (float)))) {
3889  printf("-E- : Error allocating memory to tran_std\n");
3890  exit(FATAL_ERROR);
3891  }
3892  if (!(tran_std_os_sen = (float *) calloc(NP_STD, sizeof (float)))) {
3893  printf("-E- : Error allocating memory to tran_std\n");
3894  exit(FATAL_ERROR);
3895  }
3896  if (!(tran_med_o = (float *) calloc(NP_MED, sizeof (float)))) {
3897  printf("-E- : Error allocating memory to tran_med\n");
3898  exit(FATAL_ERROR);
3899  }
3900  if (!(tran_med_index_o = (float *) calloc(NP_MED, sizeof (float)))) {
3901  printf("-E- : Error allocating memory to tran_med\n");
3902  exit(FATAL_ERROR);
3903  }
3904  if (!(tran_med_os_sol = (float *) calloc(NP_MED, sizeof (float)))) {
3905  printf("-E- : Error allocating memory to tran_med\n");
3906  exit(FATAL_ERROR);
3907  }
3908  if (!(tran_med_os_sen = (float *) calloc(NP_MED, sizeof (float)))) {
3909  printf("-E- : Error allocating memory to tran_med\n");
3910  exit(FATAL_ERROR);
3911  }
3912  if (!(tran_med_index_os_sol = (float *) calloc(NP_MED, sizeof (float)))) {
3913  printf("-E- : Error allocating memory to tran_med\n");
3914  exit(FATAL_ERROR);
3915  }
3916  if (!(tran_med_index_os_sen = (float *) calloc(NP_MED, sizeof (float)))) {
3917  printf("-E- : Error allocating memory to tran_med\n");
3918  exit(FATAL_ERROR);
3919  }
3920 
3921  for (j = 0; j < NP_MED; j++) {
3922  ndx1 = index_med[j]-(ncvhf_wavno[j] - 1);
3923  ndx2 = index_med[j] + ncvhf_wavno[j] - 1;
3924 
3925  //printf(" NDX1,NDX2= %d %d %d %d\n",ndx1,ndx2,index_med[j],ncvhf_wavno[j]);
3926  for (k = ndx1 - 1; k < ndx2; k++) {
3927  tran_med_index_o[j] += tran_hi_others[k] * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3928 
3929  // printf(" TRAN_MED_INDEX_O: %d %d <%g> %g %g %d %d %d %g\n",j,k,tran_med_index_o[j],tran_hi_others[k],
3930  // finstr_wavno[j][k-index_med[j]+ncvhf_wavno[j]],
3931  // index_med[j],ncvhf_wavno[j],k-index_med[j]+ncvhf_wavno[j],tran_hi_others[k]*finstr_wavno[j][k-index_med[j]+ncvhf_wavno[j]]);
3932  if (splitpaths) {
3933  //Note that the tran_hi_* arrays are 0 for solar path and 1 for sensor
3934  airm = -(float) log(tran_hi_others[k]) / airmass;
3935  tran_hi_others_sol = (float) exp(-airm / mu0);
3936  tran_hi_others_sen = (float) exp(-airm / mu);
3937  tran_med_index_os_sol[j] += tran_hi_others_sol * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3938  tran_med_index_os_sen[j] += tran_hi_others_sen * finstr_wavno[j][k - index_med[j] + ncvhf_wavno[j]];
3939 
3940  }
3941  }
3942  }
3943  /*
3944  *
3945  Linear interpolation to get TRAN_MED from TRAN_MED_INDEX:
3946  (Note that WAVLN_MED_INDEX(J) >= WAVLN_MED(J) )
3947  *
3948  */
3949  tran_med_o[0] = tran_med_index_o[0];
3950  tran_med_o[NP_MED - 1] = tran_med_index_o[NP_MED - 1];
3951 
3952  if (splitpaths) {
3953  tran_med_os_sol[0] = tran_med_index_os_sol[0];
3954  tran_med_os_sol[NP_MED - 1] = tran_med_index_os_sol[NP_MED - 1];
3955  tran_med_os_sen[0] = tran_med_index_os_sen[0];
3956  tran_med_os_sen[NP_MED - 1] = tran_med_index_os_sen[NP_MED - 1];
3957  }
3958 
3959  for (j = 1; j < NP_MED - 1; j++) {
3960  if (wavln_med_index[j] <= init_speccal12_.wavln_med[j]) {
3961  tran_med_o[j] = tran_med_index_o[j];
3962  // printf(" TRAN_MED_WAVLN: %d <%g> <%g> %g %g\n",j,tran_med_o[j],tran_med_index_o][j],
3963  // wavln_med_index[j],init_speccal12_.wavln_med[j]);
3964  if (splitpaths) {
3965  tran_med_os_sol[j] = tran_med_index_os_sol[j];
3966  tran_med_os_sen[j] = tran_med_index_os_sen[j];
3967  }
3968  } else {
3970  fjm1 = (wavln_med_index[j] - init_speccal12_.wavln_med[j]) / dlt;
3971  fj = (init_speccal12_.wavln_med [j] - wavln_med_index[j - 1]) / dlt;
3972  tran_med_o[j] = fjm1 * tran_med_index_o[j - 1] + fj * tran_med_index_o[j];
3973  // printf(" TRAN_MED_INTERP: %d <%g> <%g> %g %g %g\n",j,tran_med_index_o[j-1],tran_med_index_o[j],
3974  // fjm1,fj,dlt);
3975  if (splitpaths) {
3976  tran_med_os_sol[j] = fjm1 * tran_med_index_os_sol[j - 1] + fj * tran_med_index_os_sol[j];
3977  tran_med_os_sen[j] = fjm1 * tran_med_index_os_sen[j - 1] + fj * tran_med_index_os_sen[j];
3978  // printf(" TRAN_MED_INTERP_OS: %d <%g> <%g> %g %g %g\n",j,tran_med_index_os_sol[j-1],tran_med_index_os_sol[j],
3979  // fjm1,fj,dlt);
3980  }
3981  }
3982  }
3983 
3984  /*
3985  * --- Here multiplying O3 and NO2 spectra and other spectrum at medium resolution:
3986  *
3987  */
3988 
3989  for (i = 0; i < NP_STD; i++) tran_std_o[i] = 1.0;
3990 
3991  if (splitpaths) {
3992  for (i = 0; i < NP_STD; i++) {
3993  tran_std_os_sol[i] = 1.0;
3994  tran_std_os_sen[i] = 1.0;
3995  }
3996  }
3997 
3998  for (i = 0; i < NO3PT; i++) tran_std_o[i] = init_speccal16_.tran_o3_std[i] * init_speccal17_.tran_no2_std[i];
3999 
4000  if (splitpaths) {
4001  for (i = 0; i < NO3PT; i++) {
4002  airm = -(float) log(tran_std_o[i]) / airmass;
4003  tran_std_os_sol[i] = (float) exp(-airm / mu0);
4004  tran_std_os_sen[i] = (float) exp(-airm / mu);
4005  }
4006  }
4007 
4008  for (i = NPSHIF; i < NP_STD; i++) tran_std_o[i] *= tran_med_o[i - NPSHIF];
4009 
4010  if (splitpaths) {
4011  for (i = NPSHIF; i < NP_STD; i++) {
4012  tran_std_os_sol[i] *= tran_med_os_sol[i - NPSHIF];
4013  tran_std_os_sen[i] *= tran_med_os_sen[i - NPSHIF];
4014  // printf("%d TRAN_STD_OS_SOL= %g %g\n",i,tran_std_os_sol[i],tran_med_os_sol[i-NPSHIF]);
4015  // printf("%d TRAN_STD_OS_SEN= %g %g\n",i,tran_std_os_sen[i],tran_med_os_sen[i-NPSHIF]);
4016  }
4017  }
4018 
4019  /*
4020  * The 2nd stage of smoothing - smooth the medium resolution spectrum (resolution
4021  of 0.2 nm and point spacing of 0.1 nm) with about 25,000 points to match
4022  the coarser and variable resolution spectrum from imaging spectrometers.
4023 
4024  Initialize some index parameters:
4025 
4026  */
4027 
4028  for (j = 0; j < nobs; j++) {
4029 
4030  tran_ia = 0.0;
4031  tran_iap1 = 0.0;
4032 
4033  if (splitpaths) {
4034  tran_ias_sol = 0.0;
4035  tran_iap1s_sol = 0.0;
4036  tran_ias_sen = 0.0;
4037  tran_iap1s_sen = 0.0;
4038  }
4039 
4040  // Smoothing ...
4041  for (k = ia[j]-(ncvhf[j] - 1); k < ia[j] + ncvhf[j]; k++) {
4042  tran_ia += tran_std_o[k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
4043  // printf("TRAN_IA: %d %d %d %g %g %d %g %d\n",j,k,ia[j],tran_ia,tran_std_o[k],k-ia[j]+ncvhf[j]-1,init_speccal15_.finstr[j][k-ia[j]+ncvhf[j]-1],ncvhf[j]);
4044 
4045  if (splitpaths) {
4046  tran_ias_sol += tran_std_os_sol [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
4047  tran_ias_sen += tran_std_os_sen [k] * init_speccal15_.finstr[j][k - ia[j] + ncvhf[j] - 1];
4048  // printf("TRAN_IAS_SOL: %d %d %g %g %d %g %d %d\n",j,k,tran_ias_sol,tran_std_os_sol[k],k-ia[j]+ncvhf[j]-1,mu0,ia[j],ncvhf[j]);
4049  // printf("TRAN_IAS_SEN: %d %d %g %g %d %g %d %d\n",j,k,tran_ias_sen,tran_std_os_sen[k],k-ia[j]+ncvhf[j]-1,mu,ia[j],ncvhf[j]);
4050  }
4051  }
4052 
4053  ia_p1 = ia[j] + 1;
4054  for (k = ia_p1 - (ncvhf[j] - 1); k < ia_p1 + ncvhf[j]; k++) {
4055  tran_iap1 += tran_std_o[k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
4056  if (splitpaths) {
4057  tran_iap1s_sol += tran_std_os_sol [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
4058  tran_iap1s_sen += tran_std_os_sen [k] * init_speccal15_.finstr[j][k - ia_p1 + ncvhf[j] - 1];
4059  }
4060  }
4061 
4062  // Linear interpolation to get TRNCAL from TRAN_IA and TRAN_IAP1:
4063  dlt_ia = wavln_std[ia_p1] - wavln_std[ia[j]];
4064  fia = (wavln_std[ia_p1] - wavobs[j]) / dlt_ia;
4065  fia_p1 = (float) 1.0 - fia;
4066 
4067  trntblo[j] = fia * tran_ia + fia_p1*tran_iap1;
4068 
4069  if (splitpaths) {
4070 
4071  tg_solo[j] = fia * tran_ias_sol + fia_p1*tran_iap1s_sol;
4072  tg_seno[j] = fia * tran_ias_sen + fia_p1*tran_iap1s_sen;
4073  // printf("TG_SOLO: %d %g %g %g %g %g\n",j,tg_solo[j],tran_ias_sol,tran_iap1s_sol,fia,fia_p1);
4074  // printf("TG_SENO: %d %g %g %g %g %g\n",j,tg_seno[j],tran_ias_sen,tran_iap1s_sen,fia,fia_p1);
4075  }
4076  }
4077 
4078  free(tran_std_o);
4079  free(tran_med_o);
4080  free(tran_std_os_sol);
4081  free(tran_std_os_sen);
4082  free(tran_med_index_o);
4083  free(tran_med_os_sol);
4084  free(tran_med_os_sen);
4085  free(tran_med_index_os_sol);
4086  free(tran_med_index_os_sen);
4087 }
float clmvapp
Definition: atrem_corl1.h:178
float tran_std_sap1_sol[NP_STD]
float tg_seno[NBANDS]
Definition: atrem_corl1.h:127
#define ATREM_N2O
Definition: atrem_corl1.h:28
float tg_sen[NBANDS]
Definition: atrem_corl1.h:127
float f1a
Definition: atrem_corl1.h:229
void ecdf_(float *xcdf, float *ycdf, int32_t *bin_number, float *xs, int32_t *sample_size)
Definition: numerical.c:22
float f1b
Definition: atrem_corl1.h:229
data_t q
Definition: decode_rs.h:74
integer, parameter int16
Definition: cubeio.f90:3
float tran_hi_others[NP_HI]
int32_t ist4
Definition: atrem_cor.h:110
data_t t[NROOTS+1]
Definition: decode_rs.h:77
float tran_std_sbp1_sen[NP_STD]
float tran_std_sb_sen[NP_STD]
int32_t co
Definition: atrem_corl1.h:118
#define RAD_DEG
Definition: atrem_corl1v2.h:48
struct @25 getinput4_
#define H2O_BIT
Definition: l12_parms.h:60
int32_t hunt(float *xx, int32_t n, double x, int32_t jlo)
int j
Definition: decode_rs.h:73
float wavln_med_index[NP_MED]
int32_t day
int32_t ied4
Definition: atrem_cor.h:110
float dvap_layer
Definition: atrem_corl1.h:178
float tran_med_index_sa_sol[NP_MED]
int splitpaths
Definition: atrem_corl1.h:228
#define CONST1
Definition: atrem_corl1v2.h:49
int status
Definition: l1_czcs_hdf.c:32
struct @24 getinput3_
float dp_layer
Definition: atrem_corl1.h:178
struct @22 input_l2gen_
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
float go3
int32_t nl
Definition: atrem_corl1.h:132
#define NO3PT
Definition: atrem_corl1v2.h:22
struct @31 model_adj1_
int32_t o3
Definition: atrem_corl1.h:118
int32_t ncvhf[NBANDS]
struct @77 geometry1_
struct @85 no2cf_init1_
float f1(float x)
list levels
Definition: mapgen.py:180
float wndow4
Definition: atrem_corl1.h:153
float hp[MODELMAX]
Definition: atrem_corl1.h:173
int32_t co2
Definition: atrem_corl1.h:118
int32_t nh2o
Definition: atrem_cor.h:102
float totlo3
#define NULL
Definition: decode_rs.h:63
float sno2
Definition: atrem_corl1.h:133
float tran_med_sbp1_sen[NP_MED]
#define NP_STD
Definition: atrem_corl1v2.h:27
struct @9 tran_table1_
read l1rec
float wndow1
Definition: atrem_corl1.h:153
float wndow2
Definition: atrem_corl1.h:153
#define CO2_BIT
Definition: l12_parms.h:58
#define DLT_MED
Definition: atrem_corl1v2.h:35
void channelRatio()
float tran_med_index_sa_sen[NP_MED]
float wavln_std[NP_STD]
float wt4
Definition: atrem_cor.h:114
struct @75 init_speccal17_
int32_t nb4
Definition: atrem_cor.h:98
int init_tpvmr(int model)
float tran_med_index_sb_sol[NP_MED]
float mu
struct @65 init_speccal5_
float h[MODELMAX]
Definition: atrem_corl1.h:131
float * lat
int32_t iedp94
Definition: atrem_cor.h:106
float tm[MODELMAX]
#define O3_BIT
Definition: l12_parms.h:57
float vaptot[TBLMAX]
Definition: atrem_cor.h:128
int init_tpvmr_nc(int model)
int32_t nbp94
Definition: atrem_cor.h:98
float tran_med_index_sap1_sen[NP_MED]
int getModelNum(float lat, int32_t day)
int get_angle_limits(float **anglelimit, float **insenz, float **insolz, int *n_senz, int *n_solz)
float xpss
Definition: atrem_corl1.h:165
float vmrm[MODELMAX]
struct @46 debug_atrem
float tran_med_sa_sol[NP_MED]
float tran_med_sb_sol[NP_MED]
float fwhm[NBANDS]
Definition: atrem_corl1.h:144
float trntblo[NBANDS]
struct @30 getinput14_
struct @4 init_speccal6_
@ Nbands
Definition: hybrid.c:24
float vrto3
Definition: atrem_corl1.h:133
float clmvap
Definition: atrem_corl1.h:169
float tp[MODELMAX]
Definition: atrem_corl1.h:173
float tran_med_sbp1_sol[NP_MED]
float tran_med_index_sbp1_sen[NP_MED]
int32_t nobs
Definition: atrem_cor.h:93
instr * input
character(len=1000) if
Definition: names.f90:13
void model_adjust()
#define MODELMAX
Definition: atrem_corl1.h:20
int32_t h2o
Definition: atrem_corl1.h:118
void locate_pos_(float *xx, int32_t *n1, float *x1, int32_t *jj)
float rno2cf[NO2PT]
struct @81 geometry5_
int jb
Definition: atrem_corl1.h:227
float f2(float y)
float dp_plane
Definition: atrem_corl1.h:178
float tran_std_sa_sen[NP_STD]
int bindex_get(int32_t wave)
Definition: windex.c:45
void get_tpvmr(size_t layers, size_t models, int sds_id, char filename[FILENAME_MAX], char *varname, float *var_a)
float dlt2
Definition: atrem_cor.h:94
float ggeom
#define NPSHIF
Definition: atrem_corl1v2.h:29
struct @6 init_speccal8_
int32_t no2
Definition: atrem_corl1.h:118
#define ATREM_NO2
Definition: atrem_corl1.h:24
float f2a
Definition: atrem_corl1.h:229
float linterp(float xin[], float yin[], int32_t nin, float xout)
Definition: lspline.c:59
int get_atrem_cor(int32_t sensorID, l1str *l1rec, int32_t ip, float *rhot, float *tg_tot, float *tg_sol, float *tg_sen)
#define NH2OMAX
Definition: atrem_corl1.h:17
struct @21 getinput1_
int32_t nb1
Definition: atrem_cor.h:98
struct @33 model_adj3_
struct @7 init_speccal10_
float tran_std_sbp1_sol[NP_STD]
void get_abscf_data(int levels, int bands, int sds_id, char filename[FILENAME_MAX], float *abscf, char *varname)
#define ATREM_O3
Definition: atrem_corl1.h:22
int32_t nb2
Definition: atrem_cor.h:98
#define ATREM_CO
Definition: atrem_corl1.h:25
float vmrp[MODELMAX]
Definition: atrem_corl1.h:173
struct @1 getinput5_
int32_t ied1p14
Definition: atrem_cor.h:110
#define FACDLT
Definition: atrem_corl1v2.h:36
int init_atrem(int32_t sensorID, paramstr *P, l1str *l1rec, int32_t nbands)
float tg_sol[NBANDS]
Definition: atrem_corl1.h:127
float pp[MODELMAX]
Definition: atrem_corl1.h:173
float tran_std_sa_sol[NP_STD]
struct @34 model_adj4_
struct @50 tran_tables_
#define NO2_BIT
Definition: l12_parms.h:59
#define FATAL_ERROR
Definition: swl0_parms.h:5
float w1p14c
Definition: atrem_corl1.h:153
float solzni
const double delta
int32_t istp94
Definition: atrem_cor.h:106
#define DWAVNO
Definition: atrem_corl1v2.h:34
float dp[MODELMAX]
float tran_med_sap1_sen[NP_MED]
void unix2yds(double usec, short *year, short *day, double *secs)
float get_current_angle_limit(float insenz, float insolz, int *ii, int *jj, float **anglelimit, float *senz, float *solz, int n_senz, int n_solz)
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
float tran_med_index_sap1_sol[NP_MED]
int32_t o2
Definition: atrem_corl1.h:118
float ja
Definition: atrem_cor.h:114
int32_t iaer
Definition: atrem_corl1.h:132
float ssh2o[NH2OMAX]
float tran_med_sap1_sol[NP_MED]
#define ATREM_CH4
Definition: atrem_corl1.h:26
#define NP_HI
Definition: atrem_corl1v2.h:25
struct @43 geometry4_
int32_t ist1
Definition: atrem_cor.h:106
float wt2
Definition: atrem_cor.h:114
float wp94c
Definition: atrem_corl1.h:153
float tran_std_sb_sol[NP_STD]
void tran_table()
int32_t findMatch(float *list, int32_t nobs, float elem)
float dvap_plane
Definition: atrem_corl1.h:178
void get_input_()
struct @74 init_speccal16_
int32_t index_med[NP_MED]
float pm[MODELMAX]
float finst2[FINSTMAX]
Definition: atrem_cor.h:120
struct @51 tran_tables1_
#define ATREM_O2
Definition: atrem_corl1.h:27
struct @78 geometry2_
struct @44 geometry_l2gen_
struct @63 init_speccal1_
int32_t nbands
struct @27 getinput6_
int32_t k_plane
Definition: atrem_corl1.h:177
#define fabs(a)
Definition: misc.h:93
float vmr[MODELMAX]
Definition: atrem_corl1.h:131
Extra metadata that will be written to the HDF4 file l2prod rank
int32_t ist2
Definition: atrem_cor.h:106
float obszni
void init_spectral_calculations()
float xppp
Definition: atrem_corl1.h:165
float wt3
Definition: atrem_cor.h:114
float mu0
float hsurf
Definition: atrem_cor.h:94
int32_t ied1
Definition: atrem_cor.h:106
struct @10 geometry3_
float tran_std_sap1_sen[NP_STD]
int32_t ch4
Definition: atrem_corl1.h:118
struct @71 init_speccal12_
float wavobs[NBANDS]
Definition: atrem_corl1.h:144
struct @45 tpvmr_init1_
struct @23 tran_table_l2gen_
float wndow3
Definition: atrem_corl1.h:153
int32_t rdatreminfo(int32_t sensorID, int32_t evalmask, const char *pname, void **pval)
Definition: rdatreminfo.c:38
float tran_med_sa_sen[NP_MED]
int32_t model
Definition: atrem_corl1.h:132
#define VSTART
Definition: atrem_corl1v2.h:31
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
void apply_gas_trans(int32_t k_surf, int levels, int bands, float *abscf, float *dp, float *vmrm, float *tran_hi)
float dlt
Definition: atrem_cor.h:94
struct @29 getinput8_
struct @3 init_speccal3_
int32_t ied3
Definition: atrem_cor.h:110
float tran_med_index_sb_sen[NP_MED]
#define ATREM_CO2
Definition: atrem_corl1.h:23
float g_vap
Definition: atrem_cor.h:132
#define DWAVLN
Definition: atrem_corl1v2.h:33
int i
Definition: decode_rs.h:71
struct @8 init_speccal11_
void tran_smooth_others()
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
float wt1
Definition: atrem_cor.h:114
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:97
int32_t nb1p14
Definition: atrem_cor.h:98
float tran_med_sb_sen[NP_MED]
int32_t ied2
Definition: atrem_cor.h:106
struct @5 init_speccal7_
int32_t k_surf
Definition: atrem_corl1.h:182
#define NO2PT
Definition: atrem_corl1v2.h:23
struct @72 init_speccal13_
int32_t ist1p14
Definition: atrem_cor.h:110
@ NBANDS
Definition: make_L3_v1.1.c:53
int k
Definition: decode_rs.h:73
struct @73 init_speccal15_
#define NH2OMAXM1
Definition: atrem_corl1.h:18
float get_atrem(float *tg_tot, float *rhot, paramstr *P)
void geometry()
int32_t nb3
Definition: atrem_cor.h:98
float p[MODELMAX]
Definition: atrem_corl1.h:131
float tran_med_index_sbp1_sol[NP_MED]
float tg_solo[NBANDS]
Definition: atrem_corl1.h:127
struct @2 getinput7_
float o3cf[NO3PT]
int32_t ist3
Definition: atrem_cor.h:110
float f2b
Definition: atrem_corl1.h:229
int32_t nb
Definition: atrem_corl1.h:132
int32_t n2o
Definition: atrem_corl1.h:118
float obsphi
#define NP_MED
Definition: atrem_corl1v2.h:26
void kdistgasabs(float *kcdf, float *abscf, float *waveno, float *wavobs, int32_t nphi, int32_t n_layers, int32_t nbands)
void tran_smooth(float *tran_hi)
int count
Definition: decode_rs.h:79