1 /***********************************************************************
2 * GNU Lesser General Public License
4 * This file is part of the GFDL Flexible Modeling System (FMS).
6 * FMS is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or (at
9 * your option) any later version.
11 * FMS is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
22 #include "grid_utils.h"
23 #include "tree_utils.h"
24 #include "horiz_interp_conserve_xgrid.h"
33 * \brief Grid creation and calculation functions for use in @ref mosaic_mod
36 /*******************************************************************************
37 void create_xgrid_1dx2d_order1
38 This routine generate exchange grids between two grids for the first order
39 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
40 and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
41 *******************************************************************************/
42 int create_xgrid_1dx2d_order1_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
43 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
44 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
, double *xgrid_area
)
48 nxgrid
= create_xgrid_1dx2d_order1(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
,
49 i_in
, j_in
, i_out
, j_out
, xgrid_area
);
54 int create_xgrid_1dx2d_order1(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
, const double *lon_in
,
55 const double *lat_in
, const double *lon_out
, const double *lat_out
,
56 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
,
57 int *j_out
, double *xgrid_area
)
60 int nx1
, ny1
, nx2
, ny2
, nx1p
, nx2p
;
61 int i1
, j1
, i2
, j2
, nxgrid
;
62 double ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_in
[MV
], y_in
[MV
], x_out
[MV
], y_out
[MV
];
63 double *area_in
, *area_out
, min_area
;
75 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
76 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
77 tmpx
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
78 tmpy
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
79 for(j1
=0; j1
<=ny1
; j1
++) for(i1
=0; i1
<=nx1
; i1
++) {
80 tmpx
[j1
*nx1p
+i1
] = lon_in
[i1
];
81 tmpy
[j1
*nx1p
+i1
] = lat_in
[j1
];
83 /* This is just a temporary fix to solve the issue that there is one point in zonal direction */
85 get_grid_area(nlon_in
, nlat_in
, tmpx
, tmpy
, area_in
);
87 get_grid_area_no_adjust(nlon_in
, nlat_in
, tmpx
, tmpy
, area_in
);
89 get_grid_area(nlon_out
, nlat_out
, lon_out
, lat_out
, area_out
);
93 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
95 ll_lon
= lon_in
[i1
]; ll_lat
= lat_in
[j1
];
96 ur_lon
= lon_in
[i1
+1]; ur_lat
= lat_in
[j1
+1];
97 for(j2
=0; j2
<ny2
; j2
++) for(i2
=0; i2
<nx2
; i2
++) {
101 y_in
[0] = lat_out
[j2
*nx2p
+i2
];
102 y_in
[1] = lat_out
[j2
*nx2p
+i2
+1];
103 y_in
[2] = lat_out
[(j2
+1)*nx2p
+i2
+1];
104 y_in
[3] = lat_out
[(j2
+1)*nx2p
+i2
];
105 if ( (y_in
[0]<=ll_lat
) && (y_in
[1]<=ll_lat
)
106 && (y_in
[2]<=ll_lat
) && (y_in
[3]<=ll_lat
) ) continue;
107 if ( (y_in
[0]>=ur_lat
) && (y_in
[1]>=ur_lat
)
108 && (y_in
[2]>=ur_lat
) && (y_in
[3]>=ur_lat
) ) continue;
110 x_in
[0] = lon_out
[j2
*nx2p
+i2
];
111 x_in
[1] = lon_out
[j2
*nx2p
+i2
+1];
112 x_in
[2] = lon_out
[(j2
+1)*nx2p
+i2
+1];
113 x_in
[3] = lon_out
[(j2
+1)*nx2p
+i2
];
114 n_in
= fix_lon(x_in
, y_in
, 4, (ll_lon
+ur_lon
)/2);
116 if ( (n_out
= clip ( x_in
, y_in
, n_in
, ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_out
, y_out
)) > 0 ) {
117 Xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
118 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
119 if( Xarea
/min_area
> AREA_RATIO_THRESH
) {
120 xgrid_area
[nxgrid
] = Xarea
;
126 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
137 } /* create_xgrid_1dx2d_order1 */
140 /*******************************************************************************
141 void create_xgrid_1dx2d_order1_ug
142 This routine generate exchange grids between two grids for the first order
143 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
144 and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
145 *******************************************************************************/
146 int create_xgrid_1dx2d_order1_ug_(const int *nlon_in
, const int *nlat_in
, const int *npts_out
,
147 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
148 const double *mask_in
, int *i_in
, int *j_in
, int *l_out
, double *xgrid_area
)
152 nxgrid
= create_xgrid_1dx2d_order1_ug(nlon_in
, nlat_in
, npts_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
,
153 i_in
, j_in
, l_out
, xgrid_area
);
158 int create_xgrid_1dx2d_order1_ug(const int *nlon_in
, const int *nlat_in
, const int *npts_out
, const double *lon_in
,
159 const double *lat_in
, const double *lon_out
, const double *lat_out
,
160 const double *mask_in
, int *i_in
, int *j_in
, int *l_out
, double *xgrid_area
)
163 int nx1
, ny1
, nx1p
, nv
, npts2
;
164 int i1
, j1
, l2
, nxgrid
;
165 double ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_in
[MV
], y_in
[MV
], x_out
[MV
], y_out
[MV
];
166 double *area_in
, *area_out
, min_area
;
177 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
178 area_out
= (double *)malloc(npts2
*sizeof(double));
179 tmpx
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
180 tmpy
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
181 for(j1
=0; j1
<=ny1
; j1
++) for(i1
=0; i1
<=nx1
; i1
++) {
182 tmpx
[j1
*nx1p
+i1
] = lon_in
[i1
];
183 tmpy
[j1
*nx1p
+i1
] = lat_in
[j1
];
185 /* This is just a temporary fix to solve the issue that there is one point in zonal direction */
187 get_grid_area(nlon_in
, nlat_in
, tmpx
, tmpy
, area_in
);
189 get_grid_area_no_adjust(nlon_in
, nlat_in
, tmpx
, tmpy
, area_in
);
191 get_grid_area_ug(npts_out
, lon_out
, lat_out
, area_out
);
195 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
197 ll_lon
= lon_in
[i1
]; ll_lat
= lat_in
[j1
];
198 ur_lon
= lon_in
[i1
+1]; ur_lat
= lat_in
[j1
+1];
199 for(l2
=0; l2
<npts2
; l2
++) {
203 y_in
[0] = lat_out
[l2
*nv
];
204 y_in
[1] = lat_out
[l2
*nv
+1];
205 y_in
[2] = lat_out
[l2
*nv
+2];
206 y_in
[3] = lat_out
[l2
*nv
+3];
207 if ( (y_in
[0]<=ll_lat
) && (y_in
[1]<=ll_lat
)
208 && (y_in
[2]<=ll_lat
) && (y_in
[3]<=ll_lat
) ) continue;
209 if ( (y_in
[0]>=ur_lat
) && (y_in
[1]>=ur_lat
)
210 && (y_in
[2]>=ur_lat
) && (y_in
[3]>=ur_lat
) ) continue;
212 x_in
[0] = lon_out
[l2
*nv
];
213 x_in
[1] = lon_out
[l2
*nv
+1];
214 x_in
[2] = lon_out
[l2
*nv
+2];
215 x_in
[3] = lon_out
[l2
*nv
+3];
216 n_in
= fix_lon(x_in
, y_in
, 4, (ll_lon
+ur_lon
)/2);
218 if ( (n_out
= clip ( x_in
, y_in
, n_in
, ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_out
, y_out
)) > 0 ) {
219 Xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
220 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[l2
]);
221 if( Xarea
/min_area
> AREA_RATIO_THRESH
) {
222 xgrid_area
[nxgrid
] = Xarea
;
227 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
238 } /* create_xgrid_1dx2d_order1_ug */
240 /********************************************************************************
241 void create_xgrid_1dx2d_order2
242 This routine generate exchange grids between two grids for the second order
243 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
244 and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
245 ********************************************************************************/
246 int create_xgrid_1dx2d_order2_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
247 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
248 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
249 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
252 nxgrid
= create_xgrid_1dx2d_order2(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
, i_in
,
253 j_in
, i_out
, j_out
, xgrid_area
, xgrid_clon
, xgrid_clat
);
257 int create_xgrid_1dx2d_order2(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
258 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
259 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
260 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
263 int nx1
, ny1
, nx2
, ny2
, nx1p
, nx2p
;
264 int i1
, j1
, i2
, j2
, nxgrid
;
265 double ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_in
[MV
], y_in
[MV
], x_out
[MV
], y_out
[MV
];
266 double *area_in
, *area_out
, min_area
;
278 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
279 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
280 tmpx
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
281 tmpy
= (double *)malloc((nx1
+1)*(ny1
+1)*sizeof(double));
282 for(j1
=0; j1
<=ny1
; j1
++) for(i1
=0; i1
<=nx1
; i1
++) {
283 tmpx
[j1
*nx1p
+i1
] = lon_in
[i1
];
284 tmpy
[j1
*nx1p
+i1
] = lat_in
[j1
];
286 get_grid_area(nlon_in
, nlat_in
, tmpx
, tmpy
, area_in
);
287 get_grid_area(nlon_out
, nlat_out
, lon_out
, lat_out
, area_out
);
291 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
293 ll_lon
= lon_in
[i1
]; ll_lat
= lat_in
[j1
];
294 ur_lon
= lon_in
[i1
+1]; ur_lat
= lat_in
[j1
+1];
295 for(j2
=0; j2
<ny2
; j2
++) for(i2
=0; i2
<nx2
; i2
++) {
297 double xarea
, lon_in_avg
;
299 y_in
[0] = lat_out
[j2
*nx2p
+i2
];
300 y_in
[1] = lat_out
[j2
*nx2p
+i2
+1];
301 y_in
[2] = lat_out
[(j2
+1)*nx2p
+i2
+1];
302 y_in
[3] = lat_out
[(j2
+1)*nx2p
+i2
];
303 if ( (y_in
[0]<=ll_lat
) && (y_in
[1]<=ll_lat
)
304 && (y_in
[2]<=ll_lat
) && (y_in
[3]<=ll_lat
) ) continue;
305 if ( (y_in
[0]>=ur_lat
) && (y_in
[1]>=ur_lat
)
306 && (y_in
[2]>=ur_lat
) && (y_in
[3]>=ur_lat
) ) continue;
308 x_in
[0] = lon_out
[j2
*nx2p
+i2
];
309 x_in
[1] = lon_out
[j2
*nx2p
+i2
+1];
310 x_in
[2] = lon_out
[(j2
+1)*nx2p
+i2
+1];
311 x_in
[3] = lon_out
[(j2
+1)*nx2p
+i2
];
312 n_in
= fix_lon(x_in
, y_in
, 4, (ll_lon
+ur_lon
)/2);
313 lon_in_avg
= avgval_double(n_in
, x_in
);
315 if ( (n_out
= clip ( x_in
, y_in
, n_in
, ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_out
, y_out
)) > 0 ) {
316 xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
317 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
318 if(xarea
/min_area
> AREA_RATIO_THRESH
) {
319 xgrid_area
[nxgrid
] = xarea
;
320 xgrid_clon
[nxgrid
] = poly_ctrlon(x_out
, y_out
, n_out
, lon_in_avg
);
321 xgrid_clat
[nxgrid
] = poly_ctrlat (x_out
, y_out
, n_out
);
327 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
337 } /* create_xgrid_1dx2d_order2 */
339 /*******************************************************************************
340 void create_xgrid_2dx1d_order1
341 This routine generate exchange grids between two grids for the first order
342 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
343 and lon_out,lat_out are 1-D grid bounds, lon_in,lat_in are geographic grid location of grid cell bounds.
344 mask is on grid lon_in/lat_in.
345 *******************************************************************************/
346 int create_xgrid_2dx1d_order1_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
347 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
348 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
,
349 int *j_out
, double *xgrid_area
)
353 nxgrid
= create_xgrid_2dx1d_order1(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
,
354 i_in
, j_in
, i_out
, j_out
, xgrid_area
);
358 int create_xgrid_2dx1d_order1(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
, const double *lon_in
,
359 const double *lat_in
, const double *lon_out
, const double *lat_out
,
360 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
,
361 int *j_out
, double *xgrid_area
)
364 int nx1
, ny1
, nx2
, ny2
, nx1p
, nx2p
;
365 int i1
, j1
, i2
, j2
, nxgrid
;
366 double ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_in
[MV
], y_in
[MV
], x_out
[MV
], y_out
[MV
];
367 double *area_in
, *area_out
, min_area
;
381 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
382 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
383 tmpx
= (double *)malloc((nx2
+1)*(ny2
+1)*sizeof(double));
384 tmpy
= (double *)malloc((nx2
+1)*(ny2
+1)*sizeof(double));
385 for(j2
=0; j2
<=ny2
; j2
++) for(i2
=0; i2
<=nx2
; i2
++) {
386 tmpx
[j2
*nx2p
+i2
] = lon_out
[i2
];
387 tmpy
[j2
*nx2p
+i2
] = lat_out
[j2
];
389 get_grid_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area_in
);
390 get_grid_area(nlon_out
, nlat_out
, tmpx
, tmpy
, area_out
);
395 for(j2
=0; j2
<ny2
; j2
++) for(i2
=0; i2
<nx2
; i2
++) {
397 ll_lon
= lon_out
[i2
]; ll_lat
= lat_out
[j2
];
398 ur_lon
= lon_out
[i2
+1]; ur_lat
= lat_out
[j2
+1];
399 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
401 y_in
[0] = lat_in
[j1
*nx1p
+i1
];
402 y_in
[1] = lat_in
[j1
*nx1p
+i1
+1];
403 y_in
[2] = lat_in
[(j1
+1)*nx1p
+i1
+1];
404 y_in
[3] = lat_in
[(j1
+1)*nx1p
+i1
];
405 if ( (y_in
[0]<=ll_lat
) && (y_in
[1]<=ll_lat
)
406 && (y_in
[2]<=ll_lat
) && (y_in
[3]<=ll_lat
) ) continue;
407 if ( (y_in
[0]>=ur_lat
) && (y_in
[1]>=ur_lat
)
408 && (y_in
[2]>=ur_lat
) && (y_in
[3]>=ur_lat
) ) continue;
410 x_in
[0] = lon_in
[j1
*nx1p
+i1
];
411 x_in
[1] = lon_in
[j1
*nx1p
+i1
+1];
412 x_in
[2] = lon_in
[(j1
+1)*nx1p
+i1
+1];
413 x_in
[3] = lon_in
[(j1
+1)*nx1p
+i1
];
415 n_in
= fix_lon(x_in
, y_in
, 4, (ll_lon
+ur_lon
)/2);
417 if ( (n_out
= clip ( x_in
, y_in
, n_in
, ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_out
, y_out
)) > 0 ) {
418 Xarea
= poly_area ( x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
419 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
420 if( Xarea
/min_area
> AREA_RATIO_THRESH
) {
421 xgrid_area
[nxgrid
] = Xarea
;
427 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
438 } /* create_xgrid_2dx1d_order1 */
441 /********************************************************************************
442 void create_xgrid_2dx1d_order2
443 This routine generate exchange grids between two grids for the second order
444 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
445 and lon_out,lat_out are 1-D grid bounds, lon_in,lat_in are geographic grid location of grid cell bounds.
446 mask is on grid lon_in/lat_in.
447 ********************************************************************************/
448 int create_xgrid_2dx1d_order2_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
449 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
450 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
451 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
454 nxgrid
= create_xgrid_2dx1d_order2(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
, i_in
,
455 j_in
, i_out
, j_out
, xgrid_area
, xgrid_clon
, xgrid_clat
);
460 int create_xgrid_2dx1d_order2(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
461 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
462 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
463 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
466 int nx1
, ny1
, nx2
, ny2
, nx1p
, nx2p
;
467 int i1
, j1
, i2
, j2
, nxgrid
;
468 double ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_in
[MV
], y_in
[MV
], x_out
[MV
], y_out
[MV
];
470 double *area_in
, *area_out
, min_area
;
485 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
486 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
487 tmpx
= (double *)malloc((nx2
+1)*(ny2
+1)*sizeof(double));
488 tmpy
= (double *)malloc((nx2
+1)*(ny2
+1)*sizeof(double));
489 for(j2
=0; j2
<=ny2
; j2
++) for(i2
=0; i2
<=nx2
; i2
++) {
490 tmpx
[j2
*nx2p
+i2
] = lon_out
[i2
];
491 tmpy
[j2
*nx2p
+i2
] = lat_out
[j2
];
493 get_grid_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area_in
);
494 get_grid_area(nlon_out
, nlat_out
, tmpx
, tmpy
, area_out
);
499 for(j2
=0; j2
<ny2
; j2
++) for(i2
=0; i2
<nx2
; i2
++) {
501 ll_lon
= lon_out
[i2
]; ll_lat
= lat_out
[j2
];
502 ur_lon
= lon_out
[i2
+1]; ur_lat
= lat_out
[j2
+1];
503 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
505 y_in
[0] = lat_in
[j1
*nx1p
+i1
];
506 y_in
[1] = lat_in
[j1
*nx1p
+i1
+1];
507 y_in
[2] = lat_in
[(j1
+1)*nx1p
+i1
+1];
508 y_in
[3] = lat_in
[(j1
+1)*nx1p
+i1
];
509 if ( (y_in
[0]<=ll_lat
) && (y_in
[1]<=ll_lat
)
510 && (y_in
[2]<=ll_lat
) && (y_in
[3]<=ll_lat
) ) continue;
511 if ( (y_in
[0]>=ur_lat
) && (y_in
[1]>=ur_lat
)
512 && (y_in
[2]>=ur_lat
) && (y_in
[3]>=ur_lat
) ) continue;
514 x_in
[0] = lon_in
[j1
*nx1p
+i1
];
515 x_in
[1] = lon_in
[j1
*nx1p
+i1
+1];
516 x_in
[2] = lon_in
[(j1
+1)*nx1p
+i1
+1];
517 x_in
[3] = lon_in
[(j1
+1)*nx1p
+i1
];
519 n_in
= fix_lon(x_in
, y_in
, 4, (ll_lon
+ur_lon
)/2);
520 lon_in_avg
= avgval_double(n_in
, x_in
);
522 if ( (n_out
= clip ( x_in
, y_in
, n_in
, ll_lon
, ll_lat
, ur_lon
, ur_lat
, x_out
, y_out
)) > 0 ) {
523 xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
524 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
525 if(xarea
/min_area
> AREA_RATIO_THRESH
) {
526 xgrid_area
[nxgrid
] = xarea
;
527 xgrid_clon
[nxgrid
] = poly_ctrlon(x_out
, y_out
, n_out
, lon_in_avg
);
528 xgrid_clat
[nxgrid
] = poly_ctrlat (x_out
, y_out
, n_out
);
534 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
545 } /* create_xgrid_2dx1d_order2 */
547 /*******************************************************************************
548 void create_xgrid_2DX2D_order1
549 This routine generate exchange grids between two grids for the first order
550 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
551 and lon_in,lat_in, lon_out,lat_out are geographic grid location of grid cell bounds.
552 mask is on grid lon_in/lat_in.
553 *******************************************************************************/
554 int create_xgrid_2dx2d_order1_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
555 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
556 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
,
557 int *j_out
, double *xgrid_area
)
561 nxgrid
= create_xgrid_2dx2d_order1(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
,
562 i_in
, j_in
, i_out
, j_out
, xgrid_area
);
566 int create_xgrid_2dx2d_order1(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
567 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
568 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
,
569 int *j_out
, double *xgrid_area
)
572 int nx1
, nx2
, ny1
, ny2
, nx1p
, nx2p
, nxgrid
;
573 double *area_in
, *area_out
;
575 int *istart2
=NULL
, *iend2
=NULL
;
576 int npts_left
, nblks_left
, pos
, m
, npts_my
, ij
;
577 double *lon_out_min_list
,*lon_out_max_list
,*lon_out_avg
,*lat_out_min_list
,*lat_out_max_list
;
578 double *lon_out_list
, *lat_out_list
;
579 int *pnxgrid
=NULL
, *pstart
;
580 int *pi_in
=NULL
, *pj_in
=NULL
, *pi_out
=NULL
, *pj_out
=NULL
;
581 double *pxgrid_area
=NULL
;
583 int nthreads
, nxgrid_block_max
;
592 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
593 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
594 get_grid_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area_in
);
595 get_grid_area(nlon_out
, nlat_out
, lon_out
, lat_out
, area_out
);
600 nthreads
= omp_get_num_threads();
605 istart2
= (int *)malloc(nblocks
*sizeof(int));
606 iend2
= (int *)malloc(nblocks
*sizeof(int));
608 pstart
= (int *)malloc(nblocks
*sizeof(int));
609 pnxgrid
= (int *)malloc(nblocks
*sizeof(int));
611 nxgrid_block_max
= MAXXGRID
/nblocks
;
613 for(m
=0; m
<nblocks
; m
++) {
615 pstart
[m
] = m
*nxgrid_block_max
;
623 pxgrid_area
= xgrid_area
;
626 pi_in
= (int *)malloc(MAXXGRID
*sizeof(int));
627 pj_in
= (int *)malloc(MAXXGRID
*sizeof(int));
628 pi_out
= (int *)malloc(MAXXGRID
*sizeof(int));
629 pj_out
= (int *)malloc(MAXXGRID
*sizeof(int));
630 pxgrid_area
= (double *)malloc(MAXXGRID
*sizeof(double));
634 nblks_left
= nblocks
;
636 for(m
=0; m
<nblocks
; m
++) {
638 npts_my
= npts_left
/nblks_left
;
639 iend2
[m
] = istart2
[m
] + npts_my
- 1;
641 npts_left
-= npts_my
;
645 lon_out_min_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
646 lon_out_max_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
647 lat_out_min_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
648 lat_out_max_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
649 lon_out_avg
= (double *)malloc(nx2
*ny2
*sizeof(double));
650 n2_list
= (int *)malloc(nx2
*ny2
*sizeof(int));
651 lon_out_list
= (double *)malloc(MAX_V
*nx2
*ny2
*sizeof(double));
652 lat_out_list
= (double *)malloc(MAX_V
*nx2
*ny2
*sizeof(double));
654 #pragma omp parallel for default(none) shared(nx2,ny2,nx2p,lon_out,lat_out,lat_out_min_list, \
655 lat_out_max_list,lon_out_min_list,lon_out_max_list, \
656 lon_out_avg,n2_list,lon_out_list,lat_out_list)
658 for(ij
=0; ij
<nx2
*ny2
; ij
++){
659 int i2
, j2
, n
, n0
, n1
, n2
, n3
, n2_in
, l
;
660 double x2_in
[MV
], y2_in
[MV
];
664 n0
= j2
*nx2p
+i2
; n1
= j2
*nx2p
+i2
+1;
665 n2
= (j2
+1)*nx2p
+i2
+1; n3
= (j2
+1)*nx2p
+i2
;
666 x2_in
[0] = lon_out
[n0
]; y2_in
[0] = lat_out
[n0
];
667 x2_in
[1] = lon_out
[n1
]; y2_in
[1] = lat_out
[n1
];
668 x2_in
[2] = lon_out
[n2
]; y2_in
[2] = lat_out
[n2
];
669 x2_in
[3] = lon_out
[n3
]; y2_in
[3] = lat_out
[n3
];
671 lat_out_min_list
[n
] = minval_double(4, y2_in
);
672 lat_out_max_list
[n
] = maxval_double(4, y2_in
);
673 n2_in
= fix_lon(x2_in
, y2_in
, 4, M_PI
);
674 if(n2_in
> MAX_V
) error_handler("create_xgrid.c: n2_in is greater than MAX_V");
675 lon_out_min_list
[n
] = minval_double(n2_in
, x2_in
);
676 lon_out_max_list
[n
] = maxval_double(n2_in
, x2_in
);
677 lon_out_avg
[n
] = avgval_double(n2_in
, x2_in
);
679 for(l
=0; l
<n2_in
; l
++) {
680 lon_out_list
[n
*MAX_V
+l
] = x2_in
[l
];
681 lat_out_list
[n
*MAX_V
+l
] = y2_in
[l
];
688 #pragma omp parallel for default(none) shared(nblocks,nx1,ny1,nx1p,mask_in,lon_in,lat_in, \
689 istart2,iend2,nx2,lat_out_min_list,lat_out_max_list, \
690 n2_list,lon_out_list,lat_out_list,lon_out_min_list, \
691 lon_out_max_list,lon_out_avg,area_in,area_out, \
692 pxgrid_area,pnxgrid,pi_in,pj_in,pi_out,pj_out,pstart,nthreads)
694 for(m
=0; m
<nblocks
; m
++) {
696 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
697 int n0
, n1
, n2
, n3
, l
,n1_in
;
698 double lat_in_min
,lat_in_max
,lon_in_min
,lon_in_max
,lon_in_avg
;
699 double x1_in
[MV
], y1_in
[MV
], x_out
[MV
], y_out
[MV
];
701 n0
= j1
*nx1p
+i1
; n1
= j1
*nx1p
+i1
+1;
702 n2
= (j1
+1)*nx1p
+i1
+1; n3
= (j1
+1)*nx1p
+i1
;
703 x1_in
[0] = lon_in
[n0
]; y1_in
[0] = lat_in
[n0
];
704 x1_in
[1] = lon_in
[n1
]; y1_in
[1] = lat_in
[n1
];
705 x1_in
[2] = lon_in
[n2
]; y1_in
[2] = lat_in
[n2
];
706 x1_in
[3] = lon_in
[n3
]; y1_in
[3] = lat_in
[n3
];
707 lat_in_min
= minval_double(4, y1_in
);
708 lat_in_max
= maxval_double(4, y1_in
);
709 n1_in
= fix_lon(x1_in
, y1_in
, 4, M_PI
);
710 lon_in_min
= minval_double(n1_in
, x1_in
);
711 lon_in_max
= maxval_double(n1_in
, x1_in
);
712 lon_in_avg
= avgval_double(n1_in
, x1_in
);
713 for(ij
=istart2
[m
]; ij
<=iend2
[m
]; ij
++) {
714 int n_out
, i2
, j2
, n2_in
;
715 double xarea
, dx
, lon_out_min
, lon_out_max
;
716 double x2_in
[MAX_V
], y2_in
[MAX_V
];
721 if(lat_out_min_list
[ij
] >= lat_in_max
|| lat_out_max_list
[ij
] <= lat_in_min
) continue;
722 /* adjust x2_in according to lon_in_avg*/
724 for(l
=0; l
<n2_in
; l
++) {
725 x2_in
[l
] = lon_out_list
[ij
*MAX_V
+l
];
726 y2_in
[l
] = lat_out_list
[ij
*MAX_V
+l
];
728 lon_out_min
= lon_out_min_list
[ij
];
729 lon_out_max
= lon_out_max_list
[ij
];
730 dx
= lon_out_avg
[ij
] - lon_in_avg
;
734 for (l
=0; l
<n2_in
; l
++) x2_in
[l
] += TPI
;
736 else if (dx
> M_PI
) {
739 for (l
=0; l
<n2_in
; l
++) x2_in
[l
] -= TPI
;
742 /* x2_in should in the same range as x1_in after lon_fix, so no need to
743 consider cyclic condition
745 if(lon_out_min
>= lon_in_max
|| lon_out_max
<= lon_in_min
) continue;
746 if ( (n_out
= clip_2dx2d( x1_in
, y1_in
, n1_in
, x2_in
, y2_in
, n2_in
, x_out
, y_out
)) > 0) {
749 xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
750 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
751 if( xarea
/min_area
> AREA_RATIO_THRESH
) {
753 if(pnxgrid
[m
]>= MAXXGRID
/nthreads
)
754 error_handler("nxgrid is greater than MAXXGRID/nthreads, increase MAXXGRID, decrease nthreads, or increase number of MPI ranks");
755 nn
= pstart
[m
] + pnxgrid
[m
]-1;
757 pxgrid_area
[nn
] = xarea
;
770 /*copy data if nblocks > 1 */
782 for(m
=0; m
<nblocks
; m
++) {
783 for(i
=0; i
<pnxgrid
[m
]; i
++) {
785 i_in
[nxgrid
] = pi_in
[nn
];
786 j_in
[nxgrid
] = pj_in
[nn
];
787 i_out
[nxgrid
] = pi_out
[nn
];
788 j_out
[nxgrid
] = pj_out
[nn
];
789 xgrid_area
[nxgrid
] = pxgrid_area
[nn
];
802 free(lon_out_min_list
);
803 free(lon_out_max_list
);
804 free(lat_out_min_list
);
805 free(lat_out_max_list
);
813 }/* get_xgrid_2Dx2D_order1 */
815 /********************************************************************************
816 void create_xgrid_2dx1d_order2
817 This routine generate exchange grids between two grids for the second order
818 conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
819 and lon_in,lat_in, lon_out,lat_out are geographic grid location of grid cell bounds.
820 mask is on grid lon_in/lat_in.
821 ********************************************************************************/
822 int create_xgrid_2dx2d_order2_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
823 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
824 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
825 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
828 nxgrid
= create_xgrid_2dx2d_order2(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
, mask_in
, i_in
,
829 j_in
, i_out
, j_out
, xgrid_area
, xgrid_clon
, xgrid_clat
);
833 int create_xgrid_2dx2d_order2(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
834 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
835 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
836 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
839 int nx1
, nx2
, ny1
, ny2
, nx1p
, nx2p
, nxgrid
;
840 double *area_in
, *area_out
;
842 int *istart2
=NULL
, *iend2
=NULL
;
843 int npts_left
, nblks_left
, pos
, m
, npts_my
, ij
;
844 double *lon_out_min_list
,*lon_out_max_list
,*lon_out_avg
,*lat_out_min_list
,*lat_out_max_list
;
845 double *lon_out_list
, *lat_out_list
;
846 int *pnxgrid
=NULL
, *pstart
;
847 int *pi_in
=NULL
, *pj_in
=NULL
, *pi_out
=NULL
, *pj_out
=NULL
;
848 double *pxgrid_area
=NULL
, *pxgrid_clon
=NULL
, *pxgrid_clat
=NULL
;
850 int nthreads
, nxgrid_block_max
;
859 area_in
= (double *)malloc(nx1
*ny1
*sizeof(double));
860 area_out
= (double *)malloc(nx2
*ny2
*sizeof(double));
861 get_grid_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area_in
);
862 get_grid_area(nlon_out
, nlat_out
, lon_out
, lat_out
, area_out
);
867 nthreads
= omp_get_num_threads();
872 istart2
= (int *)malloc(nblocks
*sizeof(int));
873 iend2
= (int *)malloc(nblocks
*sizeof(int));
875 pstart
= (int *)malloc(nblocks
*sizeof(int));
876 pnxgrid
= (int *)malloc(nblocks
*sizeof(int));
878 nxgrid_block_max
= MAXXGRID
/nblocks
;
880 for(m
=0; m
<nblocks
; m
++) {
882 pstart
[m
] = m
*nxgrid_block_max
;
890 pxgrid_area
= xgrid_area
;
891 pxgrid_clon
= xgrid_clon
;
892 pxgrid_clat
= xgrid_clat
;
895 pi_in
= (int *)malloc(MAXXGRID
*sizeof(int));
896 pj_in
= (int *)malloc(MAXXGRID
*sizeof(int));
897 pi_out
= (int *)malloc(MAXXGRID
*sizeof(int));
898 pj_out
= (int *)malloc(MAXXGRID
*sizeof(int));
899 pxgrid_area
= (double *)malloc(MAXXGRID
*sizeof(double));
900 pxgrid_clon
= (double *)malloc(MAXXGRID
*sizeof(double));
901 pxgrid_clat
= (double *)malloc(MAXXGRID
*sizeof(double));
905 nblks_left
= nblocks
;
907 for(m
=0; m
<nblocks
; m
++) {
909 npts_my
= npts_left
/nblks_left
;
910 iend2
[m
] = istart2
[m
] + npts_my
- 1;
912 npts_left
-= npts_my
;
916 lon_out_min_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
917 lon_out_max_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
918 lat_out_min_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
919 lat_out_max_list
= (double *)malloc(nx2
*ny2
*sizeof(double));
920 lon_out_avg
= (double *)malloc(nx2
*ny2
*sizeof(double));
921 n2_list
= (int *)malloc(nx2
*ny2
*sizeof(int));
922 lon_out_list
= (double *)malloc(MAX_V
*nx2
*ny2
*sizeof(double));
923 lat_out_list
= (double *)malloc(MAX_V
*nx2
*ny2
*sizeof(double));
925 #pragma omp parallel for default(none) shared(nx2,ny2,nx2p,lon_out,lat_out,lat_out_min_list, \
926 lat_out_max_list,lon_out_min_list,lon_out_max_list, \
927 lon_out_avg,n2_list,lon_out_list,lat_out_list)
929 for(ij
=0; ij
<nx2
*ny2
; ij
++){
930 int i2
, j2
, n
, n0
, n1
, n2
, n3
, n2_in
, l
;
931 double x2_in
[MV
], y2_in
[MV
];
935 n0
= j2
*nx2p
+i2
; n1
= j2
*nx2p
+i2
+1;
936 n2
= (j2
+1)*nx2p
+i2
+1; n3
= (j2
+1)*nx2p
+i2
;
937 x2_in
[0] = lon_out
[n0
]; y2_in
[0] = lat_out
[n0
];
938 x2_in
[1] = lon_out
[n1
]; y2_in
[1] = lat_out
[n1
];
939 x2_in
[2] = lon_out
[n2
]; y2_in
[2] = lat_out
[n2
];
940 x2_in
[3] = lon_out
[n3
]; y2_in
[3] = lat_out
[n3
];
942 lat_out_min_list
[n
] = minval_double(4, y2_in
);
943 lat_out_max_list
[n
] = maxval_double(4, y2_in
);
944 n2_in
= fix_lon(x2_in
, y2_in
, 4, M_PI
);
945 if(n2_in
> MAX_V
) error_handler("create_xgrid.c: n2_in is greater than MAX_V");
946 lon_out_min_list
[n
] = minval_double(n2_in
, x2_in
);
947 lon_out_max_list
[n
] = maxval_double(n2_in
, x2_in
);
948 lon_out_avg
[n
] = avgval_double(n2_in
, x2_in
);
950 for(l
=0; l
<n2_in
; l
++) {
951 lon_out_list
[n
*MAX_V
+l
] = x2_in
[l
];
952 lat_out_list
[n
*MAX_V
+l
] = y2_in
[l
];
959 #pragma omp parallel for default(none) shared(nblocks,nx1,ny1,nx1p,mask_in,lon_in,lat_in, \
960 istart2,iend2,nx2,lat_out_min_list,lat_out_max_list, \
961 n2_list,lon_out_list,lat_out_list,lon_out_min_list, \
962 lon_out_max_list,lon_out_avg,area_in,area_out, \
963 pxgrid_area,pnxgrid,pxgrid_clon,pxgrid_clat,pi_in, \
964 pj_in,pi_out,pj_out,pstart,nthreads)
966 for(m
=0; m
<nblocks
; m
++) {
968 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
969 int n0
, n1
, n2
, n3
, l
,n1_in
;
970 double lat_in_min
,lat_in_max
,lon_in_min
,lon_in_max
,lon_in_avg
;
971 double x1_in
[MV
], y1_in
[MV
], x_out
[MV
], y_out
[MV
];
973 n0
= j1
*nx1p
+i1
; n1
= j1
*nx1p
+i1
+1;
974 n2
= (j1
+1)*nx1p
+i1
+1; n3
= (j1
+1)*nx1p
+i1
;
975 x1_in
[0] = lon_in
[n0
]; y1_in
[0] = lat_in
[n0
];
976 x1_in
[1] = lon_in
[n1
]; y1_in
[1] = lat_in
[n1
];
977 x1_in
[2] = lon_in
[n2
]; y1_in
[2] = lat_in
[n2
];
978 x1_in
[3] = lon_in
[n3
]; y1_in
[3] = lat_in
[n3
];
979 lat_in_min
= minval_double(4, y1_in
);
980 lat_in_max
= maxval_double(4, y1_in
);
981 n1_in
= fix_lon(x1_in
, y1_in
, 4, M_PI
);
982 lon_in_min
= minval_double(n1_in
, x1_in
);
983 lon_in_max
= maxval_double(n1_in
, x1_in
);
984 lon_in_avg
= avgval_double(n1_in
, x1_in
);
985 for(ij
=istart2
[m
]; ij
<=iend2
[m
]; ij
++) {
986 int n_out
, i2
, j2
, n2_in
;
987 double xarea
, dx
, lon_out_min
, lon_out_max
;
988 double x2_in
[MAX_V
], y2_in
[MAX_V
];
993 if(lat_out_min_list
[ij
] >= lat_in_max
|| lat_out_max_list
[ij
] <= lat_in_min
) continue;
994 /* adjust x2_in according to lon_in_avg*/
996 for(l
=0; l
<n2_in
; l
++) {
997 x2_in
[l
] = lon_out_list
[ij
*MAX_V
+l
];
998 y2_in
[l
] = lat_out_list
[ij
*MAX_V
+l
];
1000 lon_out_min
= lon_out_min_list
[ij
];
1001 lon_out_max
= lon_out_max_list
[ij
];
1002 dx
= lon_out_avg
[ij
] - lon_in_avg
;
1006 for (l
=0; l
<n2_in
; l
++) x2_in
[l
] += TPI
;
1008 else if (dx
> M_PI
) {
1011 for (l
=0; l
<n2_in
; l
++) x2_in
[l
] -= TPI
;
1014 /* x2_in should in the same range as x1_in after lon_fix, so no need to
1015 consider cyclic condition
1017 if(lon_out_min
>= lon_in_max
|| lon_out_max
<= lon_in_min
) continue;
1018 if ( (n_out
= clip_2dx2d( x1_in
, y1_in
, n1_in
, x2_in
, y2_in
, n2_in
, x_out
, y_out
)) > 0) {
1021 xarea
= poly_area (x_out
, y_out
, n_out
) * mask_in
[j1
*nx1
+i1
];
1022 min_area
= min(area_in
[j1
*nx1
+i1
], area_out
[j2
*nx2
+i2
]);
1023 if( xarea
/min_area
> AREA_RATIO_THRESH
) {
1025 if(pnxgrid
[m
]>= MAXXGRID
/nthreads
)
1026 error_handler("nxgrid is greater than MAXXGRID/nthreads, increase MAXXGRID, decrease nthreads, or increase number of MPI ranks");
1027 nn
= pstart
[m
] + pnxgrid
[m
]-1;
1028 pxgrid_area
[nn
] = xarea
;
1029 pxgrid_clon
[nn
] = poly_ctrlon(x_out
, y_out
, n_out
, lon_in_avg
);
1030 pxgrid_clat
[nn
] = poly_ctrlat (x_out
, y_out
, n_out
);
1041 /*copy data if nblocks > 1 */
1043 nxgrid
= pnxgrid
[0];
1055 for(m
=0; m
<nblocks
; m
++) {
1056 for(i
=0; i
<pnxgrid
[m
]; i
++) {
1058 i_in
[nxgrid
] = pi_in
[nn
];
1059 j_in
[nxgrid
] = pj_in
[nn
];
1060 i_out
[nxgrid
] = pi_out
[nn
];
1061 j_out
[nxgrid
] = pj_out
[nn
];
1062 xgrid_area
[nxgrid
] = pxgrid_area
[nn
];
1063 xgrid_clon
[nxgrid
] = pxgrid_clon
[nn
];
1064 xgrid_clat
[nxgrid
] = pxgrid_clat
[nn
];
1079 free(lon_out_min_list
);
1080 free(lon_out_max_list
);
1081 free(lat_out_min_list
);
1082 free(lat_out_max_list
);
1090 }/* get_xgrid_2Dx2D_order2 */
1092 int create_xgrid_great_circle_(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
1093 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
1094 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
1095 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
1098 nxgrid
= create_xgrid_great_circle(nlon_in
, nlat_in
, nlon_out
, nlat_out
, lon_in
, lat_in
, lon_out
, lat_out
,
1099 mask_in
, i_in
, j_in
, i_out
, j_out
, xgrid_area
, xgrid_clon
, xgrid_clat
);
1104 int create_xgrid_great_circle(const int *nlon_in
, const int *nlat_in
, const int *nlon_out
, const int *nlat_out
,
1105 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
1106 const double *mask_in
, int *i_in
, int *j_in
, int *i_out
, int *j_out
,
1107 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
1110 int nx1
, nx2
, ny1
, ny2
, nx1p
, nx2p
, ny1p
, ny2p
, nxgrid
, n1_in
, n2_in
;
1111 int n0
, n1
, n2
, n3
, i1
, j1
, i2
, j2
;
1112 double x1_in
[MV
], y1_in
[MV
], z1_in
[MV
];
1113 double x2_in
[MV
], y2_in
[MV
], z2_in
[MV
];
1114 double x_out
[MV
], y_out
[MV
], z_out
[MV
];
1115 double *x1
=NULL
, *y1
=NULL
, *z1
=NULL
;
1116 double *x2
=NULL
, *y2
=NULL
, *z2
=NULL
;
1118 double *area1
, *area2
, min_area
;
1130 /* first convert lon-lat to cartesian coordinates */
1131 x1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1132 y1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1133 z1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1134 x2
= (double *)malloc(nx2p
*ny2p
*sizeof(double));
1135 y2
= (double *)malloc(nx2p
*ny2p
*sizeof(double));
1136 z2
= (double *)malloc(nx2p
*ny2p
*sizeof(double));
1138 latlon2xyz(nx1p
*ny1p
, lon_in
, lat_in
, x1
, y1
, z1
);
1139 latlon2xyz(nx2p
*ny2p
, lon_out
, lat_out
, x2
, y2
, z2
);
1141 area1
= (double *)malloc(nx1
*ny1
*sizeof(double));
1142 area2
= (double *)malloc(nx2
*ny2
*sizeof(double));
1143 get_grid_great_circle_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area1
);
1144 get_grid_great_circle_area(nlon_out
, nlat_out
, lon_out
, lat_out
, area2
);
1148 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
1150 n0
= j1
*nx1p
+i1
; n1
= (j1
+1)*nx1p
+i1
;
1151 n2
= (j1
+1)*nx1p
+i1
+1; n3
= j1
*nx1p
+i1
+1;
1152 x1_in
[0] = x1
[n0
]; y1_in
[0] = y1
[n0
]; z1_in
[0] = z1
[n0
];
1153 x1_in
[1] = x1
[n1
]; y1_in
[1] = y1
[n1
]; z1_in
[1] = z1
[n1
];
1154 x1_in
[2] = x1
[n2
]; y1_in
[2] = y1
[n2
]; z1_in
[2] = z1
[n2
];
1155 x1_in
[3] = x1
[n3
]; y1_in
[3] = y1
[n3
]; z1_in
[3] = z1
[n3
];
1157 for(j2
=0; j2
<ny2
; j2
++) for(i2
=0; i2
<nx2
; i2
++) {
1161 n0
= j2
*nx2p
+i2
; n1
= (j2
+1)*nx2p
+i2
;
1162 n2
= (j2
+1)*nx2p
+i2
+1; n3
= j2
*nx2p
+i2
+1;
1163 x2_in
[0] = x2
[n0
]; y2_in
[0] = y2
[n0
]; z2_in
[0] = z2
[n0
];
1164 x2_in
[1] = x2
[n1
]; y2_in
[1] = y2
[n1
]; z2_in
[1] = z2
[n1
];
1165 x2_in
[2] = x2
[n2
]; y2_in
[2] = y2
[n2
]; z2_in
[2] = z2
[n2
];
1166 x2_in
[3] = x2
[n3
]; y2_in
[3] = y2
[n3
]; z2_in
[3] = z2
[n3
];
1168 if ( (n_out
= clip_2dx2d_great_circle( x1_in
, y1_in
, z1_in
, n1_in
, x2_in
, y2_in
, z2_in
, n2_in
,
1169 x_out
, y_out
, z_out
)) > 0) {
1170 xarea
= great_circle_area ( n_out
, x_out
, y_out
, z_out
) * mask_in
[j1
*nx1
+i1
];
1171 min_area
= min(area1
[j1
*nx1
+i1
], area2
[j2
*nx2
+i2
]);
1172 if( xarea
/min_area
> AREA_RATIO_THRESH
) {
1173 xgrid_area
[nxgrid
] = xarea
;
1174 xgrid_clon
[nxgrid
] = 0; /*z1l: will be developed very soon */
1175 xgrid_clat
[nxgrid
] = 0;
1181 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
1200 }/* create_xgrid_great_circle */
1202 int create_xgrid_great_circle_ug_(const int *nlon_in
, const int *nlat_in
, const int *npts_out
,
1203 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
1204 const double *mask_in
, int *i_in
, int *j_in
, int *l_out
,
1205 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
1208 nxgrid
= create_xgrid_great_circle_ug(nlon_in
, nlat_in
, npts_out
, lon_in
, lat_in
, lon_out
, lat_out
,
1209 mask_in
, i_in
, j_in
, l_out
, xgrid_area
, xgrid_clon
, xgrid_clat
);
1214 int create_xgrid_great_circle_ug(const int *nlon_in
, const int *nlat_in
, const int *npts_out
,
1215 const double *lon_in
, const double *lat_in
, const double *lon_out
, const double *lat_out
,
1216 const double *mask_in
, int *i_in
, int *j_in
, int *l_out
,
1217 double *xgrid_area
, double *xgrid_clon
, double *xgrid_clat
)
1220 int nx1
, ny1
, npts2
, nx1p
, ny1p
, nxgrid
, n1_in
, n2_in
, nv
;
1221 int n0
, n1
, n2
, n3
, i1
, j1
, l2
;
1222 double x1_in
[MV
], y1_in
[MV
], z1_in
[MV
];
1223 double x2_in
[MV
], y2_in
[MV
], z2_in
[MV
];
1224 double x_out
[MV
], y_out
[MV
], z_out
[MV
];
1225 double *x1
=NULL
, *y1
=NULL
, *z1
=NULL
;
1226 double *x2
=NULL
, *y2
=NULL
, *z2
=NULL
;
1228 double *area1
, *area2
, min_area
;
1238 /* first convert lon-lat to cartesian coordinates */
1239 x1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1240 y1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1241 z1
= (double *)malloc(nx1p
*ny1p
*sizeof(double));
1242 x2
= (double *)malloc(npts2
*nv
*sizeof(double));
1243 y2
= (double *)malloc(npts2
*nv
*sizeof(double));
1244 z2
= (double *)malloc(npts2
*nv
*sizeof(double));
1246 latlon2xyz(nx1p
*ny1p
, lon_in
, lat_in
, x1
, y1
, z1
);
1247 latlon2xyz(npts2
*nv
, lon_out
, lat_out
, x2
, y2
, z2
);
1249 area1
= (double *)malloc(nx1
*ny1
*sizeof(double));
1250 area2
= (double *)malloc(npts2
*sizeof(double));
1251 get_grid_great_circle_area(nlon_in
, nlat_in
, lon_in
, lat_in
, area1
);
1252 get_grid_great_circle_area_ug(npts_out
, lon_out
, lat_out
, area2
);
1256 for(j1
=0; j1
<ny1
; j1
++) for(i1
=0; i1
<nx1
; i1
++) if( mask_in
[j1
*nx1
+i1
] > MASK_THRESH
) {
1258 n0
= j1
*nx1p
+i1
; n1
= (j1
+1)*nx1p
+i1
;
1259 n2
= (j1
+1)*nx1p
+i1
+1; n3
= j1
*nx1p
+i1
+1;
1260 x1_in
[0] = x1
[n0
]; y1_in
[0] = y1
[n0
]; z1_in
[0] = z1
[n0
];
1261 x1_in
[1] = x1
[n1
]; y1_in
[1] = y1
[n1
]; z1_in
[1] = z1
[n1
];
1262 x1_in
[2] = x1
[n2
]; y1_in
[2] = y1
[n2
]; z1_in
[2] = z1
[n2
];
1263 x1_in
[3] = x1
[n3
]; y1_in
[3] = y1
[n3
]; z1_in
[3] = z1
[n3
];
1265 for(l2
=0; l2
<npts2
; l2
++) {
1269 n0
= l2
*nv
; n1
= l2
*nv
+1;
1270 n2
= l2
*nv
+2; n3
= l2
*nv
+3;
1271 x2_in
[0] = x2
[n0
]; y2_in
[0] = y2
[n0
]; z2_in
[0] = z2
[n0
];
1272 x2_in
[1] = x2
[n1
]; y2_in
[1] = y2
[n1
]; z2_in
[1] = z2
[n1
];
1273 x2_in
[2] = x2
[n2
]; y2_in
[2] = y2
[n2
]; z2_in
[2] = z2
[n2
];
1274 x2_in
[3] = x2
[n3
]; y2_in
[3] = y2
[n3
]; z2_in
[3] = z2
[n3
];
1276 if ( (n_out
= clip_2dx2d_great_circle( x1_in
, y1_in
, z1_in
, n1_in
, x2_in
, y2_in
, z2_in
, n2_in
,
1277 x_out
, y_out
, z_out
)) > 0) {
1278 xarea
= great_circle_area ( n_out
, x_out
, y_out
, z_out
) * mask_in
[j1
*nx1
+i1
];
1279 min_area
= min(area1
[j1
*nx1
+i1
], area2
[l2
]);
1280 if( xarea
/min_area
> AREA_RATIO_THRESH
) {
1281 xgrid_area
[nxgrid
] = xarea
;
1282 xgrid_clon
[nxgrid
] = 0; /*z1l: will be developed very soon */
1283 xgrid_clat
[nxgrid
] = 0;
1288 if(nxgrid
> MAXXGRID
) error_handler("nxgrid is greater than MAXXGRID, increase MAXXGRID");
1307 }/* create_xgrid_great_circle_ug */
1309 /*******************************************************************************
1311 return constants MAXXGRID.
1312 *******************************************************************************/
1313 int get_maxxgrid(void)
1318 int get_maxxgrid_(void)
1320 return get_maxxgrid();