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
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
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
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
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
00170 double dIndices[self->ndims];
00171 for (i = 0; i < self->ndims; ++i) {
00172
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
00221
00222
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
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
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
00263 self->indices[k] = (int *) malloc(numNodes * sizeof(int));
00264 for (j = 0; j < numNodes; ++j) {
00265
00266
00267 for (i = 0; i < self->ndims; ++i) {
00268 displ[i] = j / prodDims[i] % 2;
00269 }
00270
00271
00272 for (i = 0; i < self->ndims; ++i) {
00273 indx[i] = (int) floor(dIndices[i]) + displ[i];
00274
00275
00276
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
00288 dims[0] = self->ntargets;
00289 dims[1] = numNodes;
00290 self->nnodes = numNodes;
00291 indom_dim[0] = self->ntargets;
00292 int ddims = 2;
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
00302 free(coordOriData);
00303 free(coordTargetData);
00304
00305 return totErr;
00306 }