20static char const *
cmd;
21#define DEFAULT_INTERP_STACK \
23 " {\"conservative\":\n" \
25 " \"enforced_conservation\": false,\n" \
26 " \"partial_coverage\": false,\n" \
27 " \"normalisation\": \"fracarea\"}\n" \
30 " {\"user_value\": -1}\n" \
34 "YAC weight file generation tool\n" \
35 " Reads in or generates a source and target grid file, computes\n" \
36 " interpolation weights, and writes them to file.\n" \
37 " Program is parallelised using MPI and can be run with an arbitrary number\n" \
42 " mpirun -n $N %s [OPTION]\n" \
44 " Mandatory arguments:\n" \
45 " -s/-t GRID_TYPE,{CONFIG}\n" \
46 " type and configuraion of source/target grid\n" \
48 " \"icon\": ICON-formated NetCDF grid file\n" \
49 " CONFIG: {FILE,NAME}\n" \
50 " FILE: grid file name\n" \
51 " NAME: grid name\n" \
52 " \"scrip\": OASIS-SCRIP-formated NetCDF grid file \n" \
53 " CONFIG: {FILE,NAME,EDGE_TYPE,MASK_FILE}\n" \
54 " FILE: grid file name\n" \
55 " NAME: grid name\n" \
56 " EDGE_TYPE: grid edge type\n" \
57 " \"gc\": great circles edge\n" \
58 " \"ll\": lon/lat circles edge\n" \
59 " MASK_FILE: mask file name\n" \
60 " \"exodus\": EXODUS-formated NetCDF grid file\n" \
61 " CONFIG: {FILE,NAME,EDGE_TYPE}\n" \
62 " FILE: grid file name\n" \
63 " NAME: grid name\n" \
64 " EDGE_TYPE: grid edge type\n" \
65 " \"gc\": great circles edge\n" \
66 " \"ll\": lon/lat circles edge\n" \
67 " \"reg2d\": Regular lon/lat grid\n" \
68 " (edges follow either circles of constant longitude or\n" \
70 " CONFIG: {NAME,NLON,NLAT,MIN_LON,MAX_LON,MIN_LAT,MAX_LAT}\n" \
71 " NAME: grid name\n" \
72 " NLON: number of grid vertices in longitude direction\n" \
73 " NLAT: number of grid vertices in latitude direction\n" \
74 " MIN_LON: minimum longitude in degree\n" \
75 " MAX_LON: maximum longitude in degree\n" \
76 " MIN_LAT: minimum latitude in degree\n" \
77 " MAX_LAT: maximum latitude in degree\n" \
78 " \"reg2drot\": Regular lon/lat grid with rotated north pole\n" \
79 " (all edges follow great circles)\n" \
80 " CONFIG: {NAME,NLON,NLAT,MIN_LON,MAX_LON,MIN_LAT,MAX_LAT," \
81 "POL_LON,POL_LAT}\n" \
82 " NAME: grid name\n" \
83 " NLON: number of grid vertices in longitude direction\n" \
84 " NLAT: number of grid vertices in latitude direction\n" \
85 " MIN_LON: minimum longitude in degree\n" \
86 " MAX_LON: maximum longitude in degree\n" \
87 " MIN_LAT: minimum latitude in degree\n" \
88 " MAX_LAT: maximum latitude in degree\n" \
89 " POL_LON: longitude of north in degree\n" \
90 " POL_LAT: latitude of north in in degree\n" \
92 " weight file name\n" \
94 " Optional arguments:\n" \
95 " -i {INTERP_STACK}\n" \
96 " JSON-formated interpolation stack configuration " \
97 "(see YAC documentation)\n" \
99 DEFAULT_INTERP_STACK \
101 " enables writing of run-time performance measurments to stdout\n" \
105 " mpirun -n $N %s -s exodus,CSMesh129.nc,CSMesh129,gc\\\n" \
106 " -t exodus,ICOMesh100.nc,ICOMesh100,gc\\\n" \
107 " -o CSMesh129_to_ICOMesh100.nc\n"\
109 " mpirun -n $N %s -s scrip,grids.nc,torc,gc,masks.nc\\\n" \
110 " -t icon,icon_grid_R02B05.nc,icon_R02B05\\\n" \
111 " -o torc_to_iconR02B05.nc -T -i \"[\\\"nnn\\\"]\"\n"
113#define YAC_ASSERT(exp, msg) \
116 fprintf(stderr, "ERROR: %s\n" STR_USAGE, msg, cmd, cmd, cmd); \
117 exit(EXIT_FAILURE); \
121#define YAC_ASSERT_F(exp, format, ...) \
125 stderr, "ERROR: " format "\n\n" STR_USAGE, \
126 __VA_ARGS__, cmd, cmd, cmd); \
127 exit(EXIT_FAILURE); \
178 char const ** weight_filename,
179 char const ** interp_stack_string,
181 char const ** debug_grid_file);
186 char const * interp_stack_config,
int parse_flags);
199static void timer_stop(
int print_timer,
char const * timer_name);
201int main (
int argc,
char *argv[]) {
203 MPI_Init(&argc, &argv);
204 xt_initialize(MPI_COMM_WORLD);
212 char const * weight_filename;
213 char const * interp_stack_string;
217 char const * debug_grid_file;
219 argc, argv, &src_grid_config, &tgt_grid_config, &weight_filename,
220 &interp_stack_string, &print_timer, &debug_grid_file);
236 timer_stop(print_timer,
"dist_grid_pair generation");
241 .coordinates_idx = src_grid_config.cell_coordinate_idx,
242 .masks_idx = SIZE_MAX}};
243 size_t num_src_fields =
sizeof(src_fields) /
sizeof(src_fields[0]);
246 .coordinates_idx = src_grid_config.cell_coordinate_idx,
247 .masks_idx = SIZE_MAX};
269 timer_stop(print_timer,
"weight computation");
273 if (tgt_grid_config.type ==
SCRIP) {
275 weights, tgt_grid, tgt_grid_config.data.scrip.orig_cell_global_ids,
276 tgt_grid_config.data.scrip.duplicated_cell_idx,
277 tgt_grid_config.data.scrip.nbr_duplicated_cells,
YAC_LOC_CELL);
286 tgt_grid_config.global_num_cells, on_existing);
287 timer_stop(print_timer,
"writing weight file");
309 int is_gc = !strcmp(edge_type_string,
"gc") ||
310 !strcmp(edge_type_string,
"GC");
311 int is_ll = !strcmp(edge_type_string,
"ll") ||
312 !strcmp(edge_type_string,
"LL");
314 is_gc || is_ll,
"invalid grid edge type (\"%s\")", edge_type_string);
315 free((
void*)edge_type_string);
323 long int long_value = strtol(size_t_string, &endptr, 10);
326 (endptr != size_t_string) && (*endptr ==
'\0') && (long_value >= 0),
327 "\"%s\" is not a valid size_t value", size_t_string);
328 free((
void*)size_t_string);
330 return (
size_t)long_value;
336 double dble_value = strtod(double_string, &endptr);
339 (endptr != double_string) && (*endptr ==
'\0'),
340 "\"%s\" is not a valid double value", double_string);
341 free((
void*)double_string);
347 char const * token = strtok(NULL,
",");
355 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
367 MPI_Bcast(&dimlen, 1,
YAC_MPI_SIZE_T, 0, MPI_COMM_WORLD), MPI_COMM_WORLD);
410 char * x_dim_name = malloc(strlen(
grid_name) + 3);
411 char * y_dim_name = malloc(strlen(
grid_name) + 3);
412 strcpy(x_dim_name,
"x_"), strcat(x_dim_name,
grid_name);
413 strcpy(y_dim_name,
"y_"), strcat(y_dim_name,
grid_name);
443 .global_num_cells = (
nlon - 1) * (
nlat - 1),
444 .data.reg2d.nlon =
nlon,
445 .data.reg2d.nlat =
nlat,
468 .global_num_cells = (
nlon - 1) * (
nlat - 1),
469 .data.reg2drot.nlon =
nlon,
470 .data.reg2drot.nlat =
nlat,
471 .data.reg2drot.min_lon =
min_lon,
472 .data.reg2drot.max_lon =
max_lon,
473 .data.reg2drot.min_lat =
min_lat,
474 .data.reg2drot.max_lat =
max_lat,
481 char const * grid_config_string_,
char const * src_tgt) {
485 char * grid_config_string =
xstrdup(grid_config_string_);
486 char const * grid_type_string = strtok(grid_config_string,
",");
487 if (!strcmp(
"exodus", grid_type_string))
489 if (!strcmp(
"icon", grid_type_string))
491 if (!strcmp(
"scrip", grid_type_string))
493 if (!strcmp(
"reg2d", grid_type_string))
495 if (!strcmp(
"reg2drot", grid_type_string))
498 free(grid_config_string);
502 "invalid %s grid type (\"%s\")", src_tgt, grid_type_string);
510 char const ** weight_filename,
511 char const ** interp_stack_string,
513 char const ** debug_grid_file) {
517 *weight_filename = NULL;
520 *debug_grid_file = NULL;
523 while ((opt = getopt(argc, argv,
"s:t:o:i:d:T")) != -1) {
530 (opt ==
'T'),
"invalid command argument")
536 "multiple source grid arguments")
542 "multiple target grid arguments")
546 *weight_filename = optarg;
549 *interp_stack_string = optarg;
552 *debug_grid_file = optarg;
560 optind >= argc,
"non-option ARGV-element: \"%s\"", argv[optind])
566 YAC_ASSERT(*weight_filename != NULL,
"weight_filename argument is missing")
571 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
584 size_t coordinates_idx;
588 coordinates_idx = SIZE_MAX;
593 malloc(basic_grid_data->
num_cells *
sizeof(*cell_center_coords));
595 for (
size_t i = 0; i < basic_grid_data->
num_cells; ++i) {
597 double cell_center_coord[3] = {0.0, 0.0, 0.0};
598 size_t * curr_cell_to_vertex =
604 double * curr_vertex =
606 cell_center_coord[0] += curr_vertex[0];
607 cell_center_coord[1] += curr_vertex[1];
608 cell_center_coord[2] += curr_vertex[2];
611 memcpy(cell_center_coords[i], cell_center_coord, 3 *
sizeof(
double));
620 MPI_IN_PLACE, &coordinates_idx, 1,
623 return coordinates_idx;
627 size_t * nbr_vertices,
double min_lon,
double max_lon,
628 double min_lat,
double max_lat,
629 double ** lon_vertices,
double ** lat_vertices) {
631 *lon_vertices = malloc(nbr_vertices[0] *
sizeof(**lon_vertices));
632 *lat_vertices = malloc(nbr_vertices[1] *
sizeof(**lat_vertices));
634 double lon_diff = max_lon - min_lon;
635 double lat_diff = max_lat - min_lat;
637 for (
size_t i = 0; i < nbr_vertices[0]; ++i)
639 min_lon + (lon_diff * (double)i) / (double)(nbr_vertices[0] - 1);
640 (*lon_vertices)[nbr_vertices[0]-1] = max_lon;
642 for (
size_t i = 0; i < nbr_vertices[1]; ++i)
644 min_lat + (lat_diff * (double)i) / (double)(nbr_vertices[1] - 1);
645 (*lat_vertices)[nbr_vertices[1]-1] = max_lat;
652 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
658 size_t nbr_vertices[2] =
660 double * lon_vertices, * lat_vertices;
665 &lon_vertices, &lat_vertices);
672 lon_vertices, lat_vertices);
690 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
696 size_t nbr_vertices[2] =
698 double * lon_vertices, * lat_vertices;
703 &lon_vertices, &lat_vertices);
743 use_ll_edges, MPI_COMM_WORLD);
755 int valid_mask_value = 0;
783 if (debug_grid_file != NULL)
785 basic_grid, debug_grid_file, MPI_COMM_WORLD);
829 if (!print_timer)
return;
831 yac_mpi_call(MPI_Barrier(MPI_COMM_WORLD), MPI_COMM_WORLD);
835static void timer_stop(
int print_timer,
char const * timer_name) {
837 if (!print_timer)
return;
840 struct time_rank time_rank_min, time_rank_max;
845 MPI_COMM_WORLD), MPI_COMM_WORLD);
849 MPI_COMM_WORLD), MPI_COMM_WORLD);
853 MPI_COMM_WORLD), MPI_COMM_WORLD);
856 yac_mpi_call(MPI_Comm_size(MPI_COMM_WORLD, &comm_size), MPI_COMM_WORLD);
858 fprintf(stdout,
"%s: min %.3lfs (%d) avg %.3lfs max %.3lfs (%d)\n",
859 timer_name, time_rank_min.
time, time_rank_min.
rank,
860 time_sum / (
double)comm_size,
861 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)
Delete an interpolation stack and free its resources (but not the pointer array).
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
Perform weight computation using given interpolation stack and grid.
void yac_interp_stack_config_delete(struct yac_interp_stack_config *interp_stack_config)
Free an interpolation stack configuration object.
struct interp_method ** yac_interp_stack_config_generate(struct yac_interp_stack_config *interp_stack)
Generate a NULL-terminated array of interpolation methods from the stack configuration.
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)
union grid_config::@105 data
struct grid_config::@105::@107 icon
struct grid_config::@105::@110 reg2drot
struct grid_config::@105::@109 reg2d
size_t * duplicated_cell_idx
struct grid_config::@100::@104 scrip
enum grid_edge_type edge_type
char const * mask_filename
yac_int * orig_cell_global_ids
size_t cell_coordinate_idx
struct grid_config::@105::@106 exodus
char const * grid_filename
size_t nbr_duplicated_cells
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]