OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_par.c
Go to the documentation of this file.
1 /* --------------------------------------------------------------- */
2 /* get_par.c - computes photosynthetically active radiation */
3 /* */
4 /* Inputs: */
5 /* l2rec - level-2 structure containing one complete scan */
6 /* after atmospheric correction. */
7 /* Outputs: */
8 /* par - Photosynthetically Active Radiation just above the */
9 /* surface from SeaWiFS level 1b instantaneous */
10 /* radiances at 412, 443, 490, 510, 555, and 670 nm. */
11 /* */
12 /* Algorithm Provided By: Robert Frouin, */
13 /* Scripps Institution of Oceanography */
14 /* */
15 /* Written By: B. A. Franz, SAIC GSC, SIMBIOS, 30 July 1999 */
16 /* Modified: */
17 /* Fall 2013, Robert Lossing, SAIC - Adapted underlying code to C */
18 /* --------------------------------------------------------------- */
19 
20 #include <stdlib.h>
21 #include <math.h>
22 #include "l12_proto.h"
23 #include "smi_climatology.h"
24 #include "par_utils.h"
25 
26 static int* alloc_bindx(int nbands, int* bindx) {
27  if ((bindx = (int *) calloc(nbands, sizeof (int))) == NULL) {
28  printf("-E- : Error allocating memory to bindx in get_par\n");
29  exit(FATAL_ERROR);
30  }
31  return bindx;
32 }
33 
34 void get_par(l2str *l2rec, float par[]) {
35  int32_t ip, ib, ipb, iw;
36 
37  float *Lt;
38 
39  float angst;
40  float taua;
41 
42  static int32_t mask = SEAICE | LAND | HIGLINT | NAVFAIL;
43 
44  static float *lambda;
45  static float *Fobar;
46  static float *Taur;
47  static float *kO3;
48  static int *bindx;
49  static int nwave;
50  static int firstCall = TRUE;
51 
52  l1str *l1rec = l2rec->l1rec;
53  filehandle *l1file = l1rec->l1file;
54 
55  if (firstCall) {
56 
57  firstCall = FALSE;
58 
59  int16_t year, day;
60  double sec;
61  unix2yds(l2rec->l1rec->scantime, &year, &day, &sec);
62 
63  /* Initialize climatologies */
64  smi_climatology_init(input->alphafile, day, ALPHA510);
66 
67  switch (l1file->sensorID) {
68 
69  case MODISA:
70  case MODIST:
71  nwave = 3;
72  bindx = alloc_bindx(nwave, bindx);
73  bindx[0] = 2;
74  bindx[1] = 6;
75  bindx[2] = 7;
76  break;
77  case SEAWIFS:
78  nwave = 6;
79  bindx = alloc_bindx(nwave, bindx);
80  for (ib = 0; ib < nwave; ib++)
81  bindx[ib] = ib;
82  break;
83  case VIIRSN:
84  case VIIRSJ1:
85  nwave = 5;
86  bindx = alloc_bindx(nwave, bindx);
87  for (ib = 0; ib < nwave; ib++)
88  bindx[ib] = ib;
89  break;
90  case MERIS:
91  nwave = 7;
92  bindx = alloc_bindx(nwave, bindx);
93  for (ib = 0; ib < nwave; ib++)
94  bindx[ib] = ib;
95  break;
96  case OCTS:
97  nwave = 6;
98  bindx = alloc_bindx(nwave, bindx);
99  for (ib = 0; ib < nwave; ib++)
100  bindx[ib] = ib;
101  break;
102  default:
103  printf("PAR not supported for this sensor (%d).\n", l1file->sensorID);
104  exit(1);
105  break;
106  }
107  if ((lambda = (float *) calloc(nwave, sizeof (float))) == NULL) {
108  printf("-E- : Error allocating memory to lambda in get_par\n");
109  exit(FATAL_ERROR);
110  }
111  if ((Fobar = (float *) calloc(nwave, sizeof (float))) == NULL) {
112  printf("-E- : Error allocating memory to Fobar in get_par\n");
113  exit(FATAL_ERROR);
114  }
115  if ((Taur = (float *) calloc(nwave, sizeof (float))) == NULL) {
116  printf("-E- : Error allocating memory to Taur in get_par\n");
117  exit(FATAL_ERROR);
118  }
119  if ((kO3 = (float *) calloc(nwave, sizeof (float))) == NULL) {
120  printf("-E- : Error allocating memory to kO3 in get_par\n");
121  exit(FATAL_ERROR);
122  }
123 
124  /* Get band-pass dependent quantities */
125  // consider passing in an array of band indexes to index l2rec->(lambda,k03,Fobar,Taur) in calc_par
126  for (iw = 0; iw < nwave; iw++) {
127  ib = bindx[iw];
128  lambda[iw] = l1file->fwave[ib];
129  kO3[iw] = l1file->k_oz[ib];
130  Fobar[iw] = l1file->Fobar[ib];
131  Taur[iw] = l1file->Tau_r[ib];
132  }
133  }
134  if ((Lt = (float *) calloc(nwave, sizeof (float))) == NULL) {
135  printf("-E- : Error allocating memory to Lt in get_par\n");
136  exit(FATAL_ERROR);
137  }
138 
139  for (ip = 0; ip < l1rec->npix; ip++) {
140 
141  /* Grab radiances for this pixel */
142  for (ib = 0; ib < nwave; ib++) {
143  ipb = ip * l1file->nbands + bindx[ib];
144  Lt[ib] = l1rec->Lt[ipb];
145  }
146 
147  /* Skip pixel if masked */
148  if (Lt[0] <= 0.0 || (l1rec->flags[ip] & mask) != 0
149  || l1rec->solz[ip] > 90.0) {
150  par[ip] = BAD_FLT;
151  l1rec->flags[ip] |= PRODFAIL;
152  continue;
153  }
154 
155  /* Get angstrom and AOT from climatology */
156  angst = smi_climatology(l1rec->lon[ip], l1rec->lat[ip], ALPHA510);
157  taua = smi_climatology(l1rec->lon[ip], l1rec->lat[ip], TAUA865);
158 
159  switch (l1file->sensorID) {
160 
161  case SEAWIFS:
162  case MODIST:
163  case MODISA:
164  case MERIS:
165  case VIIRSN:
166  case VIIRSJ1:
167  case OCTS:
168 
169  par[ip] = calc_par(l2rec, ip, nwave, Lt, taua, angst, lambda,
170  Fobar, kO3, Taur);
171  break;
172 
173  default:
174  printf("PAR not supported for this sensor (%d).\n", l1file->sensorID);
175  exit(1);
176  break;
177  }
178  /* Convert to E/D/m^2 */
179  if (par[ip] != BAD_FLT)
180  par[ip] *= 1.193;
181 
182  }
183  free(Lt);
184 }
185 
186 /*
187  Subject:
188  PAR routine
189  Date:
190  Fri, 23 Jul 1999 08:55:29 -0700
191  From:
192  Robert Frouin <rfrouin@ucsd.edu>
193  To:
194  chuck@seawifs, gfargion@simbios, gene@seawifs, wang@simbios, franz@seawifs
195  CC:
196  jmcpherson@ucsd.edu
197 
198 
199 
200 
201  Greetings:
202 
203  A routine to compute daily PAR from SeaWiFS level 1b radiances is available
204  at the following address: http://genius.ucsd.edu/~john/SeaWiFS_dir/ under
205  the rubrique "PAR subroutine and test program".
206 
207  The routine requires as input year, month, day, time, latitude, longitude,
208  SeaWiFS radiances in the first 6 spectral bands, solar zenith angle,
209  viewing zenith angle, relative azimuth angle, aerosol optical thickness at
210  865 nm, Angstrom coefficient, ozone amount, and surface pressure. Routine
211  output is daily PAR.
212 
213  Thus a daily PAR value is computed for each instantaneous SeaWiFS
214  observation, clear or cloudy. Diurnal variations are taken into account
215  statistically. The algorithm is described succintly in the routine.
216 
217  During our discussion at GSFC in June, a first routine was supposed to be
218  developed to provide a normalized cloud/surface albedo and then a second
219  routine to compute daily PAR from the normalized albedo, and the second
220  routine was to be applied when binning to the 9 km resolution. Now daily
221  PAR is obtained using a single routine, which is more convenient.
222 
223  The binning to the 9 km resolution should be done as follows. First,
224  weight-average the daily PAR estimates obtained from all SeaWiFS
225  observations during the same day at each location (there might be several
226  SeaWiFS observations of a surface target during the same day). The weight
227  is the cosine of the sun zenith angle for the SeaWiFS observation. That is:
228 
229  PAR_avg = sum{cos[tetas(i)]*PAR(i)}/sum{cos[tetas(i)]}
230 
231  Second, simply average the values at all the locations within the 9 km bins.
232 
233  The routine requires aerosol data, ozone amount, surface pressure. If these
234  parameters are missing (-999 or less), default values are used. If Eric
235  Vermote's aerosol climatology (or Menghua's) is not available yet, please
236  use default values for tests.
237 
238  At this time, the statistical diurnal function does not depend on latitude,
239  longitude, and date, but will depend on these parameters in the second
240  version of the code. Creating a date and location dependent function
241  requires analysing several years of ISCCP data. We have the data, but a
242  couple of weeks is needed to accomplish the task.
243 
244  I will present the algorithm at the SeaWiFS atmospheric correction meeting
245  next week, and prepare a detailed documentation.
246 
247  Best, Robert.
248 
249 
250  Robert Frouin
251  Scripps Institution of Oceanography
252  University of California San Diego
253  9500 Gilman Drive
254  La Jolla, CA 92093-0221
255  Voice Tel.: 619/534-6243
256  Fax Tel.: 619/534-7452
257 
258 
259  */
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
const int bindx[3]
Definition: DbLutNetcdf.cpp:28
int smi_climatology_init(char *file, int day, int prodID)
int32_t day
#define FALSE
Definition: rice.h:164
#define NULL
Definition: decode_rs.h:63
float calc_par(l2str *l2rec, int ip, int nbands, float *Lt, float taua, float angstrom, float *wl, float *fo, float *ko3, float *taumolbar)
Definition: calc_par.c:87
read l1rec
#define VIIRSN
Definition: sensorDefs.h:23
#define TAUA865
#define MERIS
Definition: sensorDefs.h:22
#define TRUE
Definition: rice.h:165
#define MODIST
Definition: sensorDefs.h:18
#define PRODFAIL
Definition: l2_flags.h:41
data_t lambda[NROOTS+1]
Definition: decode_rs.h:75
instr * input
#define FATAL_ERROR
Definition: swl0_parms.h:5
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file for both the L1A and Geolocation enabling retrieval of South Polar DEM data Resolved Bug by changing to opent the geolocation file only after a successful read of the L1A and also by checking for fatal errors from not restoring C5 and to report how many of those high resolution values were water in the new WaterPresent SDS Added valid_range attribute to Land SeaMask Changed to bilinearly interpolate the geoid_height to remove artifacts at one degree lines Made corrections to const qualification of pointers allowed by new version of M API library Removed casts that are no longer for same not the geoid Corrected off by one error in calculation of high resolution offsets Corrected parsing of maneuver list configuration parameter Corrected to set Height SDS to fill values when geolocation when for elevation and land water mask
Definition: HISTORY.txt:114
void unix2yds(double usec, short *year, short *day, double *secs)
void get_par(l2str *l2rec, float par[])
Definition: get_par.c:34
#define LAND
Definition: l2_flags.h:12
#define SEAICE
Definition: l2_flags.h:35
#define BAD_FLT
Definition: jplaeriallib.h:19
#define OCTS
Definition: sensorDefs.h:14
float smi_climatology(float lon, float lat, int prodID)
int32_t nbands
#define HIGLINT
Definition: l2_flags.h:14
#define SEAWIFS
Definition: sensorDefs.h:12
#define MODISA
Definition: sensorDefs.h:19
#define VIIRSJ1
Definition: sensorDefs.h:37
#define ALPHA510
#define NAVFAIL
Definition: l2_flags.h:36