FV3 Bundle
read_mosaic.c
Go to the documentation of this file.
1 /***********************************************************************
2  * GNU Lesser General Public License
3  *
4  * This file is part of the GFDL Flexible Modeling System (FMS).
5  *
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.
10  *
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
14  * for more details.
15  *
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  **********************************************************************/
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <string.h>
23 #include "read_mosaic.h"
24 #include "constant.h"
25 #include "mosaic_util.h"
26 #ifdef use_netCDF
27 #include <netcdf.h>
28 #endif
29 /*********************************************************************
30  void netcdf_error( int status )
31  status is the returning value of netcdf call. this routine will
32  handle the error when status is not NC_NOERR.
33 ********************************************************************/
34 void handle_netcdf_error(const char *msg, int status )
35 {
36  char errmsg[512];
37 
38  sprintf( errmsg, "%s: %s", msg, (char *)nc_strerror(status) );
39  error_handler(errmsg);
40 
41 } /* handle_netcdf_error */
42 
43 /***************************************************************************
44  void get_file_dir(const char *file, char *dir)
45  get the directory where file is located. The dir will be the complate path
46  before the last "/". If no "/" exist in file, the path will be current ".".
47 ***************************************************************************/
48 void get_file_dir(const char *file, char *dir)
49 {
50  int len;
51  char *strptr = NULL;
52 
53  /* get the diretory */
54 
55  strptr = strrchr(file, '/');
56  if(strptr) {
57  len = strptr - file;
58  strncpy(dir, file, len);
59  }
60  else {
61  len = 1;
62  strcpy(dir, ".");
63  }
64  dir[len] = 0;
65 
66 } /* get_file_dir */
67 
68 
69 int field_exist(const char* file, const char *name)
70 {
71  int ncid, varid, status;
72  char msg[512];
73  int existed=0;
74 
75 #ifdef use_netCDF
76 
77  status = nc_open(file, NC_NOWRITE, &ncid);
78  if(status != NC_NOERR) {
79  sprintf(msg, "field_exist: in opening file %s", file);
81  }
82 
83  status = nc_inq_varid(ncid, name, &varid);
84  if(status == NC_NOERR){
85  existed = 1;
86  }
87 
88  status = nc_close(ncid);
89  if(status != NC_NOERR) {
90  sprintf(msg, "field_exist: in closing file %s.", file);
92  }
93 
94 #else /* ndef use_netCDF */
95  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
96 #endif /* use_netcdf */
97 
98  return existed;
99 
100 } /* field_exist */
101 
102 int get_dimlen(const char* file, const char *name)
103 {
104  int ncid, dimid, status, len;
105  size_t size;
106  char msg[512];
107 
108  len = 0;
109 #ifdef use_netCDF
110  status = nc_open(file, NC_NOWRITE, &ncid);
111  if(status != NC_NOERR) {
112  sprintf(msg, "in opening file %s", file);
114  }
115 
116  status = nc_inq_dimid(ncid, name, &dimid);
117  if(status != NC_NOERR) {
118  sprintf(msg, "in getting dimid of %s from file %s.", name, file);
120  }
121 
122  status = nc_inq_dimlen(ncid, dimid, &size);
123  if(status != NC_NOERR) {
124  sprintf(msg, "in getting dimension size of %s from file %s.", name, file);
126  }
127  status = nc_close(ncid);
128  if(status != NC_NOERR) {
129  sprintf(msg, "in closing file %s.", file);
131  }
132 
133  len = size;
134  if(status != NC_NOERR) {
135  sprintf(msg, "in closing file %s", file);
137  }
138 #else
139  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
140 #endif
141 
142  return len;
143 
144 } /* get_dimlen */
145 
146 /*******************************************************************************
147  void get_string_data(const char *file, const char *name, char *data)
148  get string data of field with "name" from "file".
149 ******************************************************************************/
150 void get_string_data(const char *file, const char *name, char *data)
151 {
152  int ncid, varid, status;
153  char msg[512];
154 
155 #ifdef use_netCDF
156  status = nc_open(file, NC_NOWRITE, &ncid);
157  if(status != NC_NOERR) {
158  sprintf(msg, "in opening file %s", file);
160  }
161  status = nc_inq_varid(ncid, name, &varid);
162  if(status != NC_NOERR) {
163  sprintf(msg, "in getting varid of %s from file %s.", name, file);
165  }
166  status = nc_get_var_text(ncid, varid, data);
167  if(status != NC_NOERR) {
168  sprintf(msg, "in getting data of %s from file %s.", name, file);
170  }
171  status = nc_close(ncid);
172  if(status != NC_NOERR) {
173  sprintf(msg, "in closing file %s.", file);
175  }
176 #else
177  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
178 #endif
179 
180 } /* get_string_data */
181 
182 /*******************************************************************************
183  void get_string_data_level(const char *file, const char *name, const size_t *start, const size_t *nread, char *data)
184  get string data of field with "name" from "file".
185 ******************************************************************************/
186 void get_string_data_level(const char *file, const char *name, char *data, const unsigned int *level)
187 {
188  int ncid, varid, status, i;
189  size_t start[4], nread[4];
190  char msg[512];
191 
192 #ifdef use_netCDF
193  status = nc_open(file, NC_NOWRITE, &ncid);
194  if(status != NC_NOERR) {
195  sprintf(msg, "in opening file %s", file);
197  }
198  status = nc_inq_varid(ncid, name, &varid);
199  if(status != NC_NOERR) {
200  sprintf(msg, "in getting varid of %s from file %s.", name, file);
202  }
203  for(i=0; i<4; i++) {
204  start[i] = 0; nread[i] = 1;
205  }
206  start[0] = *level; nread[1] = STRING;
207  status = nc_get_vara_text(ncid, varid, start, nread, data);
208  if(status != NC_NOERR) {
209  sprintf(msg, "in getting data of %s from file %s.", name, file);
211  }
212  status = nc_close(ncid);
213  if(status != NC_NOERR) {
214  sprintf(msg, "in closing file %s.", file);
216  }
217 #else
218  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
219 #endif
220 
221 } /* get_string_data_level */
222 
223 
224 /*******************************************************************************
225  void get_var_data(const char *file, const char *name, double *data)
226  get var data of field with "name" from "file".
227 ******************************************************************************/
228 void get_var_data(const char *file, const char *name, void *data)
229 {
230 
231  int ncid, varid, status;
232  nc_type vartype;
233  char msg[512];
234 
235 #ifdef use_netCDF
236  status = nc_open(file, NC_NOWRITE, &ncid);
237  if(status != NC_NOERR) {
238  sprintf(msg, "in opening file %s", file);
240  }
241  status = nc_inq_varid(ncid, name, &varid);
242  if(status != NC_NOERR) {
243  sprintf(msg, "in getting varid of %s from file %s.", name, file);
245  }
246 
247  status = nc_inq_vartype(ncid, varid, &vartype);
248  if(status != NC_NOERR) {
249  sprintf(msg, "get_var_data: in getting vartype of of %s in file %s ", name, file);
251  }
252 
253  switch (vartype) {
254  case NC_DOUBLE:case NC_FLOAT:
255 #ifdef OVERLOAD_R4
256  status = nc_get_var_float(ncid, varid, data);
257 #else
258  status = nc_get_var_double(ncid, varid, data);
259 #endif
260  break;
261  case NC_INT:
262  status = nc_get_var_int(ncid, varid, data);
263  break;
264  default:
265  sprintf(msg, "get_var_data: field %s in file %s has an invalid type, "
266  "the type should be NC_DOUBLE, NC_FLOAT or NC_INT", name, file);
267  error_handler(msg);
268  }
269  if(status != NC_NOERR) {
270  sprintf(msg, "in getting data of %s from file %s.", name, file);
272  }
273  status = nc_close(ncid);
274  if(status != NC_NOERR) {
275  sprintf(msg, "in closing file %s.", file);
277  }
278 #else
279  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
280 #endif
281 
282 } /* get_var_data */
283 
284 /*******************************************************************************
285  void get_var_data(const char *file, const char *name, double *data)
286  get var data of field with "name" from "file".
287 ******************************************************************************/
288 void get_var_data_region(const char *file, const char *name, const size_t *start, const size_t *nread, void *data)
289 {
290 
291  int ncid, varid, status;
292  nc_type vartype;
293  char msg[512];
294 
295 #ifdef use_netCDF
296  status = nc_open(file, NC_NOWRITE, &ncid);
297  if(status != NC_NOERR) {
298  sprintf(msg, "get_var_data_region: in opening file %s", file);
300  }
301  status = nc_inq_varid(ncid, name, &varid);
302  if(status != NC_NOERR) {
303  sprintf(msg, "in getting varid of %s from file %s.", name, file);
305  }
306 
307  status = nc_inq_vartype(ncid, varid, &vartype);
308  if(status != NC_NOERR) {
309  sprintf(msg, "get_var_data_region: in getting vartype of of %s in file %s ", name, file);
311  }
312 
313  switch (vartype) {
314  case NC_DOUBLE:case NC_FLOAT:
315 #ifdef OVERLOAD_R4
316  status = nc_get_vara_float(ncid, varid, start, nread, data);
317 #else
318  status = nc_get_vara_double(ncid, varid, start, nread, data);
319 #endif
320  break;
321  case NC_INT:
322  status = nc_get_vara_int(ncid, varid, start, nread, data);
323  break;
324  default:
325  sprintf(msg, "get_var_data_region: field %s in file %s has an invalid type, "
326  "the type should be NC_DOUBLE, NC_FLOAT or NC_INT", name, file);
327  error_handler(msg);
328  }
329 
330  if(status != NC_NOERR) {
331  sprintf(msg, "get_var_data_region: in getting data of %s from file %s.", name, file);
333  }
334  status = nc_close(ncid);
335  if(status != NC_NOERR) {
336  sprintf(msg, "get_var_data_region: in closing file %s.", file);
338  }
339 #else
340  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
341 #endif
342 
343 } /* get_var_data_region */
344 
345 /******************************************************************************
346  void get_var_text_att(const char *file, const char *name, const char *attname, char *att)
347  get text attribute of field 'name' from 'file
348 ******************************************************************************/
349 void get_var_text_att(const char *file, const char *name, const char *attname, char *att)
350 {
351  int ncid, varid, status;
352  char msg[512];
353 
354 #ifdef use_netCDF
355  status = nc_open(file, NC_NOWRITE, &ncid);
356  if(status != NC_NOERR) {
357  sprintf(msg, "in opening file %s", file);
359  }
360  status = nc_inq_varid(ncid, name, &varid);
361  if(status != NC_NOERR) {
362  sprintf(msg, "in getting varid of %s from file %s.", name, file);
364  }
365  status = nc_get_att_text(ncid, varid, attname, att);
366  if(status != NC_NOERR) {
367  sprintf(msg, "in getting attribute %s of %s from file %s.", attname, name, file);
369  }
370  status = nc_close(ncid);
371  if(status != NC_NOERR) {
372  sprintf(msg, "in closing file %s.", file);
374  }
375 #else
376  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
377 #endif
378 
379 } /* get_var_text_att */
380 
381 /***********************************************************************
382  return number of overlapping cells.
383 ***********************************************************************/
384 #ifndef __AIX
385 int read_mosaic_xgrid_size_( const char *xgrid_file )
386 {
387  return read_mosaic_xgrid_size(xgrid_file);
388 }
389 #endif
390 
391 int read_mosaic_xgrid_size( const char *xgrid_file )
392 {
393  int ncells;
394 
395  ncells = get_dimlen(xgrid_file, "ncells");
396  return ncells;
397 }
398 
399 #ifdef OVERLOAD_R4
400 float get_global_area(void)
401 {
402  float garea;
403 #else
404  double get_global_area(void)
405  {
406  double garea;
407 #endif
408  garea = 4*M_PI*RADIUS*RADIUS;
409 
410  return garea;
411  }
412 
413 #ifndef __AIX
414 #ifdef OVERLOAD_R4
415  float get_global_area_(void)
416  {
417  float garea;
418 #else
419  double get_global_area_(void)
420  {
421  double garea;
422 #endif
423  garea = 4*M_PI*RADIUS*RADIUS;
424 
425  return garea;
426  }
427 #endif
428 
429 
430  /****************************************************************************/
431 #ifndef __AIX
432 #ifdef OVERLOAD_R4
433  void read_mosaic_xgrid_order1_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area )
434 #else
435  void read_mosaic_xgrid_order1_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area )
436 #endif
437  {
438  read_mosaic_xgrid_order1(xgrid_file, i1, j1, i2, j2, area);
439 
440  }
441 #endif
442 
443 #ifdef OVERLOAD_R4
444  void read_mosaic_xgrid_order1(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area )
445 #else
446  void read_mosaic_xgrid_order1(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area )
447 #endif
448  {
449  int ncells, n;
450  int *tile1_cell, *tile2_cell;
451 #ifdef OVERLOAD_R4
452  float garea;
453 #else
454  double garea;
455 #endif
456 
457  ncells = get_dimlen(xgrid_file, "ncells");
458 
459  tile1_cell = (int *)malloc(ncells*2*sizeof(int));
460  tile2_cell = (int *)malloc(ncells*2*sizeof(int));
461  get_var_data(xgrid_file, "tile1_cell", tile1_cell);
462  get_var_data(xgrid_file, "tile2_cell", tile2_cell);
463 
464  get_var_data(xgrid_file, "xgrid_area", area);
465 
466  garea = 4*M_PI*RADIUS*RADIUS;
467 
468  for(n=0; n<ncells; n++) {
469  i1[n] = tile1_cell[n*2] - 1;
470  j1[n] = tile1_cell[n*2+1] - 1;
471  i2[n] = tile2_cell[n*2] - 1;
472  j2[n] = tile2_cell[n*2+1] - 1;
473  area[n] /= garea; /* rescale the exchange grid area to unit earth area */
474  }
475 
476  free(tile1_cell);
477  free(tile2_cell);
478 
479  } /* read_mosaic_xgrid_order1 */
480 
481 
482 #ifndef __AIX
483 #ifdef OVERLOAD_R4
484  void read_mosaic_xgrid_order1_region_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area, int *isc, int *iec )
485 #else
486  void read_mosaic_xgrid_order1_region_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, int *isc, int *iec )
487 #endif
488  {
489  read_mosaic_xgrid_order1_region(xgrid_file, i1, j1, i2, j2, area, isc, iec);
490 
491  }
492 #endif
493 
494 #ifdef OVERLOAD_R4
495  void read_mosaic_xgrid_order1_region(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area, int *isc, int *iec )
496 #else
497  void read_mosaic_xgrid_order1_region(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, int *isc, int *iec )
498 #endif
499  {
500  int ncells, n, i;
501  int *tile1_cell, *tile2_cell;
502  size_t start[4], nread[4];
503 #ifdef OVERLOAD_R4
504  float garea;
505 #else
506  double garea;
507 #endif
508 
509  ncells = *iec-*isc+1;
510 
511  tile1_cell = (int *)malloc(ncells*2*sizeof(int));
512  tile2_cell = (int *)malloc(ncells*2*sizeof(int));
513  for(i=0; i<4; i++) {
514  start[i] = 0; nread[i] = 1;
515  }
516 
517  start[0] = *isc;
518  nread[0] = ncells;
519  nread[1] = 2;
520 
521  get_var_data_region(xgrid_file, "tile1_cell", start, nread, tile1_cell);
522  get_var_data_region(xgrid_file, "tile2_cell", start, nread, tile2_cell);
523 
524  nread[1] = 1;
525 
526  get_var_data_region(xgrid_file, "xgrid_area", start, nread, area);
527 
528  garea = 4*M_PI*RADIUS*RADIUS;
529 
530  for(n=0; n<ncells; n++) {
531  i1[n] = tile1_cell[n*2] - 1;
532  j1[n] = tile1_cell[n*2+1] - 1;
533  i2[n] = tile2_cell[n*2] - 1;
534  j2[n] = tile2_cell[n*2+1] - 1;
535  area[n] /= garea; /* rescale the exchange grid area to unit earth area */
536  }
537 
538  free(tile1_cell);
539  free(tile2_cell);
540 
541  } /* read_mosaic_xgrid_order1 */
542 
543  /* NOTE: di, dj is for tile1, */
544  /****************************************************************************/
545 #ifndef __AIX
546 #ifdef OVERLOAD_R4
547  void read_mosaic_xgrid_order2_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area, float *di, float *dj )
548 #else
549  void read_mosaic_xgrid_order2_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, double *di, double *dj )
550 #endif
551  {
552  read_mosaic_xgrid_order2(xgrid_file, i1, j1, i2, j2, area, di, dj);
553 
554  }
555 #endif
556 #ifdef OVERLOAD_R4
557  void read_mosaic_xgrid_order2(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, float *area, float *di, float *dj )
558 #else
559  void read_mosaic_xgrid_order2(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, double *di, double *dj )
560 #endif
561 
562  {
563  int ncells, n;
564  int *tile1_cell, *tile2_cell;
565  double *tile1_distance;
566 #ifdef OVERLOAD_R4
567  float garea;
568 #else
569  double garea;
570 #endif
571  ncells = get_dimlen(xgrid_file, "ncells");
572 
573  tile1_cell = (int *)malloc(ncells*2*sizeof(int ));
574  tile2_cell = (int *)malloc(ncells*2*sizeof(int ));
575  tile1_distance = (double *)malloc(ncells*2*sizeof(double));
576  get_var_data(xgrid_file, "tile1_cell", tile1_cell);
577  get_var_data(xgrid_file, "tile2_cell", tile2_cell);
578  get_var_data(xgrid_file, "xgrid_area", area);
579  get_var_data(xgrid_file, "tile1_distance", tile1_distance);
580 
581  garea = 4*M_PI*RADIUS*RADIUS;
582 
583  for(n=0; n<ncells; n++) {
584  i1[n] = tile1_cell[n*2] - 1;
585  j1[n] = tile1_cell[n*2+1] - 1;
586  i2[n] = tile2_cell[n*2] - 1;
587  j2[n] = tile2_cell[n*2+1] - 1;
588  di[n] = tile1_distance[n*2];
589  dj[n] = tile1_distance[n*2+1];
590  area[n] /= garea; /* rescale the exchange grid area to unit earth area */
591  }
592 
593  free(tile1_cell);
594  free(tile2_cell);
595  free(tile1_distance);
596 
597  } /* read_mosaic_xgrid_order2 */
598 
599  /******************************************************************************
600  int read_mosaic_ntiles(const char *mosaic_file)
601  return number tiles in mosaic_file
602  ******************************************************************************/
603 #ifndef __AIX
604  int read_mosaic_ntiles_(const char *mosaic_file)
605  {
606  return read_mosaic_ntiles(mosaic_file);
607  }
608 #endif
609  int read_mosaic_ntiles(const char *mosaic_file)
610  {
611 
612  int ntiles;
613 
614  ntiles = get_dimlen(mosaic_file, "ntiles");
615 
616  return ntiles;
617 
618  } /* read_mosaic_ntiles */
619 
620  /******************************************************************************
621  int read_mosaic_ncontacts(const char *mosaic_file)
622  return number of contacts in mosaic_file
623  ******************************************************************************/
624 #ifndef __AIX
625  int read_mosaic_ncontacts_(const char *mosaic_file)
626  {
627  return read_mosaic_ncontacts(mosaic_file);
628  }
629 #endif
630  int read_mosaic_ncontacts(const char *mosaic_file)
631  {
632 
633  int ncontacts;
634 
635  if(field_exist(mosaic_file, "contacts") )
636  ncontacts = get_dimlen(mosaic_file, "ncontact");
637  else
638  ncontacts = 0;
639 
640  return ncontacts;
641 
642  } /* read_mosaic_ncontacts */
643 
644 
645  /*****************************************************************************
646  void read_mosaic_grid_sizes(const char *mosaic_file, int *nx, int *ny)
647  read mosaic grid size of each tile, currently we are assuming the refinement is 2.
648  We assume the grid files are located at the same directory as mosaic_file.
649  *****************************************************************************/
650 #ifndef __AIX
651  void read_mosaic_grid_sizes_(const char *mosaic_file, int *nx, int *ny)
652  {
653  read_mosaic_grid_sizes(mosaic_file, nx, ny);
654  }
655 #endif
656  void read_mosaic_grid_sizes(const char *mosaic_file, int *nx, int *ny)
657  {
658  unsigned int ntiles, n;
659  char gridfile[STRING], tilefile[2*STRING];
660  char dir[STRING];
661  const int x_refine = 2, y_refine = 2;
662 
663  get_file_dir(mosaic_file, dir);
664  ntiles = get_dimlen(mosaic_file, "ntiles");
665  for(n = 0; n < ntiles; n++) {
666  get_string_data_level(mosaic_file, "gridfiles", gridfile, &n);
667  sprintf(tilefile, "%s/%s", dir, gridfile);
668  nx[n] = get_dimlen(tilefile, "nx");
669  ny[n] = get_dimlen(tilefile, "ny");
670  if(nx[n]%x_refine != 0) error_handler("Error from read_mosaic_grid_sizes: nx is not divided by x_refine");
671  if(ny[n]%y_refine != 0) error_handler("Error from read_mosaic_grid_sizes: ny is not divided by y_refine");
672  nx[n] /= x_refine;
673  ny[n] /= y_refine;
674  }
675 
676  } /* read_mosaic_grid_sizes */
677 
678 
679  /******************************************************************************
680  void read_mosaic_contact(const char *mosaic_file)
681  read mosaic contact information
682  ******************************************************************************/
683 #ifndef __AIX
684  void read_mosaic_contact_(const char *mosaic_file, int *tile1, int *tile2, int *istart1, int *iend1,
685  int *jstart1, int *jend1, int *istart2, int *iend2, int *jstart2, int *jend2)
686  {
687  read_mosaic_contact(mosaic_file, tile1, tile2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2);
688  }
689 #endif
690 
691  /* transfer the index from supergrid to model grid
692  return 0 if istart = iend
693  otherwise return 1.
694  */
695 
696  int transfer_to_model_index(int istart_in, int iend_in, int *istart_out, int *iend_out, int refine_ratio)
697  {
698 
699  int type;
700 
701  if( istart_in == iend_in ) {
702  type = 0;
703  istart_out[0] = (istart_in+1)/refine_ratio-1;
704  iend_out[0] = istart_out[0];
705  }
706  else {
707  type = 1;
708  if( iend_in > istart_in ) {
709  istart_out[0] = istart_in - 1;
710  iend_out[0] = iend_in - refine_ratio;
711  }
712  else {
713  istart_out[0] = istart_in - refine_ratio;
714  iend_out[0] = iend_in - 1;
715  }
716 
717  if( istart_out[0]%refine_ratio || iend_out[0]%refine_ratio)
718  error_handler("Error from read_mosaic: mismatch between refine_ratio and istart_in/iend_in");
719  istart_out[0] /= refine_ratio;
720  iend_out[0] /= refine_ratio;
721  }
722 
723  return type;
724 
725  }
726 
727 
728  void read_mosaic_contact(const char *mosaic_file, int *tile1, int *tile2, int *istart1, int *iend1,
729  int *jstart1, int *jend1, int *istart2, int *iend2, int *jstart2, int *jend2)
730  {
731  char contacts[STRING];
732  char **gridtiles;
733 #define MAXVAR 40
734  char pstring[MAXVAR][STRING];
735  unsigned int nstr, ntiles, ncontacts, n, m, l, found;
736  const int x_refine = 2, y_refine = 2;
737  int i1_type, j1_type, i2_type, j2_type;
738 
739  ntiles = get_dimlen(mosaic_file, "ntiles");
740  gridtiles = (char **)malloc(ntiles*sizeof(char *));
741  for(n=0; n<ntiles; n++) {
742  gridtiles[n] = (char *)malloc(STRING*sizeof(char));
743  get_string_data_level(mosaic_file, "gridtiles", gridtiles[n], &n);
744  }
745 
746  ncontacts = get_dimlen(mosaic_file, "ncontact");
747  for(n = 0; n < ncontacts; n++) {
748  get_string_data_level(mosaic_file, "contacts", contacts, &n);
749  /* parse the string contacts to get tile number */
750  tokenize( contacts, ":", STRING, MAXVAR, (char *)pstring, &nstr);
751  if(nstr != 4) error_handler("Error from read_mosaic: number of elements "
752  "in contact seperated by :/:: should be 4");
753  found = 0;
754  for(m=0; m<ntiles; m++) {
755  if(strcmp(gridtiles[m], pstring[1]) == 0) { /*found the tile name */
756  found = 1;
757  tile1[n] = m+1;
758  break;
759  }
760  }
761  if(!found) error_handler("error from read_mosaic: the first tile name specified "
762  "in contact is not found in tile list");
763  found = 0;
764  for(m=0; m<ntiles; m++) {
765  if(strcmp(gridtiles[m], pstring[3]) == 0) { /*found the tile name */
766  found = 1;
767  tile2[n] = m+1;
768  break;
769  }
770  }
771  if(!found) error_handler("error from read_mosaic: the second tile name specified "
772  "in contact is not found in tile list");
773  get_string_data_level(mosaic_file, "contact_index", contacts, &n);
774  /* parse the string to get contact index */
775  tokenize( contacts, ":,", STRING, MAXVAR, (char *)pstring, &nstr);
776  if(nstr != 8) error_handler("Error from read_mosaic: number of elements "
777  "in contact_index seperated by :/, should be 8");
778  /* make sure the string is only composed of numbers */
779  for(m=0; m<nstr; m++){
780  for(l=0; l<strlen(pstring[m]); l++){
781  if(pstring[m][l] > '9' || pstring[m][l] < '0' ) {
782  error_handler("Error from read_mosaic: some of the character in "
783  "contact_indices except token is not digit number");
784  }
785  }
786  }
787  istart1[n] = atoi(pstring[0]);
788  iend1[n] = atoi(pstring[1]);
789  jstart1[n] = atoi(pstring[2]);
790  jend1[n] = atoi(pstring[3]);
791  istart2[n] = atoi(pstring[4]);
792  iend2[n] = atoi(pstring[5]);
793  jstart2[n] = atoi(pstring[6]);
794  jend2[n] = atoi(pstring[7]);
795  i1_type = transfer_to_model_index(istart1[n], iend1[n], istart1+n, iend1+n, x_refine);
796  j1_type = transfer_to_model_index(jstart1[n], jend1[n], jstart1+n, jend1+n, y_refine);
797  i2_type = transfer_to_model_index(istart2[n], iend2[n], istart2+n, iend2+n, x_refine);
798  j2_type = transfer_to_model_index(jstart2[n], jend2[n], jstart2+n, jend2+n, y_refine);
799  if( i1_type == 0 && j1_type == 0 )
800  error_handler("Error from read_mosaic_contact:istart1==iend1 and jstart1==jend1");
801  if( i2_type == 0 && j2_type == 0 )
802  error_handler("Error from read_mosaic_contact:istart2==iend2 and jstart2==jend2");
803  if( i1_type + j1_type != i2_type + j2_type )
804  error_handler("Error from read_mosaic_contact: It is not a line or overlap contact");
805 
806  }
807 
808  for(m=0; m<ntiles; m++) {
809  free(gridtiles[m]);
810  }
811 
812  free(gridtiles);
813 
814 
815  } /* read_mosaic_contact */
816 
817 
818  /******************************************************************************
819  void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny,
820  double *data, int level, int ioff, int joff)
821  read mosaic grid information onto model grid. We assume the refinement is 2 right now.
822  We may remove this restriction in the future. nx and ny are model grid size. level
823  is the tile number. ioff and joff to indicate grid location. ioff =0 and joff = 0
824  for C-cell. ioff=0 and joff=1 for E-cell, ioff=1 and joff=0 for N-cell,
825  ioff=1 and joff=1 for T-cell
826  ******************************************************************************/
827  void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny,
828  double *data, unsigned int level, int ioff, int joff)
829  {
830  char tilefile[STRING], gridfile[STRING], dir[STRING];
831  double *tmp;
832  int ni, nj, nxp, nyp, i, j;
833 
834  get_file_dir(mosaic_file, dir);
835 
836  get_string_data_level(mosaic_file, "gridfiles", gridfile, &level);
837  sprintf(tilefile, "%s/%s", dir, gridfile);
838 
839  ni = get_dimlen(tilefile, "nx");
840  nj = get_dimlen(tilefile, "ny");
841 
842  if( ni != nx*2 || nj != ny*2) error_handler("supergrid size should be double of the model grid size");
843  tmp = (double *)malloc((ni+1)*(nj+1)*sizeof(double));
844  get_var_data( tilefile, name, tmp);
845  nxp = nx + 1 - ioff;
846  nyp = ny + 1 - joff;
847  for(j=0; j<nyp; j++) for(i=0; i<nxp; i++) data[j*nxp+i] = tmp[(2*j+joff)*(ni+1)+2*i+ioff];
848  free(tmp);
849 
850  } /* read_mosaic_grid_data */
l_size ! loop over number of fields ke do je do i
subroutine error_handler(routine, message)
Definition: fft.F90:1097
double get_global_area(void)
Definition: read_mosaic.c:404
int read_mosaic_ncontacts_(const char *mosaic_file)
Definition: read_mosaic.c:625
void read_mosaic_contact_(const char *mosaic_file, int *tile1, int *tile2, int *istart1, int *iend1, int *jstart1, int *jend1, int *istart2, int *iend2, int *jstart2, int *jend2)
Definition: read_mosaic.c:684
integer, parameter, public strlen
integer, save, private iec
Definition: oda_core.F90:124
int read_mosaic_ntiles_(const char *mosaic_file)
Definition: read_mosaic.c:604
int read_mosaic_xgrid_size_(const char *xgrid_file)
Definition: read_mosaic.c:385
void get_string_data(const char *file, const char *name, char *data)
Definition: read_mosaic.c:150
void read_mosaic_xgrid_order2(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, double *di, double *dj)
Definition: read_mosaic.c:559
int transfer_to_model_index(int istart_in, int iend_in, int *istart_out, int *iend_out, int refine_ratio)
Definition: read_mosaic.c:696
void get_var_data(const char *file, const char *name, void *data)
Definition: read_mosaic.c:228
void tokenize(const char *const string, const char *tokens, unsigned int varlen, unsigned int maxvar, char *pstring, unsigned int *const nstr)
Definition: mosaic_util.c:112
integer, parameter nx
int read_mosaic_ncontacts(const char *mosaic_file)
Definition: read_mosaic.c:630
void read_mosaic_grid_sizes_(const char *mosaic_file, int *nx, int *ny)
Definition: read_mosaic.c:651
void read_mosaic_xgrid_order1_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area)
Definition: read_mosaic.c:435
void get_var_text_att(const char *file, const char *name, const char *attname, char *att)
Definition: read_mosaic.c:349
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************! this routine is used to retrieve scalar boundary data for symmetric domain. subroutine MPP_GET_BOUNDARY_2D_(field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &position, complete, tile_count) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::field(:,:) MPP_TYPE_, intent(inout), optional ::ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:) integer, intent(in), optional ::flags, position, tile_count logical, intent(in), optional ::complete MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_, allocatable, dimension(:,:) ::ebuffer2D, sbuffer2D, wbuffer2D, nbuffer2D integer ::xcount, ycount integer ::ntile logical ::need_ebuffer, need_sbuffer, need_wbuffer, need_nbuffer integer(LONG_KIND), dimension(MAX_DOMAIN_FIELDS, MAX_TILES), save ::f_addrs=-9999 integer(LONG_KIND), dimension(4, MAX_DOMAIN_FIELDS, MAX_TILES), save ::b_addrs=-9999 integer, save ::bsize(4)=0, isize=0, jsize=0, ksize=0, pos, list=0, l_size=0, upflags integer ::buffer_size(4) integer ::max_ntile, tile, update_position, ishift, jshift logical ::do_update, is_complete, set_mismatch character(len=3) ::text MPP_TYPE_ ::d_type type(overlapSpec), pointer ::bound=> NULL() ntile
integer, parameter ny
void read_mosaic_xgrid_order2_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, double *di, double *dj)
Definition: read_mosaic.c:549
l_size ! loop over number of fields ke do j
character(len=32) name
int read_mosaic_xgrid_size(const char *xgrid_file)
Definition: read_mosaic.c:391
void get_var_data_region(const char *file, const char *name, const size_t *start, const size_t *nread, void *data)
Definition: read_mosaic.c:288
double get_global_area_(void)
Definition: read_mosaic.c:419
integer, parameter m
integer(i_long) ncid
Definition: ncdw_state.f90:8
void get_file_dir(const char *file, char *dir)
Definition: read_mosaic.c:48
void read_mosaic_xgrid_order1(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area)
Definition: read_mosaic.c:446
int read_mosaic_ntiles(const char *mosaic_file)
Definition: read_mosaic.c:609
type
Definition: c2f.py:15
int field_exist(const char *file, const char *name)
Definition: read_mosaic.c:69
real, dimension(:,:), allocatable area
void read_mosaic_contact(const char *mosaic_file, int *tile1, int *tile2, int *istart1, int *iend1, int *jstart1, int *jend1, int *istart2, int *iend2, int *jstart2, int *jend2)
Definition: read_mosaic.c:728
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE start
void get_string_data_level(const char *file, const char *name, char *data, const unsigned int *level)
Definition: read_mosaic.c:186
integer, parameter x_refine
Definition: mosaic.F90:50
#define RADIUS
Definition: constant.h:19
void handle_netcdf_error(const char *msg, int status)
Definition: read_mosaic.c:34
void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny, double *data, unsigned int level, int ioff, int joff)
Definition: read_mosaic.c:827
integer, save, private isc
Definition: oda_core.F90:124
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
void read_mosaic_xgrid_order1_region(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, int *isc, int *iec)
Definition: read_mosaic.c:497
void read_mosaic_xgrid_order1_region_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area, int *isc, int *iec)
Definition: read_mosaic.c:486
int get_dimlen(const char *file, const char *name)
Definition: read_mosaic.c:102
#define STRING
Definition: constant.h:20
void read_mosaic_grid_sizes(const char *mosaic_file, int *nx, int *ny)
Definition: read_mosaic.c:656
integer, pointer ntiles
integer, parameter y_refine
Definition: mosaic.F90:50
#define MAXVAR