project_field_eof.c File Reference

Project physical field on pre-computed EOF. More...

#include <pceof.h>
Include dependency graph for project_field_eof.c:

Go to the source code of this file.

Functions

int project_field_eof (double *bufout, double *bufin, double *bufeof, double *singular_value, double missing_value_eof, double *lon, double *lat, double scale, int ni, int nj, int ntime, int neof)
 Subroutine to project a 2D-time field on pre-calculated EOFs.

Detailed Description

Project physical field on pre-computed EOF.

Definition in file project_field_eof.c.


Function Documentation

int project_field_eof ( double *  bufout,
double *  bufin,
double *  bufeof,
double *  singular_value,
double  missing_value_eof,
double *  lon,
double *  lat,
double  scale,
int  ni,
int  nj,
int  ntime,
int  neof 
)

Subroutine to project a 2D-time field on pre-calculated EOFs.

Parameters:
[out] bufout Output 2D (neof x ntime) projected bufin field using input eof and singular_value
[in] bufin Input field 3D (ni x nj x ntime)
[in] bufeof EOF of input field 3D (ni x nj x neof)
[in] singular_value Singular value for EOF
[in] missing_value_eof Missing value for bufeof
[in] lon Longitude
[in] lat Latitude
[in] scale Scaling for units to apply before projecting onto EOF
[in] ni Horizontal dimension
[in] nj Horizontal dimension
[in] ntime Temporal dimension
[in] neof EOF dimension

Definition at line 55 of file project_field_eof.c.

References alloc_error(), DEGTORAD, and EARTH_RADIUS.

Referenced by main(), and wt_downscaling().

00057 {
00073   double norm; /* Normalization factor. */
00074   double sum_verif_norm; /* Sum to verify normalization. */
00075   double val; /* Double temporary value */
00076   double sum; /* Temporary sum */
00077 
00078   double *true_val = NULL; /* 2D matrix of normalized value */
00079   
00080   double variance_bufin; /* Variance of input buffer */
00081   double tot_variance_bufin = 0.0; /* Total Variance of input buffer */
00082   double variance_bufout; /* Variance of output buffer */
00083   double tot_variance_bufout = 0.0; /* Total Variance of output buffer */
00084 
00085   double sum_scal = 0.0; /* EOF scaling factor sum */
00086   double *scal = NULL; /* EOF Scaling factor */
00087   double e1n, e2n; /* Scaling factor components */
00088 
00089   int eof; /* Loop counter */
00090   int i; /* Loop counter */
00091   int j; /* Loop counter */
00092   int t; /* Loop counter */
00093 
00094   /*** Project field on EOFs ***/
00095 
00096   /* Allocate memory */
00097   true_val = (double *) malloc(ni*nj * sizeof(double));
00098   if (true_val == NULL) alloc_error(__FILE__, __LINE__);
00099   scal = (double *) malloc(ni*nj * sizeof(double));
00100   if (scal == NULL) alloc_error(__FILE__, __LINE__);
00101 
00102   /* Compute norm */
00103 
00104   /* DEBUG */
00105   /*  sum = 0.0;
00106   for (j=0; j<nj; j++)
00107     for (i=0; i<ni; i++) {
00108       eof = 0;
00109       if (bufeof[i+j*ni+eof*ni*nj] != missing_value_eof)
00110         printf("%d %d %d %d %lf\n",(int) sum,i,j,eof,bufeof[i+j*ni+eof*ni*nj]);
00111       if (bufeof[i+j*ni] != missing_value_eof)
00112         sum = sum + 1.0;
00113         } */
00114 
00115   /* Loop over all EOFs */
00116   for (eof=0; eof<neof; eof++) {
00117 
00118     /* Initializing */
00119     norm = 0.0;
00120     sum_verif_norm = 0.0;
00121     
00122     /* Loop over all gridpoints */
00123     /* Compute the sum of the squared values normalized by the singular value */
00124     for (j=0; j<nj; j++)
00125       for (i=0; i<ni; i++) {
00126         if (bufeof[i+j*ni+eof*ni*nj] != missing_value_eof) {
00127           val = bufeof[i+j*ni+eof*ni*nj] / singular_value[eof];
00128           norm += (val * val);
00129         }
00130       }
00131     
00132     /* Compute true value */
00133     sum = 0.0;
00134     for (j=0; j<nj; j++)
00135       for (i=0; i<ni; i++) {
00136         if (bufeof[i+j*ni+eof*ni*nj] != missing_value_eof) {
00137           val = bufeof[i+j*ni+eof*ni*nj] / ( sqrt(norm) * singular_value[eof] );
00138           true_val[i+j*ni] = val;
00139           sum += val;
00140           sum_verif_norm += (val * val);
00141         }
00142       }
00143 
00144     /* Verify that the norm is equal to 1.0 */
00145     (void) fprintf(stdout, "%s: Verifying the sqrt(norm)=%lf (should be equal to 1) for EOF #%d: %lf\n", __FILE__, sqrt(norm),
00146                    eof, sum_verif_norm);
00147     if (fabs(sum_verif_norm) < 0.01) {
00148       (void) fprintf(stderr, "%s: FATAL ERROR: Re-norming does not equal 1.0 : %lf.\nAborting\n", __FILE__, sum_verif_norm);
00149       /* Free memory */
00150       (void) free(true_val);
00151       (void) free(scal);
00152       return -1;
00153     }
00154 
00155     /* Compute EOF scale factor */
00156     sum_scal = 0.0;
00157     for (j=0; j<nj; j++)
00158       for (i=0; i<ni; i++) {
00159         if (j < (nj-1))
00160           e1n = ( 2.0*M_PI*EARTH_RADIUS/(DEGTORAD*lon[i+j*ni]) ) * fabs( cos( DEGTORAD*(lat[i+(j+1)*ni]-lat[i+j*ni]) ) );
00161         else
00162           e1n = ( 2.0*M_PI*EARTH_RADIUS/(DEGTORAD*lon[i+j*ni]) ) * fabs( cos( DEGTORAD*(lat[i+j*ni]-lat[i+(j-1)*ni]) ) );
00163         if (j < (nj-1))
00164           e2n = ( 2.0*EARTH_RADIUS ) * fabs( cos( DEGTORAD*(lat[i+(j+1)*ni]-lat[i+j*ni]) ) );
00165         else
00166           e2n = ( 2.0*EARTH_RADIUS ) * fabs( cos( DEGTORAD*(lat[i+j*ni]-lat[i+(j-1)*ni]) ) );
00167         //        printf("%lf %lf\n",e1n,e2n);
00168         scal[i+j*ni] = e1n * e2n;
00169         sum_scal += scal[i+j*ni];
00170       }
00171     for (j=0; j<nj; j++)
00172       for (i=0; i<ni; i++) {
00173         scal[i+j*ni] = sqrt( scal[i+j*ni] * (1.0/sum_scal) );
00174         //        if (eof == 0)
00175         //          printf("%d %d lon=%lf %lf %lf\n",i,j,lon[i+j*ni],lat[i+j*ni],scal[i+j*ni]);
00176       }
00177 
00178     /* Project field onto EOF */
00179     for (t=0; t<ntime; t++) {
00180       sum = 0.0;
00181       for (j=0; j<nj; j++)
00182         for (i=0; i<ni; i++)
00183           if (bufeof[i+j*ni+eof*ni*nj] != missing_value_eof)
00184             /*            sum += ( bufin[i+j*ni+t*ni*nj] * scale * scal[i+j*ni] / sqrt(norm) * true_val[i+j*ni] );*/
00185             sum += ( bufin[i+j*ni+t*ni*nj] * scale / sqrt(norm) * true_val[i+j*ni] );
00186       bufout[t+eof*ntime] = sum;
00187       //      printf("%d %d %lf\n",t,eof,sum);
00188     }
00189 
00190     variance_bufout = gsl_stats_variance(&(bufout[eof*ntime]), 1, ntime);
00191     tot_variance_bufout += variance_bufout;
00192     variance_bufin = gsl_stats_variance(&(bufin[eof*ntime]), 1, ntime);
00193     tot_variance_bufin += variance_bufin;
00194 
00195     /* Verify variance of field */
00196     /* Should be of the same order */
00197     (void) fprintf(stdout, "%s: Verifying square-root of variance (should be the same order): %lf %lf\n", __FILE__,
00198                    sqrt(variance_bufout), singular_value[eof]);
00199     (void) fprintf(stdout, "%s: %lf\n", __FILE__, sqrt(variance_bufout) / singular_value[eof]);
00200     if ( (sqrt(gsl_stats_variance(&(bufout[eof*ntime]), 1, ntime)) / singular_value[eof]) >= 10.0) {
00201       (void) fprintf(stderr, "%s: FATAL ERROR: Problem in scaling factor! Variance is not of the same order. Verify configuration file scaling factor.\nAborting\n", __FILE__);
00202       /* Free memory */
00203       (void) free(true_val);
00204       (void) free(scal);
00205       return -1;
00206     }
00207   }
00208 
00209   (void) fprintf(stdout, "%s: Comparing total variance of field before %lf and after %lf projection onto EOF: %% of variance remaining: %lf\n",
00210                  __FILE__, tot_variance_bufin, tot_variance_bufout, tot_variance_bufout / tot_variance_bufin * 100.0);
00211 
00212   /* Free memory */
00213   (void) free(true_val);
00214   (void) free(scal);
00215 
00216   /* Success status */
00217   return 0;
00218 }


Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1