21static char const *
cmd;
22#define DEFAULT_INTERP_STACK \
24 " {\"conservative\":\n" \
26 " \"enforced_conservation\": false,\n" \
27 " \"partial_coverage\": false,\n" \
28 " \"normalisation\": \"fracarea\"}\n" \
31 " {\"user_value\": -1}\n" \
35 "YAC weight file generation tool\n" \
36 " Reads in or generates a source and target grid file, computes\n" \
37 " interpolation weights, and writes them to file.\n" \
38 " Program is parallelised using MPI and can be run with an arbitrary number\n" \
43 " mpirun -n $N %s [OPTION]\n" \
45 " Mandatory arguments:\n" \
46 " -s/-t GRID_TYPE,{CONFIG}\n" \
47 " type and configuraion of source/target grid\n" \
49 " \"icon\": ICON-formated NetCDF grid file\n" \
50 " CONFIG: {FILE,NAME}\n" \
51 " FILE: grid file name\n" \
52 " NAME: grid name\n" \
53 " \"scrip\": OASIS-SCRIP-formated NetCDF grid file \n" \
54 " CONFIG: {FILE,NAME,EDGE_TYPE,MASK_FILE}\n" \
55 " FILE: grid file name\n" \
56 " NAME: grid name\n" \
57 " EDGE_TYPE: grid edge type\n" \
58 " \"gc\": great circles edge\n" \
59 " \"ll\": lon/lat circles edge\n" \
60 " MASK_FILE: mask file name\n" \
61 " \"exodus\": EXODUS-formated NetCDF grid file\n" \
62 " CONFIG: {FILE,NAME,EDGE_TYPE}\n" \
63 " FILE: grid file name\n" \
64 " NAME: grid name\n" \
65 " EDGE_TYPE: grid edge type\n" \
66 " \"gc\": great circles edge\n" \
67 " \"ll\": lon/lat circles edge\n" \
68 " \"reg2d\": Regular lon/lat grid\n" \
69 " (edges follow either circles of constant longitude or\n" \
71 " CONFIG: {NAME,NLON,NLAT,MIN_LON,MAX_LON,MIN_LAT,MAX_LAT}\n" \
72 " NAME: grid name\n" \
73 " NLON: number of grid vertices in longitude direction\n" \
74 " NLAT: number of grid vertices in latitude direction\n" \
75 " MIN_LON: minimum longitude in degree\n" \
76 " MAX_LON: maximum longitude in degree\n" \
77 " MIN_LAT: minimum latitude in degree\n" \
78 " MAX_LAT: maximum latitude in degree\n" \
79 " \"reg2drot\": Regular lon/lat grid with rotated north pole\n" \
80 " (all edges follow great circles)\n" \
81 " CONFIG: {NAME,NLON,NLAT,MIN_LON,MAX_LON,MIN_LAT,MAX_LAT," \
82 "POL_LON,POL_LAT}\n" \
83 " NAME: grid name\n" \
84 " NLON: number of grid vertices in longitude direction\n" \
85 " NLAT: number of grid vertices in latitude direction\n" \
86 " MIN_LON: minimum longitude in degree\n" \
87 " MAX_LON: maximum longitude in degree\n" \
88 " MIN_LAT: minimum latitude in degree\n" \
89 " MAX_LAT: maximum latitude in degree\n" \
90 " POL_LON: longitude of north in degree\n" \
91 " POL_LAT: latitude of north in in degree\n" \
93 " weight file name\n" \
95 " Optional arguments:\n" \
96 " -i {INTERP_STACK}\n" \
97 " JSON-formated interpolation stack configuration " \
98 "(see YAC documentation)\n" \
100 DEFAULT_INTERP_STACK \
102 " enables writing of run-time performance measurments to stdout\n" \
106 " mpirun -n $N %s -s exodus,CSMesh129.nc,CSMesh129,gc\\\n" \
107 " -t exodus,ICOMesh100.nc,ICOMesh100,gc\\\n" \
108 " -o CSMesh129_to_ICOMesh100.nc\n"\
110 " mpirun -n $N %s -s scrip,grids.nc,torc,gc,masks.nc\\\n" \
111 " -t icon,icon_grid_R02B05.nc,icon_R02B05\\\n" \
112 " -o torc_to_iconR02B05.nc -T -i \"[\\\"nnn\\\"]\"\n"
114#define YAC_ASSERT(exp, msg) \
117 fprintf(stderr, "ERROR: %s\n" STR_USAGE, msg, cmd, cmd, cmd); \
118 exit(EXIT_FAILURE); \
122#define YAC_ASSERT_F(exp, format, ...) \
126 stderr, "ERROR: " format "\n\n" STR_USAGE, \
127 __VA_ARGS__, cmd, cmd, cmd); \
128 exit(EXIT_FAILURE); \
179 char const ** weight_filename,
180 char const ** interp_stack_string,
182 char const ** debug_grid_file);
187 char const * interp_stack_config,
int parse_flags);
200static void timer_stop(
int print_timer,
char const * timer_name);
202int main (
int argc,
char *argv[]) {
204 MPI_Init(&argc, &argv);
205 xt_initialize(MPI_COMM_WORLD);
213 char const * weight_filename;
214 char const * interp_stack_string;
218 char const * debug_grid_file;
220 argc, argv, &src_grid_config, &tgt_grid_config, &weight_filename,
221 &interp_stack_string, &print_timer, &debug_grid_file);
237 timer_stop(print_timer,
"dist_grid_pair generation");
242 .coordinates_idx = src_grid_config.cell_coordinate_idx,
243 .masks_idx = SIZE_MAX}};
244 size_t num_src_fields =
sizeof(src_fields) /
sizeof(src_fields[0]);
247 .coordinates_idx = src_grid_config.cell_coordinate_idx,
248 .masks_idx = SIZE_MAX};
270 timer_stop(print_timer,
"weight computation");
274 if (tgt_grid_config.type ==
SCRIP) {
276 weights, tgt_grid, tgt_grid_config.data.scrip.orig_cell_global_ids,
277 tgt_grid_config.data.scrip.duplicated_cell_idx,
278 tgt_grid_config.data.scrip.nbr_duplicated_cells,
YAC_LOC_CELL);
287 tgt_grid_config.global_num_cells, on_existing);
288 timer_stop(print_timer,
"writing weight file");
310 int is_gc = !strcmp(edge_type_string,
"gc") ||
311 !strcmp(edge_type_string,
"GC");
312 int is_ll = !strcmp(edge_type_string,
"ll") ||
313 !strcmp(edge_type_string,
"LL");
315 is_gc || is_ll,
"invalid grid edge type (\"%s\")", edge_type_string);
316 free((
void*)edge_type_string);
324 long int long_value = strtol(size_t_string, &endptr, 10);
327 (endptr != size_t_string) && (*endptr ==
'\0') && (long_value >= 0),
328 "\"%s\" is not a valid size_t value", size_t_string);
329 free((
void*)size_t_string);
331 return (
size_t)long_value;
337 double dble_value = strtod(double_string, &endptr);
340 (endptr != double_string) && (*endptr ==
'\0'),
341 "\"%s\" is not a valid double value", double_string);
342 free((
void*)double_string);
348 char const * token = strtok(NULL,
",");
350 return strdup(token);
356 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
368 MPI_Bcast(&dimlen, 1,
YAC_MPI_SIZE_T, 0, MPI_COMM_WORLD), MPI_COMM_WORLD);
411 char * x_dim_name = malloc(strlen(
grid_name) + 3);
412 char * y_dim_name = malloc(strlen(
grid_name) + 3);
413 strcpy(x_dim_name,
"x_"), strcat(x_dim_name,
grid_name);
414 strcpy(y_dim_name,
"y_"), strcat(y_dim_name,
grid_name);
444 .global_num_cells = (
nlon - 1) * (
nlat - 1),
445 .data.reg2d.nlon =
nlon,
446 .data.reg2d.nlat =
nlat,
469 .global_num_cells = (
nlon - 1) * (
nlat - 1),
470 .data.reg2drot.nlon =
nlon,
471 .data.reg2drot.nlat =
nlat,
472 .data.reg2drot.min_lon =
min_lon,
473 .data.reg2drot.max_lon =
max_lon,
474 .data.reg2drot.min_lat =
min_lat,
475 .data.reg2drot.max_lat =
max_lat,
482 char const * grid_config_string_,
char const * src_tgt) {
486 char * grid_config_string = strdup(grid_config_string_);
487 char const * grid_type_string = strtok(grid_config_string,
",");
488 if (!strcmp(
"exodus", grid_type_string))
490 if (!strcmp(
"icon", grid_type_string))
492 if (!strcmp(
"scrip", grid_type_string))
494 if (!strcmp(
"reg2d", grid_type_string))
496 if (!strcmp(
"reg2drot", grid_type_string))
499 free(grid_config_string);
503 "invalid %s grid type (\"%s\")", src_tgt, grid_type_string);
511 char const ** weight_filename,
512 char const ** interp_stack_string,
514 char const ** debug_grid_file) {
518 *weight_filename = NULL;
521 *debug_grid_file = NULL;
524 while ((opt = getopt(argc, argv,
"s:t:o:i:d:T")) != -1) {
531 (opt ==
'T'),
"invalid command argument")
537 "multiple source grid arguments")
543 "multiple target grid arguments")
547 *weight_filename = optarg;
550 *interp_stack_string = optarg;
553 *debug_grid_file = optarg;
561 optind >= argc,
"non-option ARGV-element: \"%s\"", argv[optind])
567 YAC_ASSERT(*weight_filename != NULL,
"weight_filename argument is missing")
572 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
585 size_t coordinates_idx;
589 coordinates_idx = SIZE_MAX;
594 malloc(basic_grid_data->
num_cells *
sizeof(*cell_center_coords));
596 for (
size_t i = 0; i < basic_grid_data->
num_cells; ++i) {
598 double cell_center_coord[3] = {0.0, 0.0, 0.0};
599 size_t * curr_cell_to_vertex =
605 double * curr_vertex =
607 cell_center_coord[0] += curr_vertex[0];
608 cell_center_coord[1] += curr_vertex[1];
609 cell_center_coord[2] += curr_vertex[2];
612 memcpy(cell_center_coords[i], cell_center_coord, 3 *
sizeof(
double));
621 MPI_IN_PLACE, &coordinates_idx, 1,
624 return coordinates_idx;
628 size_t * nbr_vertices,
double min_lon,
double max_lon,
629 double min_lat,
double max_lat,
630 double ** lon_vertices,
double ** lat_vertices) {
632 *lon_vertices = malloc(nbr_vertices[0] *
sizeof(**lon_vertices));
633 *lat_vertices = malloc(nbr_vertices[1] *
sizeof(**lat_vertices));
635 double lon_diff = max_lon - min_lon;
636 double lat_diff = max_lat - min_lat;
638 for (
size_t i = 0; i < nbr_vertices[0]; ++i)
640 min_lon + (lon_diff * (double)i) / (double)(nbr_vertices[0] - 1);
641 (*lon_vertices)[nbr_vertices[0]-1] = max_lon;
643 for (
size_t i = 0; i < nbr_vertices[1]; ++i)
645 min_lat + (lat_diff * (double)i) / (double)(nbr_vertices[1] - 1);
646 (*lat_vertices)[nbr_vertices[1]-1] = max_lat;
653 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
659 size_t nbr_vertices[2] =
661 double * lon_vertices, * lat_vertices;
666 &lon_vertices, &lat_vertices);
673 lon_vertices, lat_vertices);
691 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
697 size_t nbr_vertices[2] =
699 double * lon_vertices, * lat_vertices;
704 &lon_vertices, &lat_vertices);
744 use_ll_edges, MPI_COMM_WORLD);
756 int valid_mask_value = 0;
784 if (debug_grid_file != NULL)
786 basic_grid, debug_grid_file, MPI_COMM_WORLD);
830 if (!print_timer)
return;
832 yac_mpi_call(MPI_Barrier(MPI_COMM_WORLD), MPI_COMM_WORLD);
836static void timer_stop(
int print_timer,
char const * timer_name) {
838 if (!print_timer)
return;
841 struct time_rank time_rank_min, time_rank_max;
846 MPI_COMM_WORLD), MPI_COMM_WORLD);
850 MPI_COMM_WORLD), MPI_COMM_WORLD);
854 MPI_COMM_WORLD), MPI_COMM_WORLD);
857 yac_mpi_call(MPI_Comm_size(MPI_COMM_WORLD, &comm_size), MPI_COMM_WORLD);
859 fprintf(stdout,
"%s: min %.3lfs (%d) avg %.3lfs max %.3lfs (%d)\n",
860 timer_name, time_rank_min.
time, time_rank_min.
rank,
861 time_sum / (
double)comm_size,
862 time_rank_max.
time, time_rank_max.
rank);
struct yac_basic_grid * yac_basic_grid_reg_2d_deg_new(char const *name, size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
void yac_basic_grid_to_file_parallel(struct yac_basic_grid *grid, char const *filename, MPI_Comm comm)
struct yac_basic_grid * yac_basic_grid_reg_2d_rot_deg_new(char const *name, size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices, double north_pole_lon, double north_pole_lat)
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
size_t yac_basic_grid_add_coordinates_nocpy(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates)
char const * yac_basic_grid_get_name(struct yac_basic_grid *grid)
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
void yac_basic_grid_delete(struct yac_basic_grid *grid)
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
struct yac_dist_grid_pair * yac_dist_grid_pair_new(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
void yac_duplicate_stencils(struct yac_interp_weights *weights, struct yac_basic_grid *tgt_grid, yac_int *tgt_orig_global_id, size_t *tgt_duplicated_idx, size_t nbr_duplicated, enum yac_location location)
void yac_interp_grid_delete(struct yac_interp_grid *interp_grid)
struct yac_interp_grid * yac_interp_grid_new(struct yac_dist_grid_pair *grid_pair, char const *src_grid_name, char const *tgt_grid_name, size_t num_src_fields, struct yac_interp_field const *src_fields, struct yac_interp_field const tgt_field)
void yac_interp_method_delete(struct interp_method **method)
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
void yac_interp_stack_config_delete(struct yac_interp_stack_config *interp_stack_config)
struct interp_method ** yac_interp_stack_config_generate(struct yac_interp_stack_config *interp_stack)
void yac_interp_weights_delete(struct yac_interp_weights *weights)
void yac_interp_weights_write_to_file(struct yac_interp_weights *weights, char const *filename, char const *src_grid_name, char const *tgt_grid_name, size_t src_grid_size, size_t tgt_grid_size, enum yac_weight_file_on_existing on_existing)
yac_weight_file_on_existing
@ YAC_WEIGHT_FILE_OVERWRITE
overwrite existing weight file
void yac_nc_open(const char *path, int omode, int *ncidp)
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
struct yac_basic_grid * yac_read_exodus_basic_grid_parallel(char const *filename, char const *gridname, int use_ll_edges, MPI_Comm comm)
void yac_read_icon_basic_grid_parallel_2(char const *filename, char const *gridname, MPI_Comm comm, struct yac_basic_grid **basic_grid, size_t *cell_coordinate_idx, int **cell_mask)
struct yac_basic_grid * yac_read_scrip_basic_grid_parallel(char const *grid_filename, char const *mask_filename, MPI_Comm comm, char const *grid_name, int valid_mask_value, char const *name, int use_ll_edges, size_t *cell_coord_idx, size_t **duplicated_cell_idx, yac_int **orig_cell_global_ids, size_t *nbr_duplicated_cells)
struct grid_config::@112::@113 exodus
struct grid_config::@107::@111 scrip
struct grid_config::@112::@116 reg2d
size_t * duplicated_cell_idx
struct grid_config::@112::@117 reg2drot
union grid_config::@112 data
enum grid_edge_type edge_type
char const * mask_filename
yac_int * orig_cell_global_ids
size_t cell_coordinate_idx
char const * grid_filename
size_t nbr_duplicated_cells
struct grid_config::@112::@114 icon
yac_coordinate_pointer vertex_coordinates
size_t * cell_to_vertex_offsets
int * num_vertices_per_cell
enum yac_location location
struct yac_interp_field tgt_field
struct yac_dist_grid_pair * grid_pair
struct yac_interp_field src_fields[]
#define YAC_HANDLE_ERROR(exp)
static void grid_config_delete(struct grid_config grid_config)
static struct grid_config parse_grid_config(char const *grid_config_string_, char const *src_tgt)
static void timer_stop(int print_timer, char const *timer_name)
static char const * get_next_token(char const *token_name)
struct grid_config parse_grid_config_scrip()
#define DEFAULT_INTERP_STACK
static void timer_start(int print_timer)
struct grid_config parse_grid_config_reg2d()
static struct yac_basic_grid * get_basic_grid_from_config(struct grid_config *grid_config, char const *debug_grid_file)
#define YAC_ASSERT_F(exp, format,...)
struct grid_config parse_grid_config_reg2drot()
static void generate_reg2d_vertices(size_t *nbr_vertices, double min_lon, double max_lon, double min_lat, double max_lat, double **lon_vertices, double **lat_vertices)
struct grid_config parse_grid_config_exodus()
static void parse_arguments(int argc, char **argv, struct grid_config *src_grid_config, struct grid_config *tgt_grid_config, char const **weight_filename, char const **interp_stack_string, int *print_timer, char const **debug_grid_file)
struct grid_config parse_grid_config_icon()
static size_t generate_cell_center_coordinates(struct yac_basic_grid *basic_grid)
static double parse_double(char const *double_string)
int const YAC_YAML_PARSER_JSON_FORCE
assume JSON format
static enum grid_edge_type parse_edge_type(char const *edge_type_string)
static void normalise_vector(double v[])
static struct yac_basic_grid * generate_reg2drot_grid(struct grid_config grid_config)
size_t read_netcdf_dimension(char const *filename, char const *dim_name)
static struct yac_basic_grid * generate_reg2d_grid(struct grid_config grid_config)
static struct time_rank local_time_rank
struct yac_interp_stack_config * yac_yaml_parse_interp_stack_config_string(char const *interp_stack_config, int parse_flags)
static size_t parse_size_t(char const *size_t_string)
#define YAC_ASSERT(exp, msg)
#define yac_mpi_call(call, comm)
double(* yac_coordinate_pointer)[3]