OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_pft_uitz.c
Go to the documentation of this file.
1 /*Uitz algorithm for determining the distribution of phytoplankton communities based upon surface chlorophyll
2  *
3  * This algorithm utilizes the near-surface chlorophyll a concentration as derived from satellite ocean color observation to infer the the phytoplankton functional type composition.
4  *
5  * Citation:
6  * Uitz,J.,H. Claustre, A. Morel, and S.B. Hooker (2006), Vertical distributin of phytoplankton communities in open ocean: An assessment based on surface chlorophyll, J. Geophys. Res., 111, C08005, doi:10.1029/2005JC003207.
7  *
8  * This algorithm was developed by Robert Lossing in October 2013 */
9 
10 #include <stdlib.h>
11 #include <math.h>
12 #include <gsl/gsl_integration.h>
13 #include "l12_proto.h"
14 
15 void calc_pft_uitz(float mld, float lat, float chl, float *fm, float *fn, float *fp) {
16 
17  /*Check Chlorophyll and mixed layer depth (mld) inputs and pixel fill values with ERROR CODES (2 if chl<0 and 5 if mld <=0) */
18 
19  if (chl < 0) {
20  *fm = BAD_FLT;
21  *fn = BAD_FLT;
22  *fp = BAD_FLT;
23  return;
24  }
25  if (mld <= 0) {
26  *fm = BAD_FLT;
27  *fn = BAD_FLT;
28  *fp = BAD_FLT;
29  return;
30  }
31  float f;
32  /*Estimate the euphotic depth (Zeu) using chl Eq. 10 of Morel et al., RSE 111, 69-88, 2007 */
33 
34  float x, a, y, zeu;
35  x = log(chl);
36  a = 0.0186 * pow(x, 3);
37  y = 1.524 - 0.436 * x - 0.0145 * pow(x, 2) + a;
38  zeu = pow(10, y);
39 
40  /*Zm equals the mixed layer depth (mld) */
41  float zm;
42  zm = mld;
43 
44  /*Determine if waters are mixed or stratified. */
45  if (zeu / zm > 1) {
46  /* Determination of coeffiecients and variables for equation 7.
47  *
48  * Explanation of variable names:
49  * trophcat = Trophic categories defined with respect to the chlorophyll a concentration within the surface layer, [Chla]surf
50  * chpcb,ps,pcmax,pzeta,pzetamax,pdeltamax = parameter placeholder value for equation 7 */
51 
52  int trophcathi, trophcatlo;
53 
54  /* Values of the five parameters (Table 5) to be used in equation (7) bbtained for the average dimensionless vertical profiles of
55  * Chla,Micro-Chla,Nano-Chla, and Pico-Chla, for each trophic class of stratified water (S1 to S9) (Table 5)*/
56 
57  // If the variable has a number at the end of it,it is related to a PFT size class.1=chla, 2= micro, 3= nano, 4 = pico. //
58 
59  //Table 5 Parameters for Chla
60  float cb1 [9] = {0.471, 0.533, 0.428, 0.570, 0.611, 0.390, 0.569, 0.835, 0.188};
61  float s1 [9] = {0.135, 0.172, 0.138, 0.173, 0.214, 0.109, 0.183, 0.298, 0};
62  float cmax1 [9] = {1.572, 1.194, 1.015, 0.766, 0.676, 0.788, 0.608, 0.382, 0.885};
63  float zetamax1 [9] = {0.969, 0.921, 0.905, 0.814, 0.663, 0.521, 0.452, 0.512, 0.378};
64  float deltazeta1 [9] = {0.393, 0.435, 0.630, 0.586, 0.539, 0.681, 0.744, 0.625, 1.081};
65  //Table 5 Parameters for Micro-Chla
66  float cb2[9] = {0.036, 0.071, 0.076, 0.071, 0.145, 0.173, 0.237, 0.331, 0.891};
67  float s2 [9] = {0.020, 0.020, 0.021, 0.021, 0.050, 0.044, 0.077, 0.105, 0.302};
68  float cmax2 [9] = {0.122, 0.173, 0.126, 0.160, 0.163, 0.161, 0.158, 0.278, 0};
69  float zetamax2 [9] = {1.012, 0.885, 0.835, 0.776, 0.700, 0.600, 0.521, 0.451, 0.277};
70  float deltazeta2 [9] = {0.532, 0.406, 0.424, 0.546, 0.479, 0.508, 0.543, 0.746, 1.014};
71  //Table 5 Parameters for Nano-Chla
72  float cb3 [9] = {0.138, 0.129, 0.142, 0.192, 0.188, 0.331, 0.201, 0.227, 0.171};
73  float s3 [9] = {0.033, 0.014, 0, 0.037, 0.055, 0.132, 0.084, 0.081, 0};
74  float cmax3 [9] = {0.764, 0.589, 0.463, 0.400, 0.418, 0.294, 0.350, 0.198, 0.088};
75  float zetamax3 [9] = {0.980, 0.899, 0.872, 0.782, 0.650, 0.501, 0.402, 0.181, 0.375};
76  float deltazeta3 [9] = {0.451, 0.454, 0.526, 0.535, 0.640, 0.516, 0724, 0.690, 0.352};
77  //Table 5 Parameters for Pico-Chla
78  float cb4 [9] = {0.222, 0.242, 0.254, 0.271, 0.159, 0.176, 0.009, 0.094, 0.051};
79  float s4 [9] = {0.114, 0.109, 0.099, 0.100, 0.052, 0.071, 0, 0.040, 0.023};
80  float cmax4 [9] = {0.906, 0.627, 0.437, 0.255, 0.176, 0.129, 0.251, 0.109, 0};
81  float zetamax4 [9] = {0.970, 0.977, 0.969, 0.858, 0.574, 0.458, 0.239, 0.187, 0.052};
82  float deltazeta4 [9] = {0.352, 0.427, 0.634, 0.637, 0.650, 0.626, 0.943, 0.618, 0.417};
83 
84  //interpolation
85  int i;
86  float f;
87 
88  //for (i = 0; i<9 ;i++)
89 
90  /*Trophic Categories for Stratified Waters were Defined With Respect to the Chlorophyll a Concentration Within the Surface Layer,
91  * [Chla]surf, and the Associated Parameters. Stratified Waters were separated into 9 trophic categories"trophcat". */
92 
93  float avgchlasurf_stratified [9] = {.032, 0.062, 0.098, 0.158, 0.244, 0.347, 0.540, 1.235, 2.953};
94 
95 
96  // Average Chla surface mg m-3 values from Table 3 for stratified waters.
97  if (chl <= avgchlasurf_stratified[0]) {
98  trophcathi = 0;
99  trophcatlo = 0;
100  } else if (chl > avgchlasurf_stratified[0] && chl <= avgchlasurf_stratified[1]) {
101  trophcatlo = 0;
102  trophcathi = 1;
103  } else if (chl >= avgchlasurf_stratified[1] && chl <= avgchlasurf_stratified[2]) {
104  trophcatlo = 1;
105  trophcathi = 2;
106  } else if (chl >= avgchlasurf_stratified[2] && chl <= avgchlasurf_stratified[3]) {
107  trophcatlo = 2;
108  trophcathi = 3;
109  } else if (chl >= avgchlasurf_stratified[3] && chl <= avgchlasurf_stratified[4]) {
110  trophcatlo = 3;
111  trophcathi = 4;
112  } else if (chl >= avgchlasurf_stratified[4] && chl <= avgchlasurf_stratified[5]) {
113  trophcatlo = 4;
114  trophcathi = 5;
115  } else if (chl >= avgchlasurf_stratified[5] && chl <= avgchlasurf_stratified[6]) {
116  trophcatlo = 5;
117  trophcathi = 6;
118  } else if (chl >= avgchlasurf_stratified[6] && chl <= avgchlasurf_stratified[7]) {
119  trophcatlo = 6;
120  trophcathi = 7;
121  } else if (chl >= avgchlasurf_stratified[7] && chl < avgchlasurf_stratified[8]) {
122  trophcatlo = 7;
123  trophcathi = 8;
124  } else {
125  trophcatlo = 8;
126  trophcathi = 8;
127  }
128  // Returns the proper lower and upper Table 5 coeffecients necessary for Equation 7 using the calculated Trophic Category / Stratified Class
129 
130  /* weighting scheme uses Kd490 as input into Gordon and Clark 1980. Estimate Kd490 using Chl Eq. 8 of Morel et al., RSE 111, 69-88, 2007. */
131 
132  float kd;
133  kd = 0.0166 + 0.0773 * pow(chl, 0.6715);
134 
135 
136  /* weighting scheme */
137  //float od [11] = {0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1};
138  float od; //Optical Depth
139  float wt; //Weighting Scheme
140  float sumczetachlahi, sumczetamicrohi, sumczetananohi, sumczetapicohi, sumwt;
141  float sumczetachlalo, sumczetamicrolo, sumczetananolo, sumczetapicolo;
142  float increment;
143 
144 
145  sumczetachlahi = 0;
146  sumczetamicrohi = 0;
147  sumczetananohi = 0;
148  sumczetapicohi = 0;
149  sumczetachlalo = 0;
150  sumczetamicrolo = 0;
151  sumczetananolo = 0;
152  sumczetapicolo = 0;
153  increment = .1;
154  sumwt = 0;
155  od = 0;
156 
157  for (i = 0; i < 11; i++) {
158 
159  wt = pow(exp(-kd * zeu * od), 2);
160  sumwt += wt;
161 
162  /* Equation 7: The upper and lower PFTs fractional values are calulated to provide the upper/lower interpolation boundaries */
163  //czeta1[i] = cb1[trophcatlo]-s1[trophcatlo]*od + cmax1[trophcatlo] * exp(-(pow(od-zetamax1[trophcatlo])/deltazeta1[trophcatlo]),2) *wt;
164  sumczetachlalo += (cb1[trophcatlo] - s1[trophcatlo] * od + cmax1[trophcatlo] * exp(-pow((od - zetamax1[trophcatlo]) / deltazeta1[trophcatlo], 2))) * wt;
165  //Micro -Chla
166  sumczetamicrolo += (cb2[trophcatlo] - s2[trophcatlo] * od + cmax2[trophcatlo] * exp(-pow((od - zetamax2[trophcatlo]) / deltazeta2[trophcatlo], 2))) * wt;
167  // Nano-Chla
168  sumczetananolo += (cb3[trophcatlo] - s3[trophcatlo] * od + cmax3[trophcatlo] * exp(-pow((od - zetamax3[trophcatlo]) / deltazeta3[trophcatlo], 2))) * wt;
169  // Pico-Chla
170  sumczetapicolo += (cb4[trophcatlo] - s4[trophcatlo] * od + cmax4[trophcatlo] * exp(-pow((od - zetamax4[trophcatlo]) / deltazeta4[trophcatlo], 2))) * wt;
171 
172  //czeta1[i] = cb1[trophcathi]-s1[trophcathi]*od + cmax1[trophcathi] * exp(-(pow(od-zetamax1[trophcathi])/deltazeta1[trophcathi]),2) *wt;
173  sumczetachlahi += (cb1[trophcathi] - s1[trophcathi] * od + cmax1[trophcathi] * exp(-pow((od - zetamax1[trophcathi]) / deltazeta1[trophcathi], 2))) * wt;
174  //Micro -Chla
175  sumczetamicrohi += (cb2[trophcathi] - s2[trophcathi] * od + cmax2[trophcathi] * exp(-pow((od - zetamax2[trophcathi]) / deltazeta2[trophcathi], 2))) * wt;
176  // Nano-Chla
177  sumczetananohi += (cb3[trophcathi] - s3[trophcathi] * od + cmax3[trophcathi] * exp(-pow((od - zetamax3[trophcathi]) / deltazeta3[trophcathi], 2))) * wt;
178  // Pico-Chla
179  sumczetapicohi += (cb4[trophcathi] - s4[trophcathi] * od + cmax4[trophcathi] * exp(-pow((od - zetamax4[trophcathi]) / deltazeta4[trophcathi], 2))) * wt;
180 
181  od += increment;
182  }
183  //float chla;
184  float chlmhi, chlnhi, chlphi;
185  float chlmlo, chlnlo, chlplo;
186  float chlm, chln, chlp;
187 
188  //returned PFT chlorophyll concentration values mg/m-3
189  //chla = sumczetachla/sumwt;
190  chlmlo = sumczetamicrolo / sumwt;
191  chlnlo = sumczetananolo / sumwt;
192  chlplo = sumczetapicolo / sumwt;
193 
194  chlmhi = sumczetamicrohi / sumwt;
195  chlnhi = sumczetananohi / sumwt;
196  chlphi = sumczetapicohi / sumwt;
197 
198  //Final Interpolation of Calculated Low and High PFT chlorophyll concentration (mg m-3) values
199 
200  if (trophcathi == 0 && trophcatlo == 0) {
201  f = 1;
202  }
203  else if (trophcathi == 8 && trophcatlo == 8) {
204  f = 1;
205  }
206  else {
207  f = (chl - avgchlasurf_stratified[trophcatlo]) / (avgchlasurf_stratified[trophcathi] - avgchlasurf_stratified[trophcatlo]);
208  }
209  chlm = ((1 - f) * chlmlo) + (f * chlmhi);
210  chln = ((1 - f) * chlnlo) + (f * chlnhi);
211  chlp = ((1 - f) * chlplo) + (f * chlphi);
212 
213  if (chlm > 1)
214  chlm = 1;
215 
216  if (chln > 1)
217  chln = 1;
218 
219  if (chlp > 1)
220  chlp = 1;
221 
222  if (chlm < 0)
223  chlm = 0;
224 
225  if (chln < 0)
226  chln = 0;
227 
228  if (chlp < 0)
229  chlp = 0;
230 
231  /* fractional contribution of micro, nano, and picoplankton */
232 
233  *fm = chlm / (chlm + chln + chlp);
234  *fn = chln / (chlm + chln + chlp);
235  *fp = chlp / (chlm + chln + chlp);
236 
237  }
238  /* If Zeu/Zm is NOT greater than 1 then the waters are mixed */
239  else {
240 
241  if (lat >= -60) {
242  /* The following statements determine the corresponding PFTs fractional proportions in GLOBALLY MIXED WATERS (southern mixed waters excluded). */
243  int trophcathi, trophcatlo;
244 
245  float global_mixed_waters_fmicro [5] = {.180, .241, .281, .522, .909};
246  float global_mixed_waters_fnano [5] = {.507, .498, .572, .381, .053};
247  float global_mixed_waters_fpico [5] = {.312, .262, .147, .097, .037};
248 
249  /* The following procedure determines the high and low fractional values needed to interpolate the average fractional proportion of each PFTs class.
250  * The mixed waters into five trophic classes based upon average surface chlorophyll a (mg m-3) */
251 
252  float avgchlasurf_global_mixed [5] = {0.234, 0.593, 0.891, 1.540, 7.964};
253 
254  if (chl <= avgchlasurf_global_mixed[0]) {
255  trophcathi = 0;
256  trophcatlo = 0;
257  } else if (chl > avgchlasurf_global_mixed[0] && chl <= avgchlasurf_global_mixed[1]) {
258  trophcatlo = 0;
259  trophcathi = 1;
260  } else if (chl > avgchlasurf_global_mixed[1] && chl <= avgchlasurf_global_mixed[2]) {
261  trophcatlo = 1;
262  trophcathi = 2;
263  } else if (chl > avgchlasurf_global_mixed[2] && chl <= avgchlasurf_global_mixed[3]) {
264  trophcatlo = 2;
265  trophcathi = 3;
266  } else if (chl > avgchlasurf_global_mixed[3] && chl <= avgchlasurf_global_mixed[4]) {
267  trophcatlo = 3;
268  trophcathi = 4;
269  } else {
270  trophcatlo = 4;
271  trophcathi = 4;
272  }
273 
274  //Final Interpolation of Calculated Low and High PFT chlorophyll concentration (mg m-3) values
275  if (trophcathi == 0 && trophcatlo == 0) {
276  f = 1;
277  }
278  else if (trophcathi == 4 && trophcatlo == 4) {
279  f = 1;
280  }
281  else {
282  f = (chl - avgchlasurf_global_mixed[trophcatlo]) / (avgchlasurf_global_mixed[trophcathi] - avgchlasurf_global_mixed[trophcatlo]);
283  }
284 
285  float fmicro, fnano, fpico;
286 
287  fmicro = ((1 - f) * global_mixed_waters_fmicro[trophcatlo]) + (f * global_mixed_waters_fmicro[trophcathi]);
288  fnano = ((1 - f) * global_mixed_waters_fnano[trophcatlo]) + (f * global_mixed_waters_fnano[trophcathi]);
289  fpico = ((1 - f) * global_mixed_waters_fpico[trophcatlo]) + (f * global_mixed_waters_fpico[trophcathi]);
290 
291  if (fmicro > 1)
292  fmicro = 1;
293  if (fnano > 1)
294  fnano = 1;
295  if (fpico > 1)
296  fpico = 1;
297 
298  if (fmicro < 0)
299  fmicro = 0;
300  if (fnano < 0)
301  fnano = 0;
302  if (fpico < 0)
303  fpico = 0;
304 
305  /* fractional contribution of micro, nano, and picoplankton */
306 
307  *fm = fmicro;
308  *fn = fnano;
309  *fp = fpico;
310 
311 
312  } else {
313  /*For southern mixed waters */
314  /* The following procedure determines the high and low fractional values needed to interpolate the average fractional proportion of each PFTs class.
315  * The mixed waters are separated into five trophic classes based upon average surface chlorophyll a (mg m-3) */
316  int trophcathi, trophcatlo;
317  float avgchlasurf_southern_mixed [5] = {0.345, 0.605, 0.889, 1.956, 5.755};
318 
319  if (chl <= avgchlasurf_southern_mixed[0]) {
320  trophcathi = 0;
321  trophcatlo = 0;
322  } else if (chl > avgchlasurf_southern_mixed[0] && chl <= avgchlasurf_southern_mixed[1]) {
323  trophcatlo = 0;
324  trophcathi = 1;
325  } else if (chl > avgchlasurf_southern_mixed[1] && chl <= avgchlasurf_southern_mixed[2]) {
326  trophcatlo = 1;
327  trophcathi = 2;
328  } else if (chl > avgchlasurf_southern_mixed[2] && chl <= avgchlasurf_southern_mixed[3]) {
329  trophcatlo = 2;
330  trophcathi = 3;
331  } else if (chl > avgchlasurf_southern_mixed[3] && chl <= avgchlasurf_southern_mixed[4]) {
332  trophcatlo = 3;
333  trophcathi = 4;
334  } else {
335  trophcatlo = 4;
336  trophcathi = 4;
337  }
338 
339  //Final Interpolation of Calculated Low and High PFT chlorophyll concentration (mg m-3) values
340 
341 
342  float southern_mixed_waters_fmicro [5] = {.534, .507, .446, .409, .137};
343  float southern_mixed_waters_fnano [5] = {.360, .441, .507, .566, .853};
344  float southern_mixed_waters_fpico [5] = {.106, .052, .047, .025, .010};
345 
346  float f;
347 
348  if (trophcathi == 0 && trophcatlo == 0) {
349  f = 1;
350  }
351  else if (trophcathi == 4 && trophcatlo == 4) {
352  f = 1;
353  }
354  else {
355  f = (chl - avgchlasurf_southern_mixed[trophcatlo]) / (avgchlasurf_southern_mixed[trophcathi] - avgchlasurf_southern_mixed[trophcatlo]);
356  }
357 
358  float fmicro, fnano, fpico;
359 
360  fmicro = ((1 - f) * southern_mixed_waters_fmicro[trophcatlo]) + (f * southern_mixed_waters_fmicro[trophcathi]);
361  fnano = ((1 - f) * southern_mixed_waters_fnano[trophcatlo]) + (f * southern_mixed_waters_fnano[trophcathi]);
362  fpico = ((1 - f) * southern_mixed_waters_fpico[trophcatlo]) + (f * southern_mixed_waters_fpico[trophcathi]);
363 
364  if (fmicro > 1)
365  fmicro = 1;
366  if (fnano > 1)
367  fnano = 1;
368  if (fpico > 1)
369  fpico = 1;
370 
371  if (fmicro < 0)
372  fmicro = 0;
373  if (fnano < 0)
374  fnano = 0;
375  if (fpico < 0)
376  fpico = 0;
377 
378  /* fractional contribution of micro, nano, and picoplankton */
379 
380  *fm = fmicro;
381  *fn = fnano;
382  *fp = fpico;
383  }
384  }
385 }
386 
387 void get_pft_uitz(l2str *l2rec, l2prodstr *p, float prod[]) {
388  int i;
389  float mld, fm, fn, fp;
390  int16_t year, day;
391  double sec;
392  unix2yds(l2rec->l1rec->scantime, &year, &day, &sec);
393 
394  l1str *l1rec = l2rec->l1rec;
395 
396  for (i = 0; i < l1rec->npix; i++) {
397  mld = get_mld(input->mldfile, l1rec->lon[i], l1rec->lat[i], day);
398  if (l2rec->chl[i] == BAD_FLT) {
399  prod[i] = BAD_FLT;
400  continue;
401  }
402 
403  switch (p->cat_ix) {
405  calc_pft_uitz(mld, l1rec->lat[i], l2rec->chl[i], &prod[i], &fn, &fp);
406  break;
408  calc_pft_uitz(mld, l1rec->lat[i], l2rec->chl[i], &fm, &prod[i], &fp);
409  break;
411  calc_pft_uitz(mld, l1rec->lat[i], l2rec->chl[i], &fm, &fn, &prod[i]);
412  break;
413 
414  default:
415  printf("calc_chla_uitz can not produce product %s\n", p->algorithm_id);
416  exit(1);
417  }
418  if (isnan(prod[i])) {
419  prod[i] = BAD_FLT;
420  l1rec->flags[i] |= PRODFAIL;
421  }
422  }
423 }
424 
float get_mld(char *mldfile, float lon, float lat, int day)
Definition: get_mld.cpp:347
int32_t day
read l1rec
float * lat
#define PRODFAIL
Definition: l2_flags.h:41
void get_pft_uitz(l2str *l2rec, l2prodstr *p, float prod[])
Definition: get_pft_uitz.c:387
#define CAT_nanoplankton_uitz
Definition: l2prod.h:303
instr * input
double precision function f(R1)
Definition: tmd.lp.f:1454
float * od[MAX_BANDS]
#define CAT_microplankton_uitz
Definition: l2prod.h:302
void calc_pft_uitz(float mld, float lat, float chl, float *fm, float *fn, float *fp)
Definition: get_pft_uitz.c:15
void unix2yds(double usec, short *year, short *day, double *secs)
#define BAD_FLT
Definition: jplaeriallib.h:19
#define CAT_picoplankton_uitz
Definition: l2prod.h:304
int i
Definition: decode_rs.h:71
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
float p[MODELMAX]
Definition: atrem_corl1.h:131