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