YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
yac_compute_weights.c
Go to the documentation of this file.
1// Copyright (c) 2025 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <mpi.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <unistd.h>
9#include <unistd.h>
10#include <yaxt.h>
11#include <string.h>
12#include <netcdf.h>
13#include "yac.h"
14#include "yac_utils.h"
15#include "yac_mpi_common.h"
16#include "yac_mpi_internal.h"
17
18// redefine YAC assert macros
19#undef YAC_ASSERT
20#undef YAC_ASSERT_F
21static char const * cmd;
22#define DEFAULT_INTERP_STACK \
23 " [\n" \
24 " {\"conservative\":\n" \
25 " {\"order\": 1,\n" \
26 " \"enforced_conservation\": false,\n" \
27 " \"partial_coverage\": false,\n" \
28 " \"normalisation\": \"fracarea\"}\n" \
29 " },\n" \
30 " {\"fixed\":\n" \
31 " {\"user_value\": -1}\n" \
32 " }\n" \
33 " ]\n"
34#define STR_USAGE \
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" \
39 " of processes.\n" \
40 "\n" \
41 "Usage:\n" \
42 "\n" \
43 " mpirun -n $N %s [OPTION]\n" \
44 "\n" \
45 " Mandatory arguments:\n" \
46 " -s/-t GRID_TYPE,{CONFIG}\n" \
47 " type and configuraion of source/target grid\n" \
48 " GRID_TYPE:\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" \
70 " latitude)\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" \
92 " -o FILE\n" \
93 " weight file name\n" \
94 "\n" \
95 " Optional arguments:\n" \
96 " -i {INTERP_STACK}\n" \
97 " JSON-formated interpolation stack configuration " \
98 "(see YAC documentation)\n" \
99 " default value:\n" \
100 DEFAULT_INTERP_STACK \
101 " -T\n" \
102 " enables writing of run-time performance measurments to stdout\n" \
103 "\n" \
104 " Examples:\n" \
105 "\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"\
109 "\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"
113
114#define YAC_ASSERT(exp, msg) \
115 { \
116 if(!((exp))) { \
117 fprintf(stderr, "ERROR: %s\n" STR_USAGE, msg, cmd, cmd, cmd); \
118 exit(EXIT_FAILURE); \
119 } \
120 }
121
122#define YAC_ASSERT_F(exp, format, ...) \
123 { \
124 if(!((exp))) { \
125 fprintf( \
126 stderr, "ERROR: " format "\n\n" STR_USAGE, \
127 __VA_ARGS__, cmd, cmd, cmd); \
128 exit(EXIT_FAILURE); \
129 } \
130 }
131
133
134struct grid_config {
143 union {
144 struct {
145 char const * grid_filename;
149 struct {
150 char const * grid_filename;
151 size_t cell_coordinate_idx;
153 struct {
154 char const * grid_filename;
155 char const * mask_filename;
161 struct {
162 size_t nlon, nlat;
165 struct {
166 size_t nlon, nlat;
167 double min_lon, max_lon, min_lat, max_lat;
171 size_t cell_coordinate_idx;
172 char const * grid_name;
174};
175
176static void parse_arguments(int argc, char ** argv,
177 struct grid_config * src_grid_config,
178 struct grid_config * tgt_grid_config,
179 char const ** weight_filename,
180 char const ** interp_stack_string,
181 int * print_timer,
182 char const ** debug_grid_file);
183
184extern int const YAC_YAML_PARSER_JSON_FORCE;
187 char const * interp_stack_config, int parse_flags);
188
190 struct grid_config * grid_config, char const * debug_grid_file);
191
193
194struct time_rank {
195 double time;
196 int rank;
197};
199static void timer_start(int print_timer);
200static void timer_stop(int print_timer, char const * timer_name);
201
202int main (int argc, char *argv[]) {
203
204 MPI_Init(&argc, &argv);
205 xt_initialize(MPI_COMM_WORLD);
206
208 MPI_Comm_rank(MPI_COMM_WORLD, &local_time_rank.rank), MPI_COMM_WORLD);
209
210 cmd = argv[0];
211
212 // parse command line arguments
213 char const * weight_filename;
214 char const * interp_stack_string;
215 struct grid_config src_grid_config;
216 struct grid_config tgt_grid_config;
217 int print_timer;
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);
222
223 // read grid data
224 timer_start(print_timer);
225 struct yac_basic_grid * src_grid =
226 get_basic_grid_from_config(&src_grid_config, debug_grid_file);
227 timer_stop(print_timer, "read src_grid");
228 timer_start(print_timer);
229 struct yac_basic_grid * tgt_grid =
230 get_basic_grid_from_config(&tgt_grid_config, debug_grid_file);
231 timer_stop(print_timer, "read tgt_grid");
232
233 // generate distributed grid pair
234 timer_start(print_timer);
235 struct yac_dist_grid_pair * grid_pair =
236 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
237 timer_stop(print_timer, "dist_grid_pair generation");
238
239 // setup field information
240 struct yac_interp_field src_fields[] =
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]);
246 {.location = YAC_LOC_CELL,
247 .coordinates_idx = src_grid_config.cell_coordinate_idx,
248 .masks_idx = SIZE_MAX};
249
250 // generate interpolation grid
251 struct yac_interp_grid * interp_grid =
254 yac_basic_grid_get_name(tgt_grid),
256
257 // generate interpolation stack configuration from JSON-formated string
258 struct yac_interp_stack_config * interp_stack_config =
260 interp_stack_string, YAC_YAML_PARSER_JSON_FORCE);
261
262 // generate interpolation stack
263 struct interp_method ** interp_stack =
264 yac_interp_stack_config_generate(interp_stack_config);
265
266 // compute interpolation weights
267 timer_start(print_timer);
268 struct yac_interp_weights * weights =
269 yac_interp_method_do_search(interp_stack, interp_grid);
270 timer_stop(print_timer, "weight computation");
271
272 // OASIS SCRIP formated grid files may contain duplicated cell, these are
273 // masked out in the basic grid, but still require a interpolation stencil
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);
279 }
280
281 // write weights to file
282 timer_start(print_timer);
285 weights, weight_filename, yac_basic_grid_get_name(src_grid),
286 yac_basic_grid_get_name(tgt_grid), src_grid_config.global_num_cells,
287 tgt_grid_config.global_num_cells, on_existing);
288 timer_stop(print_timer, "writing weight file");
289
290 // cleanup
291 grid_config_delete(tgt_grid_config);
292 grid_config_delete(src_grid_config);
294 yac_interp_method_delete(interp_stack);
295 free(interp_stack);
296 yac_interp_stack_config_delete(interp_stack_config);
297 yac_interp_grid_delete(interp_grid);
298 yac_dist_grid_pair_delete(grid_pair);
299 yac_basic_grid_delete(tgt_grid);
300 yac_basic_grid_delete(src_grid);
301
302 xt_finalize();
303 MPI_Finalize();
304
305 return EXIT_SUCCESS;
306}
307
308static enum grid_edge_type parse_edge_type(char const * edge_type_string) {
309
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);
317
318 return is_gc?GC_EDGES:LL_EDGES;
319}
320
321static size_t parse_size_t(char const * size_t_string) {
322
323 char * endptr;
324 long int long_value = strtol(size_t_string, &endptr, 10);
325
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);
330
331 return (size_t)long_value;
332}
333
334static double parse_double(char const * double_string) {
335
336 char * endptr;
337 double dble_value = strtod(double_string, &endptr);
338
340 (endptr != double_string) && (*endptr == '\0'),
341 "\"%s\" is not a valid double value", double_string);
342 free((void*)double_string);
343
344 return dble_value;
345}
346
347static char const * get_next_token(char const * token_name) {
348 char const * token = strtok(NULL, ",");
349 YAC_ASSERT_F(token, "missing %s", token_name);
350 return strdup(token);
351}
352
353size_t read_netcdf_dimension(char const * filename, char const * dim_name) {
354
355 int rank;
356 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
357
358 size_t dimlen;
359
360 if (rank == 0) {
361 int ncid, dimid;
362 yac_nc_open(filename, NC_NOWRITE, &ncid);
363 yac_nc_inq_dimid(ncid, dim_name, &dimid);
364 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &dimlen));
365 }
366
368 MPI_Bcast(&dimlen, 1, YAC_MPI_SIZE_T, 0, MPI_COMM_WORLD), MPI_COMM_WORLD);
369
370 return dimlen;
371}
372
374
375 char const * grid_filename = get_next_token("exodus grid filename");
376 char const * grid_name = get_next_token("exodus grid name");
378 parse_edge_type(get_next_token("exodus edge type"));
380 return
381 (struct grid_config) {
382 .type = EXODUS,
383 .grid_name = grid_name,
384 .global_num_cells = global_num_cells,
385 .data.exodus.grid_filename = grid_filename,
386 .data.exodus.edge_type = edge_type
387 };
388}
389
391
392 char const * grid_filename = get_next_token("icon grid filename");
393 char const * grid_name = get_next_token("icon grid name");
395 return
396 (struct grid_config) {
397 .type = ICON,
398 .grid_name = grid_name,
399 .global_num_cells = global_num_cells,
400 .data.icon.grid_filename = grid_filename
401 };
402}
403
405
406 char const * grid_filename = get_next_token("scrip grid filename");
407 char const * grid_name = get_next_token("scrip grid name");
409 parse_edge_type(get_next_token("scrip edge type"));
410 char const * mask_filename = get_next_token("scrip mask filename");
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);
415 size_t global_num_cells =
418 free(y_dim_name);
419 free(x_dim_name);
420 return
421 (struct grid_config) {
422 .type = SCRIP,
423 .grid_name = grid_name,
424 .global_num_cells = global_num_cells,
425 .data.scrip.grid_filename = grid_filename,
426 .data.scrip.edge_type = edge_type,
427 .data.scrip.mask_filename = mask_filename
428 };
429}
430
432
433 char const * grid_name = get_next_token("reg2d grid name");
434 size_t nlon = parse_size_t(get_next_token("reg2d number of vertices in lon"));
435 size_t nlat = parse_size_t(get_next_token("reg2d number of vertices in lat"));
436 double min_lon = parse_double(get_next_token("reg2d minimum longitude"));
437 double max_lon = parse_double(get_next_token("reg2d maximum longitude"));
438 double min_lat = parse_double(get_next_token("reg2d minimum latitude"));
439 double max_lat = parse_double(get_next_token("reg2d maximum latitude"));
440 return
441 (struct grid_config) {
442 .type = REG2D,
443 .grid_name = grid_name,
444 .global_num_cells = (nlon - 1) * (nlat - 1),
445 .data.reg2d.nlon = nlon,
446 .data.reg2d.nlat = nlat,
447 .data.reg2d.min_lon = min_lon,
448 .data.reg2d.max_lon = max_lon,
449 .data.reg2d.min_lat = min_lat,
450 .data.reg2d.max_lat = max_lat
451 };
452}
453
455
456 char const * grid_name = get_next_token("reg2d grid name");
457 size_t nlon = parse_size_t(get_next_token("reg2d number of vertices in lon"));
458 size_t nlat = parse_size_t(get_next_token("reg2d number of vertices in lat"));
459 double min_lon = parse_double(get_next_token("reg2d minimum longitude"));
460 double max_lon = parse_double(get_next_token("reg2d maximum longitude"));
461 double min_lat = parse_double(get_next_token("reg2d minimum latitude"));
462 double max_lat = parse_double(get_next_token("reg2d maximum latitude"));
463 double pole_lon = parse_double(get_next_token("reg2d pole longitude"));
464 double pole_lat = parse_double(get_next_token("reg2d pole latitude"));
465 return
466 (struct grid_config) {
467 .type = REG2DROT,
468 .grid_name = grid_name,
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,
476 .data.reg2drot.pole_lon = pole_lon,
477 .data.reg2drot.pole_lat = pole_lat
478 };
479}
480
482 char const * grid_config_string_, char const * src_tgt) {
483
485
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))
498
499 free(grid_config_string);
500
503 "invalid %s grid type (\"%s\")", src_tgt, grid_type_string);
504
505 return grid_config;
506}
507
508static void parse_arguments(int argc, char ** argv,
509 struct grid_config * src_grid_config,
510 struct grid_config * tgt_grid_config,
511 char const ** weight_filename,
512 char const ** interp_stack_string,
513 int * print_timer,
514 char const ** debug_grid_file) {
515
516 src_grid_config->type = UNDEFINED_GRID;
517 tgt_grid_config->type = UNDEFINED_GRID;
518 *weight_filename = NULL;
519 *interp_stack_string = DEFAULT_INTERP_STACK;
520 *print_timer = 0;
521 *debug_grid_file = NULL;
522
523 int opt;
524 while ((opt = getopt(argc, argv, "s:t:o:i:d:T")) != -1) {
526 (opt == 's') ||
527 (opt == 't') ||
528 (opt == 'o') ||
529 (opt == 'i') ||
530 (opt == 'd') ||
531 (opt == 'T'), "invalid command argument")
532 switch (opt) {
533 default:
534 case 's':
536 src_grid_config->type == UNDEFINED_GRID,
537 "multiple source grid arguments")
538 *src_grid_config = parse_grid_config(optarg, "source");
539 break;
540 case 't':
542 tgt_grid_config->type == UNDEFINED_GRID,
543 "multiple target grid arguments")
544 *tgt_grid_config = parse_grid_config(optarg, "target");
545 break;
546 case 'o':
547 *weight_filename = optarg;
548 break;
549 case 'i':
550 *interp_stack_string = optarg;
551 break;
552 case 'd':
553 *debug_grid_file = optarg;
554 break;
555 case 'T':
556 *print_timer = 1;
557 break;
558 }
559 }
561 optind >= argc, "non-option ARGV-element: \"%s\"", argv[optind])
562 YAC_ASSERT(argc != 1, "too few arguments")
564 src_grid_config->type != UNDEFINED_GRID, "source grid argument is missing")
566 tgt_grid_config->type != UNDEFINED_GRID, "target grid argument is missing")
567 YAC_ASSERT(*weight_filename != NULL, "weight_filename argument is missing")
568}
569
570static inline void normalise_vector(double v[]) {
571
572 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
573
574 v[0] *= norm;
575 v[1] *= norm;
576 v[2] *= norm;
577}
578
580 struct yac_basic_grid * basic_grid) {
581
582 struct yac_basic_grid_data * basic_grid_data =
583 yac_basic_grid_get_data(basic_grid);
584
585 size_t coordinates_idx;
586
587 if (basic_grid_data->num_cells == 0) {
588
589 coordinates_idx = SIZE_MAX;
590
591 } else {
592
593 yac_coordinate_pointer cell_center_coords =
594 malloc(basic_grid_data->num_cells * sizeof(*cell_center_coords));
595
596 for (size_t i = 0; i < basic_grid_data->num_cells; ++i) {
597
598 double cell_center_coord[3] = {0.0, 0.0, 0.0};
599 size_t * curr_cell_to_vertex =
600 basic_grid_data->cell_to_vertex +
601 basic_grid_data->cell_to_vertex_offsets[i];
602
603 for (int j = 0; j < basic_grid_data->num_vertices_per_cell[i]; ++j) {
604
605 double * curr_vertex =
606 basic_grid_data->vertex_coordinates[curr_cell_to_vertex[j]];
607 cell_center_coord[0] += curr_vertex[0];
608 cell_center_coord[1] += curr_vertex[1];
609 cell_center_coord[2] += curr_vertex[2];
610 }
611 normalise_vector(cell_center_coord);
612 memcpy(cell_center_coords[i], cell_center_coord, 3 * sizeof(double));
613 }
614 coordinates_idx =
616 basic_grid, YAC_LOC_CELL, cell_center_coords);
617 }
618
620 MPI_Allreduce(
621 MPI_IN_PLACE, &coordinates_idx, 1,
622 YAC_MPI_SIZE_T, MPI_MIN, MPI_COMM_WORLD), MPI_COMM_WORLD);
623
624 return coordinates_idx;
625}
626
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) {
631
632 *lon_vertices = malloc(nbr_vertices[0] * sizeof(**lon_vertices));
633 *lat_vertices = malloc(nbr_vertices[1] * sizeof(**lat_vertices));
634
635 double lon_diff = max_lon - min_lon;
636 double lat_diff = max_lat - min_lat;
637
638 for (size_t i = 0; i < nbr_vertices[0]; ++i)
639 (*lon_vertices)[i] =
640 min_lon + (lon_diff * (double)i) / (double)(nbr_vertices[0] - 1);
641 (*lon_vertices)[nbr_vertices[0]-1] = max_lon;
642
643 for (size_t i = 0; i < nbr_vertices[1]; ++i)
644 (*lat_vertices)[i] =
645 min_lat + (lat_diff * (double)i) / (double)(nbr_vertices[1] - 1);
646 (*lat_vertices)[nbr_vertices[1]-1] = max_lat;
647}
648
650 struct grid_config grid_config) {
651
652 int rank;
653 yac_mpi_call(MPI_Comm_rank(MPI_COMM_WORLD, &rank), MPI_COMM_WORLD);
654
655 struct yac_basic_grid * basic_grid;
656
657 if (rank == 0) {
658
659 size_t nbr_vertices[2] =
661 double * lon_vertices, * lat_vertices;
663 nbr_vertices,
666 &lon_vertices, &lat_vertices);
667
668 int cyclic[2] = {0,0};
669
670 basic_grid =
672 grid_config.grid_name, nbr_vertices, cyclic,
673 lon_vertices, lat_vertices);
674
675 free(lon_vertices);
676 free(lat_vertices);
677
678 } else {
679
681
682 }
683
684 return basic_grid;
685}
686
688 struct grid_config grid_config) {
689
690 int rank;
691 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
692
693 struct yac_basic_grid * basic_grid;
694
695 if (rank == 0) {
696
697 size_t nbr_vertices[2] =
699 double * lon_vertices, * lat_vertices;
701 nbr_vertices,
704 &lon_vertices, &lat_vertices);
705
706 int cyclic[2] = {0,0};
707
708 basic_grid =
710 grid_config.grid_name, nbr_vertices, cyclic, lon_vertices, lat_vertices,
712
713 free(lon_vertices);
714 free(lat_vertices);
715
716 } else {
717
719
720 }
721
722 return basic_grid;
723}
724
726 struct grid_config * grid_config, char const * debug_grid_file) {
727
728 struct yac_basic_grid * basic_grid = NULL;
729
731 (grid_config->type == EXODUS) ||
732 (grid_config->type == ICON) ||
733 (grid_config->type == SCRIP) ||
734 (grid_config->type == REG2D) ||
735 (grid_config->type == REG2DROT), "invalid grid type");
736
737 switch (grid_config->type) {
738 default:
739 case (EXODUS): {
740 int use_ll_edges = grid_config->data.exodus.edge_type == LL_EDGES;
741 basic_grid =
744 use_ll_edges, MPI_COMM_WORLD);
747 break;
748 }
749 case (ICON): {
752 MPI_COMM_WORLD, &basic_grid, &grid_config->cell_coordinate_idx, NULL);
753 break;
754 }
755 case (SCRIP): {
756 int valid_mask_value = 0;
757 int use_ll_edges = grid_config->data.scrip.edge_type == LL_EDGES;
758 basic_grid =
762 MPI_COMM_WORLD, grid_config->grid_name, valid_mask_value,
763 grid_config->grid_name, use_ll_edges,
768 break;
769 }
770 case (REG2D): {
771 basic_grid = generate_reg2d_grid(*grid_config);
774 break;
775 }
776 case (REG2DROT): {
777 basic_grid = generate_reg2drot_grid(*grid_config);
780 break;
781 }
782 }
783
784 if (debug_grid_file != NULL)
786 basic_grid, debug_grid_file, MPI_COMM_WORLD);
787
788 return basic_grid;
789}
790
792
794 (grid_config.type == EXODUS) ||
795 (grid_config.type == ICON) ||
796 (grid_config.type == SCRIP) ||
797 (grid_config.type == REG2D) ||
798 (grid_config.type == REG2DROT), "invalid grid type");
799
800 free((void*)grid_config.grid_name);
801
802 switch (grid_config.type) {
803 default:
804 case (EXODUS): {
806 break;
807 }
808 case (ICON): {
809 free((void*)grid_config.data.icon.grid_filename);
810 break;
811 }
812 case (SCRIP): {
813 free((void*)grid_config.data.scrip.grid_filename);
814 free((void*)grid_config.data.scrip.mask_filename);
817 break;
818 }
819 case (REG2D): {
820 break;
821 }
822 case (REG2DROT): {
823 break;
824 }
825 }
826}
827
828static void timer_start(int print_timer) {
829
830 if (!print_timer) return;
831
832 yac_mpi_call(MPI_Barrier(MPI_COMM_WORLD), MPI_COMM_WORLD);
833 local_time_rank.time = MPI_Wtime();
834}
835
836static void timer_stop(int print_timer, char const * timer_name) {
837
838 if (!print_timer) return;
839
841 struct time_rank time_rank_min, time_rank_max;
842 double time_sum;
844 MPI_Reduce(
845 &local_time_rank, &time_rank_min, 1, MPI_DOUBLE_INT, MPI_MINLOC, 0,
846 MPI_COMM_WORLD), MPI_COMM_WORLD);
848 MPI_Reduce(
849 &local_time_rank, &time_rank_max, 1, MPI_DOUBLE_INT, MPI_MAXLOC, 0,
850 MPI_COMM_WORLD), MPI_COMM_WORLD);
852 MPI_Reduce(
853 &local_time_rank.time, &time_sum, 1, MPI_DOUBLE, MPI_SUM, 0,
854 MPI_COMM_WORLD), MPI_COMM_WORLD);
855
856 int comm_size;
857 yac_mpi_call(MPI_Comm_size(MPI_COMM_WORLD, &comm_size), MPI_COMM_WORLD);
858 if (local_time_rank.rank == 0)
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);
863}
struct @4 grid_config[]
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)
Definition basic_grid.c:335
void yac_basic_grid_to_file_parallel(struct yac_basic_grid *grid, char const *filename, MPI_Comm comm)
Definition basic_grid.c:768
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)
Definition basic_grid.c:503
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:137
size_t yac_basic_grid_add_coordinates_nocpy(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates)
Definition basic_grid.c:208
char const * yac_basic_grid_get_name(struct yac_basic_grid *grid)
Definition basic_grid.c:128
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:63
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:70
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2313
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)
Definition dist_grid.c:2061
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)
Definition interp_grid.c:31
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)
Definition io_utils.c:350
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:385
@ YAC_LOC_CELL
Definition location.h:14
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_type type
enum grid_edge_type edge_type
char const * mask_filename
yac_int * orig_cell_global_ids
char const * grid_name
char const * grid_filename
struct grid_config::@112::@114 icon
yac_coordinate_pointer vertex_coordinates
size_t * cell_to_vertex_offsets
enum yac_location location
Definition basic_grid.h:16
struct yac_interp_field tgt_field
Definition interp_grid.c:26
size_t num_src_fields
Definition interp_grid.c:27
struct yac_dist_grid_pair * grid_pair
Definition interp_grid.c:25
struct yac_interp_field src_fields[]
Definition interp_grid.c:28
unsigned cyclic[2]
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
@ SCRIP
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 char const * cmd
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
Definition config_yaml.c:70
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)
#define YAC_MPI_SIZE_T
YAC_INT yac_int
Definition yac_types.h:15
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19