gridspec_api/regrid/nccf_compute_regrid_weights.c

00001 
00007 #include <math.h>
00008 #include <netcdf.h>
00009 
00010 #include <nccf_coord.h>
00011 #include <nccf_grid.h>
00012 #include <nccf_utility_functions.h>
00013 #include "nccf_regrid.h"
00014 
00015 #define MULTIPLE_TRIALS 1
00016 #define SNAKE 0
00017 #define EXHAUSTIVE_SEARCH 0
00018 
00019 struct CFLISTITEM *CFLIST_REGRID;
00020 
00021 int nccf_is_forbidden(int ndims, const double dIndices[], 
00022                       struct CFLISTITEM *box_lohi) {
00023   int res = 0;
00024   int in_this_box;
00025   int i, id;
00026   int *lohi;
00027   nccf_li_begin(&box_lohi);
00028   while (nccf_li_next(&box_lohi)) {
00029     id = nccf_li_get_id(&box_lohi);
00030     lohi = nccf_li_find(&box_lohi, id);
00031     in_this_box = 1;
00032     for (i = 0; i < ndims; ++i) {
00033       in_this_box *= (dIndices[i] >= lohi[i] && dIndices[i] <= lohi[i + ndims]);
00034     }
00035     res += in_this_box;
00036   }
00037   return res;
00038 }
00039 
00043 int nccf_find_indices_exhaustive(int ndims, const int oriDims[], 
00044                                  const double ** coordOriData, 
00045                                  const int is_periodic[], 
00046                                  const double xyz[], 
00047                                  int nitermax, double tolpos, 
00048                                  double dIndices[]) {
00049   int status = 1;
00050   int k, i;
00051   int ntot = 1;
00052   int ijk[ndims];
00053   for (i = 0; i < ndims; ++i) {
00054     ntot *= oriDims[i];
00055   }
00056   for (k = 0; k < ntot; ++k) {
00057     nccf_get_multi_index(ndims, oriDims, k, ijk);
00058     for (i = 0; i < ndims; ++i) {
00059       dIndices[i] = (double) ijk[i];
00060     }
00061     status = nccf_find_indices_double(ndims, oriDims,
00062                                       coordOriData,
00063                                       is_periodic,
00064                                       xyz, nitermax, tolpos,
00065                                       NULL, dIndices); 
00066     if (!status) {
00067       break;
00068     }
00069   }
00070   return status;
00071 }
00072 
00078 int nccf_find_indices_from_corners(int ndims, const int oriDims[], 
00079                                    const double ** coordOriData, 
00080                                    const int is_periodic[], 
00081                                    const double xyz[], 
00082                                    int nitermax, double tolpos, 
00083                                    double dIndices[]) {
00084   int status = 0;
00085   int numSides = 1;
00086   int j, i;
00087   int cornerVector[ndims];
00088   for (i = 0; i < ndims; ++i) {
00089     numSides *= 3;
00090   }
00091   for (j = 0; j < numSides; ++j) {
00092     nccf_index_to_corner_vector(j, ndims, cornerVector);
00093     for (i = 0; i < ndims; ++i) {
00094       dIndices[i] = dIndices[i] = (cornerVector[i] + 1) * (oriDims[i] - 1) / 2;
00095     }
00096     status = nccf_find_indices_double(ndims, oriDims,
00097                                       (const double **) coordOriData,
00098                                       is_periodic,
00099                                       xyz, nitermax, tolpos,
00100                                       NULL, dIndices);
00101     if (!status) {
00102       /* success */
00103       break;
00104     }
00105   }
00106   return status;
00107 }
00108 
00109 int nccf_compute_regrid_weights(int regrid_id,
00110                                 int nitermax, 
00111                                 double tolpos, 
00112                                 const int is_periodic[]) {
00113 
00114   int totErr = NC_NOERR;
00115   int status;
00116   int dims[] = {0, 0}, indom_dim[] = {0};
00117   const char *dim_names[] = {CF_DIMNAME_NTARGETS, CF_DIMNAME_NNODES};
00118   const char *indom_name[] = {CF_DIMNAME_NNODES};
00119 
00120   struct nccf_regrid_type *self;
00121   self = nccf_li_find(&CFLIST_REGRID, regrid_id);
00122 
00123   /* Fix */
00124   nitermax = (nitermax <= 0? 1: nitermax);
00125   tolpos = (tolpos < 1.e-8? 1.e-8: tolpos);
00126   
00127   int coordTargetIds[self->ndims];
00128   status = nccf_get_struct_grid_coord_ids(self->tgt_grid_id, coordTargetIds);
00129   totErr += abs(status);
00130 
00131   /* assume ndims >= 1 */
00132   int targetDims[self->ndims];
00133   status = nccf_get_coord_dims(coordTargetIds[0], targetDims);
00134   totErr += abs(status);
00135 
00136   
00137   int i, j, k;
00138   int numNodes = 1;
00139   self->ntargets = 1;
00140   for (i = 0; i < self->ndims; ++i) {
00141     self->ntargets *= targetDims[i];
00142     numNodes *= 2;
00143   }
00144 
00145   /* Get the original grid coordinates */
00146   int coordOriIds[self->ndims];
00147   status = nccf_get_struct_grid_coord_ids(self->ori_grid_id, coordOriIds);
00148   totErr += abs(status);
00149   
00150   int oriDims[self->ndims];
00151   status = nccf_get_coord_dims(coordOriIds[0], oriDims);
00152   totErr += abs(status);  
00153 
00154   double **coordOriData;
00155   double **coordTargetData;
00156   coordOriData = (double **) malloc(self->ndims * sizeof(double *));
00157   coordTargetData = (double **) malloc(self->ndims * sizeof(double *));
00158 
00159   for (i = 0; i < self->ndims; ++i) {
00160     double *dataPtr;
00161     status = nccf_get_coord_data_pointer(coordOriIds[i], &dataPtr);
00162     totErr += abs(status);
00163     coordOriData[i] = dataPtr;
00164     status = nccf_get_coord_data_pointer(coordTargetIds[i], &dataPtr);
00165     totErr += abs(status);
00166     coordTargetData[i] = dataPtr;
00167   }  
00168 
00169   /* Locate the cells and compute the weights */
00170   double dIndices[self->ndims];
00171   for (i = 0; i < self->ndims; ++i) {
00172     /* initial guess */
00173     dIndices[i] = 0.5; 
00174   }
00175 
00176   self->weights = (double **) malloc(self->ntargets * sizeof(double *));
00177   self->indices = (int **) malloc(self->ntargets * sizeof(int *));
00178   self->inside_domain = (int *) malloc(self->ntargets * sizeof(int));
00179 
00180   int displ[self->ndims];
00181   int indx[self->ndims];
00182 
00183   int prodDims[self->ndims];
00184   prodDims[self->ndims - 1] = 1; 
00185   for (i = self->ndims - 2; i >= 0; --i) {
00186     prodDims[i] = prodDims[i + 1] * 2;
00187   }
00188 
00189   double xyz[self->ndims];
00190   int countFirstHit = 0;
00191   int countMultipleTrials = 0;
00192 #if SNAKE == 1
00193   int ijk[self->ndims];
00194   for (i = 0; i < self->ndims; ++i) {
00195     ijk[i] = 0;
00196   }
00197   
00198   k = 0;
00199   int inside_domain = 1;
00200   while (inside_domain) {
00201     k = nccf_get_flat_index(self->ndims, targetDims, ijk);
00202 #else
00203   for (k = 0; k < self->ntargets; ++k) {
00204 #endif // SNAKE
00205     for (i = 0; i < self->ndims; ++i) {
00206       xyz[i] = coordTargetData[i][k];
00207     }
00208     status = nccf_find_indices_double(self->ndims, oriDims, 
00209                                       (const double **) coordOriData, is_periodic, 
00210                                       xyz, nitermax, tolpos, 
00211                                       NULL, dIndices);
00212     if (!status && nccf_is_forbidden(self->ndims, dIndices, self->box_lohi)) {
00213       status = -1;
00214     }
00215     if (!status) {
00216       countFirstHit++;
00217     }
00218 #if MULTIPLE_TRIALS == 1
00219     /*
00220        A non-zero value indicates failure to find the set of (float) indices.
00221        This may be due to the target position being outside of the domain or
00222        the position was found to be in the forbidden region.
00223     */
00224     if (status) {
00225       status = nccf_find_indices_from_corners(self->ndims, oriDims,
00226                                               (const double **) coordOriData,
00227                                               is_periodic,
00228                                               xyz, nitermax, tolpos,
00229                                               dIndices);
00230 
00231 #if EXHAUSTIVE_SEARCH == 1
00232       if (status) {
00233         status = nccf_find_indices_exhaustive(self->ndims, oriDims,
00234                                               (const double **) coordOriData,
00235                                               is_periodic,
00236                                               xyz, nitermax, tolpos,
00237                                               dIndices);
00238       }
00239 #endif
00240       if (!status && nccf_is_forbidden(self->ndims, dIndices, self->box_lohi)) {
00241           status = -1;
00242       }
00243       if (!status) {
00244         /* success */
00245         countMultipleTrials++;
00246       }
00247     }
00248 #endif // MULTIPLE_TRIALS
00249 
00250     self->inside_domain[k] = 0;
00251     if (status == 0) {
00252       self->inside_domain[k] = 1;
00253       self->n_nonmasked++;
00254     }
00255 
00256     // compute weights
00257     self->weights[k] = (double *) malloc(numNodes * sizeof(double));
00258     status = nccf_get_linear_interp_weights(self->ndims, oriDims, 
00259                                             dIndices, self->weights[k]);
00260     totErr += abs(status);
00261 
00262     // compute indices
00263     self->indices[k] = (int *) malloc(numNodes * sizeof(int));
00264     for (j = 0; j < numNodes; ++j) {
00265 
00266       // fill in displ,  is a vector of zeros and ones
00267       for (i = 0; i < self->ndims; ++i) {
00268         displ[i] = j / prodDims[i] % 2;
00269       }
00270 
00271       // compute the index set of the node
00272       for (i = 0; i < self->ndims; ++i) {
00273         indx[i] = (int) floor(dIndices[i]) + displ[i];
00274         // Fix index to prevent memory errors. Note this should not
00275         // influence the interpolation because the weights should be 
00276         // zero for nodal values outside the domain. 
00277         indx[i] = (indx[i] > oriDims[i] - 1? oriDims[i] - 1: indx[i]);
00278       }
00279 
00280       self->indices[k][j] = nccf_get_flat_index(self->ndims, oriDims, indx);
00281     }
00282 #if SNAKE == 1
00283     inside_domain = nccf_find_next_adjacent(self->ndims, targetDims, ijk);
00284 #endif
00285   }
00286 
00287 /* Populate the data structures initialized in nccf_def_regrid */
00288   dims[0] = self->ntargets;
00289   dims[1] = numNodes;
00290   self->nnodes  =  numNodes;
00291   indom_dim[0] = self->ntargets;
00292   int ddims = 2;  /* Number of dimensions for writing. NOT ndims */
00293 
00294   nccf_varSetDims( &self->inside_domain_stt, 1, indom_dim, indom_name );
00295   nccf_varSetDataPtr( &self->inside_domain_stt, NC_INT, self->inside_domain );
00296   nccf_varSetDims( &self->weights_stt, ddims, dims, dim_names );
00297   nccf_varSetDataPtr( &self->weights_stt, NC_DOUBLE, self->weights );
00298   nccf_varSetDims( &self->indices_stt, ddims, dims, dim_names );
00299   nccf_varSetDataPtr( &self->indices_stt, NC_INT, self->indices );
00300 
00301   /* Clean up */
00302   free(coordOriData);
00303   free(coordTargetData);
00304   
00305   return totErr;
00306 }
 All Classes Files Functions Defines

Generated on Tue Mar 1 2011 06:36:59 for libCF. LibCF is a Unidata library.