51 #define WESTBERRY2013 2 
   59 #include <gsl/gsl_fit.h> 
   63 static int32_t nbandVis; 
 
   72 static int bandNum550; 
 
   73 static int limitVisFlag;
 
   77 static float nWater = 1.344; 
 
   88 static float *aphStar; 
 
   89 static float *aphStarR; 
 
   92 static float *kappaSen; 
 
   93 static float *kappaRam;
 
  101 static float *aph1Sen; 
 
  102 static float *aph2Sen; 
 
  103 static float *aph1Ram; 
 
  104 static float *aph2Ram; 
 
  111 static float *t_sol_ram; 
 
  115 static float *ramLam; 
 
  116 static float *ramBandW; 
 
  119 static float *f0BarRam; 
 
  120 static float *rayRam; 
 
  123 static float *oxyRam; 
 
  124 static float *no2Ram; 
 
  126 static float *Rrs_ram; 
 
  130 static float *alphaCor;
 
  131 static float *betaCor0;
 
  132 static float *betaCor1;
 
  135 static float lamCor1[6] = {412.0, 443.0, 488.0, 531.0, 551.0, 667.0};
 
  136 static float alpha[6] = {0.003, 0.004, 0.011, 0.015, 0.017, 0.018};
 
  137 static float beta0[6] = {0.014, 0.015, 0.010, 0.010, 0.010, 0.010};
 
  138 static float beta1[6] = {-0.022, -0.023, -0.051, -0.070, -0.080, -0.081};
 
  152     if (nc_inq_varid(grpid, varName, &varid) != NC_NOERR) {
 
  153         fprintf(
stderr, 
"-E- %s line %d: could not find netCDF variable \"%s\" in netCDF File.\n",
 
  154                 __FILE__, __LINE__, varName);
 
  159     if (nc_inq_dimid(grpid,varName, &dimid) != NC_NOERR ) {
 
  160         fprintf(
stderr, 
"-E- %s line %d: could not find %s in netCDF File.\n",
 
  161                 __FILE__, __LINE__, varName);
 
  165     if (nc_inq_dimlen(grpid, dimid, &varLen) != NC_NOERR ) {
 
  166         fprintf(
stderr, 
"-E- %s line %d: could not find netCDF variable dimensions in netCDF File.\n",
 
  173     if (varLen != nbandVis && limitVisFlag!=1) {
 
  174         fprintf(
stderr, 
"-E- %s line %d: number of Raman coefficients %ld does not equal sensors visible" 
  176                 __FILE__, __LINE__,varLen,nbandVis);
 
  181     if (nc_get_var_float (grpid, varid, variable) != NC_NOERR ) { 
 
  182         fprintf(
stderr, 
"-E- %s line %d: could not read netCDF variable %s in netCDF File.\n",
 
  183                 __FILE__, __LINE__,varName);
 
  200     bbwR = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"bbwR");
 
  201     aphStar = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aphStar");
 
  202     aphStarR = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aphStarR");
 
  203     bbtot = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"bbtot");
 
  204     atot = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"atot");
 
  205     bbtotR = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"bbtotR");
 
  206     atotR = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"atotR");
 
  208     kdSen = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"kdSen");
 
  209     kdRam = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"kdRam");
 
  210     kappaSen = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"kappaSen");
 
  211     kappaRam = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"kappaRam");
 
  213     betaCor0 = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"betaCor0");
 
  214     betaCor1 = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"betaCor1");
 
  215     alphaCor = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"alphaCor");
 
  217     eDRam = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"eDRam");
 
  218     eDSen = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"eDSen");
 
  220     t_sol_ram = (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"t_sol_ram");
 
  223             l2rec->l1rec->l1file->nbands * sizeof (
float), 
"Rrs_ram");
 
  225     ramLam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"ramLam");
 
  226     ramBandW =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"ramBandW");
 
  227     bRex =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"bRex");   
 
  228     f0BarRam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"foBarRam");
 
  229     rayRam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"rayRam");
 
  230     ozRam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"ozRam");
 
  231     wvRam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"wvRam");
 
  232     oxyRam =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"oxyRam");
 
  233     no2Ram =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"no2Ram");
 
  234     aph1Ram =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aph1Ram");
 
  235     aph2Ram =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aph2Ram");
 
  237     aph1Sen =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aph1Sen");
 
  238     aph2Sen =  (
float*) 
allocateMemory(nbandVis * 
sizeof (
float), 
"aph2Sen");
 
  251     if ((filedir = getenv(
"OCDATAROOT")) == 
NULL) {
 
  252         printf(
"-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
 
  256     filehandle *
l1file = l2rec->l1rec->l1file;
 
  274     printf(
"Loading Raman coefficients from: %s.\n", 
filename);
 
  279     if (nc_open(
filename, NC_NOWRITE, &ncid) != NC_NOERR) {
 
  280         fprintf(
stderr, 
"-E- %s line %d: could not open netCDF File \"%s\".\n",
 
  286     if (nc_inq_grp_ncid(ncid, 
"raman_coeffs", &grpid) != NC_NOERR) {
 
  287         fprintf(
stderr, 
"-E- %s line %d: could not find netCDF group \"raman_coeffs\".\n",
 
  305     if (nc_inq_grp_ncid(ncid, 
"sensor_coeffs", &grpid) != NC_NOERR) {
 
  306         fprintf(
stderr, 
"-E- %s line %d: could not find netCDF group \"sensor_coeffs\".\n",
 
  315     if (nc_close(ncid) != NC_NOERR){
 
  316         fprintf(
stderr, 
"-E- %s line %d: could not close netCDF \"%s\".\n",
 
  335     aphStar443 = aph1Sen[idx443] * pow(l2rec->chl[ip], (aph2Sen[idx443]));
 
  339     for (iw = 0; iw < nbandVis; iw++) {
 
  340         aphStar[iw] = (aph1Sen[iw] * pow(l2rec->chl[ip], (aph2Sen[iw])))
 
  342         aphStarR[iw] = (aph1Ram[iw] * pow(l2rec->chl[ip], (aph2Ram[iw])))
 
  348     aphM = (aphStar[idx443] - aphStar[idx412]) / (
lambda[idx443] - 
lambda[idx412]);
 
  349     aphC = aphStar[idx443] - aphM * 
lambda[idx443];
 
  352     for (iw = 0; iw < nbandVis; iw++) {
 
  353         if (ramLam[iw] <= 400) {
 
  354             aphStarR[iw] = (aphM * ramLam[iw] + aphC);
 
  369     double logTsol[nbandVis];
 
  370     double waveRatio[nbandVis];
 
  372     double c0, c1, cov00, cov01, cov11, 
sumsq;
 
  373     int nbands = l2rec->l1rec->l1file->nbands;
 
  376     for (iw = 0; iw < nbandVis; iw++) {
 
  377         logTsol[iw] = log(l2rec->l1rec->t_sol[ip * 
nbands + iw] / l2rec->l1rec->t_sol[ip * 
nbands + idx488]);
 
  382     gsl_fit_linear(waveRatio, 1, logTsol, 1, nbandVis, &c0, &c1, &cov00, &cov01, &cov11, &
sumsq);
 
  386     for (iw = 0; iw < nbandVis; iw++) {
 
  387         t_sol_ram[iw] = l2rec->l1rec->t_sol[ip * 
nbands + idx488] * pow((ramLam[iw] / 
lambda[idx488]), c1);
 
  400     float rat, zeta, xi, term1, term2;
 
  402     float rrs_a[nbandVis];
 
  403     float rrs_s[nbandVis];
 
  410     float acoefs[3] = {-1.146, -1.366, -0.469};
 
  413     for (iw = 0; iw < nbandVis; iw++) {
 
  414         rrs_a[iw] = l2rec->Rrs[ip * l2rec->l1rec->l1file->nbands + iw];
 
  415         rrs_s[iw] = rrs_a[iw] / (0.52 + 1.7 * rrs_a[iw]);
 
  419     if (rrs_a[idx550] <= 0.0)
 
  420         rrs_a[idx550] = 0.001;
 
  423     if ((rrs_a[idx670] > 20.0 * pow(rrs_a[idx550], 1.5)) || (rrs_a[idx670] < 0.9 * pow(rrs_a[idx550], 1.7))) {
 
  424         rrs_a[idx670] = 1.27 * pow(rrs_a[idx550], 1.47) + 0.00018 * pow(rrs_a[idx488] / rrs_a[idx550], -3.19);
 
  428     for (iw = 0; iw < nbandVis; iw++) {
 
  429         u[iw] = (sqrt(g0 * g0 + 4.0 * g1 * rrs_s[iw]) - g0) / (2.0 * g1);
 
  434     if (rrs_s[idx670] >= 0.0015) {
 
  435         aref = aw[idx670] + 0.07 * pow(rrs_a[idx670] / rrs_s[idx443], 1.1);
 
  439         numer = rrs_a[idx443] + rrs_a[idx488];
 
  440         denom = rrs_a[idx550] + 5 * rrs_a[idx670]*(rrs_a[idx670] / rrs_a[idx488]);
 
  442         rho = acoefs[0] + acoefs[1] * rho + acoefs[2] * rho*rho;
 
  443         aref = aw[idx550] + pow(10.0, rho);
 
  448     bbpref = ((
u[idxref] * aref) / (1.0 - 
u[idxref])) - bbw[idxref];
 
  451     rat = rrs_s[idx443] / rrs_s[idx550];
 
  452     Ybbp = 2.0 * (1.0 - 1.2 * exp(-0.9 * rat));
 
  456     bbp443 = bbpref * pow((
lambda[idxref] / 
lambda[idx443]), Ybbp);
 
  459     for (iw = 0; iw < nbandVis; iw++) {
 
  460         bbt[iw] = bbpref * pow((
lambda[idxref] / 
lambda[iw]), Ybbp) + bbw[iw];
 
  464     for (iw = 0; iw < nbandVis; iw++) {
 
  465         at[iw] = ((1.0 - 
u[iw]) * bbt[iw]) / 
u[iw];
 
  470     Sdg = 0.015 + 0.002 / (0.6 + rrs_s[idx443] / rrs_s[idxref]);
 
  474     zeta = 0.74 + 0.2 / (0.8 + rrs_s[idx443] / rrs_s[idxref]);
 
  476     term1 = (at[idx412] - zeta * at[idx443]) - (aw[idx412] - zeta * aw[idx443]);
 
  478     adg443 = term1 / term2;
 
  481     aph443 = at[idx443] - adg443 - aw[idx443];
 
  491     float bbpR, adgR, aphR;
 
  495     for (iw = 0; iw < nbandVis; iw++) {
 
  498         bbpR = bbp443 * pow((
lambda[idx443] / ramLam[iw]), Ybbp);
 
  499         adgR = adg443 * exp(-Sdg * (ramLam[iw] - 
lambda[idx443]));
 
  500         aphR = aph443 * aphStarR[iw];
 
  503         bbp = bbp443 * pow((
lambda[idx443] / 
lambda[iw]), Ybbp);
 
  504         adg = adg443 * exp(-Sdg * (
lambda[iw] - 
lambda[idx443]));
 
  505         aph = aph443 * aphStar[iw];
 
  508         atotR[iw] = awR[iw] + adgR + aphR;
 
  509         bbtotR[iw] = bbwR[iw] + bbpR;
 
  512         atot[iw] = aw[iw] + adg + aph;
 
  513         bbtot[iw] = bbw[iw] + bbp;
 
  524     float solzRad, solzRadSw, muD, muU;
 
  527     solzRad = l2rec->l1rec->solz[ip]*(
M_PI / 180.0);
 
  528     solzRadSw = asin(sin(solzRad) / nWater); 
 
  531     muD = cos(solzRadSw);
 
  534     for (iw = 0; iw < nbandVis; iw++) {
 
  537         kdSen[iw] = (atot[iw] + bbtot[iw]) / muD;
 
  538         kdRam[iw] = (atotR[iw] + bbtotR[iw]) / muD;
 
  540         kappaSen[iw] = (atot[iw] + bbtot[iw]) / muU;
 
  541         kappaRam[iw] = (atotR[iw] + bbtotR[iw]) / muU;
 
  554     l1str *
l1rec = l2rec->l1rec;
 
  557     float p0 = 29.92 * 33.8639; 
 
  558     float radCon = 
M_PI / 180.0; 
 
  559     float ws = l2rec->l1rec->ws[ip]; 
 
  560     float nw2= pow(nWater,2.);  
 
  563     float sin2Solz, rf0, a0,a1,a2,a3, rho_fres;
 
  564     float solz, solzRad, cosSolz, mPres, mAtm, f0Ex;
 
  565     float th2oEx, to2Ex, tno2Ex, to3Ex, tgEx;
 
  566     float a_285R, a_225R,tau_to200R;
 
  567     float no2_tr200R, eDRam_above;
 
  576     solzRad = 
l1rec->solz[ip]*radCon;
 
  579     cosSolz = cos(solzRad);
 
  582     sin2Solz = pow(sin(solzRad),2.);
 
  587     rf0 = 0.5*( pow( (cosSolz - pow(nw2 - sin2Solz ,0.5))/(cosSolz + pow(nw2 + sin2Solz ,0.5)) ,2.) 
 
  588             +   pow( (nw2*cosSolz - pow(nw2 - sin2Solz ,0.5))/(nw2*cosSolz + pow(nw2 + sin2Solz ,0.5)) ,2.) );
 
  591     a0 = 0.001*(6.944831 - 1.912076*ws  + 0.03654833*ws*ws);
 
  592     a1 = 0.7431368 + 0.0679787*ws - 0.0007171*ws*ws;
 
  593     a2 = 0.5650262 + 0.0061502*ws - 0.0239810*ws*ws + 0.0010695*ws*ws*ws;
 
  594     a3 = -0.4128083 - 0.1271037*ws + 0.0283907*ws*ws - 0.0011706*ws*ws*ws;
 
  597     rho_fres = a0 + rf0*(a1 + rf0*(a2 + a3*rf0));
 
  604     mAtm = 1.0 / (cosSolz + 0.50572 * pow((86.07995 - 
solz), -1.6364));
 
  610     mPres = mAtm * (
l1rec->pr[ip] / p0);
 
  614     if (l2rec->l1rec->no2_tropo[ip] > 0.0)
 
  616         no2_tr200R = 
l1rec->no2_frac[ip] *
l1rec->no2_tropo[ip];
 
  622     for (iw = 0; iw < nbandVis; iw++) {
 
  624         ipb =  ip*
l1rec->l1file->nbands  + iw;
 
  627         f0Ex = f0BarRam[iw] * 
l1rec->fsol; 
 
  630         to3Ex = exp(-(ozRam[iw] * 
l1rec->oz[ip] / 
l1rec->csolz[ip]) );
 
  633         a_285R = no2Ram[iw] * (1.0 - 0.003 * (285.0 - 294.0));
 
  634         a_225R = no2Ram[iw] * (1.0 - 0.003 * (225.0 - 294.0));
 
  635         tau_to200R = a_285R * no2_tr200R + a_225R * 
l1rec->no2_strat[ip];
 
  636         tno2Ex = exp(-(tau_to200R / 
l1rec->csolz[ip]) );
 
  639         th2oEx = exp((-0.2385 * wvRam[iw] * 
l1rec->wv[ip] * mAtm) /
 
  640                 (pow((1.0 + 20.07 * wvRam[iw] * 
l1rec->wv[ip] * mAtm), 0.45)));
 
  644         to2Ex = exp((-1.41 * oxyRam[iw] * mPres) / (pow((1.0 + 118.3 * oxyRam[iw] * mPres), 0.45)));
 
  646         tgEx = to3Ex*tno2Ex*th2oEx*to2Ex;
 
  649         eDRam_above = f0Ex * tgEx * t_sol_ram[iw]* cos(solzRad) * 10.0;
 
  650         eDSen[iw] = 
l1rec->Fo[iw] * 
l1rec->tg_sol[ipb] * 
l1rec->t_sol[ipb]* cos(solzRad) * 10.0;
 
  652         eDRam[iw] = 1.03*(1.0 - rho_fres)*eDRam_above;
 
  665     float Rrs443, Rrs550;
 
  668     int nbands = l2rec->l1rec->l1file->nbands;
 
  670     if (l2rec->l1rec->mask[ip]) {
 
  675     Rrs443 = l2rec->Rrs[ip * 
nbands + idx443];
 
  676     Rrs550 = l2rec->Rrs[ip * 
nbands + idx550];
 
  679     for (iw = 0; iw < nbandVis; iw++) {
 
  684         rFactor = alphaCor[iw] * Rrs443 / Rrs550 + betaCor0[iw] * pow(Rrs550, betaCor1[iw]);
 
  686         rrs_a = l2rec->Rrs[ip * 
nbands + iw];
 
  688         Rrs_ram[ip * 
nbands + iw] = rrs_a - rrs_a / (1.0 + rFactor);
 
  691             Rrs_ram[ip * 
nbands + iw] = 0.0;
 
  711     int nbands = l2rec->l1rec->l1file->nbands;
 
  712     float term0, term1, numer1, denom1;
 
  717     if (l2rec->l1rec->mask[ip]) {
 
  738     term0 = 1.0 / (4.0 * 
M_PI * nWater * nWater);
 
  742     for (iw = 0; iw < nbandVis; iw++) {
 
  748             numer1 = bRex[iw] * eDRam[iw];
 
  749             denom1 = (kdRam[iw]+kappaSen[iw])*eDSen[iw];
 
  750             term1 = numer1 / denom1;
 
  753             Rrs_rc = term0 * term1;
 
  756             Rrs_ram[ip * 
nbands + iw] = Rrs_rc;
 
  759             Rrs_ram[ip * 
nbands + iw] = 0.0;
 
  774     int nbands = l2rec->l1rec->l1file->nbands;
 
  778     if (l2rec->l1rec->mask[ip]) {
 
  796     for (iw = 0; iw < nbandVis; iw++) {
 
  800         Rrs_rc = 0.072 * (bRex[iw] * eDRam[iw]) / ((2.0 * atot[iw] + atotR[iw]) * eDSen[iw]);
 
  803         Rrs_ram[ip * 
nbands + iw] = Rrs_rc;
 
  806              Rrs_ram[ip * 
nbands + iw] = 0.0;
 
  820     static int firstCall = 1;
 
  821     static int sensorSupported;
 
  831         switch (l2rec->l1rec->l1file->sensorID){
 
  856         if (
input->raman_opt == 0) {
 
  859             if (!sensorSupported) {
 
  860                 printf(
"Raman correction unsupported for this sensor. \n");
 
  863             printf(
"No Raman scattering correction calculated for Rrs. \n");
 
  867         } 
else if (
input->raman_opt > 0 && 
input->raman_opt <= 3) {
 
  870             printf(
"Compute Raman scattering correction #%d. \n", 
input->raman_opt);
 
  875             printf(
"-E- %s line %d : '%d' is not a valid Raman correction option.\n",
 
  876                     __FILE__, __LINE__, 
input->raman_opt);
 
  885         if (sensorSupported) {
 
  891             for (iw = 0; iw < nbandVis; iw++) {
 
  894                 lambda[iw] = l2rec->l1rec->l1file->fwave[iw];
 
  902                 awR[iw] = 
aw_spectra(ramLam[iw], ramBandW[iw]);
 
  904                 aw[iw] = l2rec->l1rec->l1file->aw[iw];
 
  905                 bbw[iw] = l2rec->l1rec->l1file->bbw[iw];
 
  919             for (iw = 0; iw < nbandVis; iw++) {
 
  934         for (iw = 0; iw < l2rec->l1rec->l1file->nbands; iw++) {
 
  935             Rrs_ram[ip * l2rec->l1rec->l1file->nbands + iw] = 0.0;
 
  952     l2rec->Rrs_raman = Rrs_ram;