YAC 3.20.0
Yet Another Coupler
Loading...
Searching...
No Matches
basic_grid.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdio.h>
6#include <string.h>
7
8#include <mpi.h>
9#include <yaxt.h>
10
11#include "grids/basic_grid.h"
12#include "grids/grid_cell.h"
13#include "field_data_set.h"
14#include "io_utils.h"
15#include "yac_mpi_internal.h"
16#include "time.h"
17#include "yac_config.h"
18#include "geometry.h"
19
20#ifdef YAC_NETCDF_ENABLED
21#include <netcdf.h>
22#endif
23
30
32 .vertex_coordinates = NULL,
33 .cell_ids = NULL,
34 .vertex_ids = NULL,
35 .edge_ids = NULL,
36 .num_cells = 0,
37 .num_vertices = 0,
38 .num_edges = 0,
39 .core_cell_mask = NULL,
40 .core_vertex_mask = NULL,
41 .core_edge_mask = NULL,
42 .num_vertices_per_cell = NULL,
43 .num_cells_per_vertex = NULL,
44 .cell_to_vertex = NULL,
45 .cell_to_vertex_offsets = NULL,
46 .cell_to_edge = NULL,
47 .cell_to_edge_offsets = NULL,
48 .vertex_to_cell = NULL,
49 .vertex_to_cell_offsets = NULL,
50 .edge_to_vertex = NULL,
51 .edge_type = NULL,
52 .num_total_cells = 0,
53 .num_total_vertices = 0,
54 .num_total_edges = 0
55};
56
58 char const * name, struct yac_basic_grid_data grid_data) {
59
60 struct yac_basic_grid * grid = xmalloc(1 * sizeof(*grid));
61
62 grid->name = xstrdup(name);
63 grid->is_empty = 0;
64 grid->field_data_set = yac_field_data_set_empty_new();
65 grid->data = grid_data;
66
67 return grid;
68}
69
71 struct yac_basic_grid * grid =
73 grid->is_empty = 1;
74 return grid;
75}
76
78
79 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
80 free(grid->name);
81 yac_field_data_set_delete(grid->field_data_set);
82 yac_basic_grid_data_free(grid->data);
83 free(grid);
84}
85
87 struct yac_basic_grid * grid, struct yac_interp_field field) {
88
89 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
90
92 (field.coordinates_idx != SIZE_MAX)?
94 yac_basic_grid_get_field_data(grid, field.location),
95 field.coordinates_idx):NULL;
96
97 // if no field coordinates are defined, but the location is at the corners of
98 // of the grid cells, return coordinates of them
99 return
100 ((coords != NULL) || (field.location != YAC_LOC_CORNER))?
101 coords:((yac_const_coordinate_pointer)(grid->data.vertex_coordinates));
102}
103
105 struct yac_basic_grid * grid, enum yac_location location) {
106
108 (location == YAC_LOC_CELL) ||
110 (location == YAC_LOC_EDGE), "invalid location")
111
112 switch (location) {
113 default:
114 case(YAC_LOC_CELL): return grid->data.core_cell_mask;
115 case(YAC_LOC_CORNER): return grid->data.core_vertex_mask;
116 case(YAC_LOC_EDGE): return grid->data.core_edge_mask;
117 };
118}
119
121 struct yac_basic_grid * grid, struct yac_interp_field field) {
122
123 if (field.masks_idx == SIZE_MAX) return NULL;
124
125 return
127 yac_basic_grid_get_field_data(grid, field.location), field.masks_idx);
128}
129
130char const * yac_basic_grid_get_name(struct yac_basic_grid * grid) {
131
132 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
133
134 return grid->name;
135}
136
138 struct yac_basic_grid * grid) {
139
140 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
141
142 return &(grid->data);
143}
144
146 struct yac_basic_grid * grid, enum yac_location location) {
147
148 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
150 (location == YAC_LOC_CELL) ||
152 (location == YAC_LOC_EDGE), "invalid location")
153
154 switch (location) {
155 default:
156 case (YAC_LOC_CELL):
157 return grid->data.num_cells;
158 case (YAC_LOC_CORNER):
159 return grid->data.num_vertices;
160 case (YAC_LOC_EDGE):
161 return grid->data.num_edges;
162 };
163}
164
171
173 struct yac_basic_grid * grid, enum yac_location location,
174 char const * mask_name) {
175
176 if (mask_name == NULL) return SIZE_MAX;
177
178 struct yac_field_data * data =
180
181 if (data == NULL) return SIZE_MAX;
182
183 size_t mask_idx = SIZE_MAX;
185
186 for (size_t i = 0; (i < masks_count) && (mask_idx == SIZE_MAX); ++i) {
187 char const * curr_mask_name =
189 if ((curr_mask_name != NULL) &&
190 (!strcmp(mask_name, curr_mask_name)))
191 mask_idx = i;
192 }
193
195 mask_idx != SIZE_MAX,
196 "grid \"%s\" does not contain %s-mask with the name \"%s\"",
197 grid->name, yac_loc2str(location), mask_name)
198
199 return mask_idx;
200}
201
203 struct yac_basic_grid * grid,
205
206 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
207 YAC_ASSERT_F(!grid->is_empty, "grid \"%s\" is an empty grid", grid->name)
208
209 return
211 grid->field_data_set, location, coordinates);
212}
213
221
223 struct yac_basic_grid * grid, enum yac_location location,
224 yac_coordinate_pointer coordinates, size_t count) {
225
226 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
227 YAC_ASSERT_F(!grid->is_empty, "grid \"%s\" is an empty grid", grid->name)
228
229 return
231 grid->field_data_set, location, coordinates, count);
232}
233
235 struct yac_basic_grid * grid, int location,
236 double * coordinates, size_t count) {
237
238 return
242}
243
245 struct yac_basic_grid * grid,
246 enum yac_location location, int const * mask,
247 char const * mask_name) {
248
249 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
250 YAC_ASSERT_F(!grid->is_empty, "grid \"%s\" is an empty grid", grid->name)
251
252 return
254 grid->field_data_set, location, mask, mask_name);
255}
256
258 struct yac_basic_grid * grid, int location,
259 int const * mask, char const * mask_name) {
260
261 return
263 grid, yac_get_location(location), mask, mask_name);
264}
265
267 struct yac_basic_grid * grid, enum yac_location location,
268 int const * mask, size_t count, char const * mask_name) {
269
270 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
271 YAC_ASSERT_F(!grid->is_empty, "grid \"%s\" is an empty grid", grid->name)
272
273 return
275 grid->field_data_set, location, mask, count, mask_name);
276}
277
279 struct yac_basic_grid * grid, int location,
280 int const * mask, size_t count, char const * mask_name) {
281
282 return
284 grid, yac_get_location(location), mask, count, mask_name);
285}
286
288 struct yac_basic_grid * grid, enum yac_location location) {
289
290 YAC_ASSERT(grid, "NULL is not a valid value for argument grid")
291
292 if (grid->is_empty)
293 return NULL;
294 else
295 return
297 grid->field_data_set, location);
298}
299
301 char const * name, size_t nbr_vertices[2], int cyclic[2],
302 double *lon_vertices, double *lat_vertices) {
303
304 return
306 name,
308 nbr_vertices, cyclic, lon_vertices, lat_vertices));
309}
310
312 char const * name, size_t nbr_vertices[2], int cyclic[2],
313 double *lon_vertices, double *lat_vertices) {
314
315 return
317 name,
319 nbr_vertices, cyclic, lon_vertices, lat_vertices));
320}
321
323 char const * name, size_t nbr_vertices[2], int cyclic[2],
324 double *lon_vertices, double *lat_vertices) {
325
326 return
328 name,
330 nbr_vertices, cyclic, lon_vertices, lat_vertices));
331}
332
334 char const * name, size_t nbr_vertices[2], int cyclic[2],
335 double *lon_vertices, double *lat_vertices) {
336
337 return
339 name,
341 nbr_vertices, cyclic, lon_vertices, lat_vertices));
342}
343
345 char const * name, size_t nbr_vertices, size_t nbr_cells,
346 int *num_vertices_per_cell, double *x_vertices, double *y_vertices,
347 int *cell_to_vertex) {
348
349 return
351 name,
353 nbr_vertices, nbr_cells, num_vertices_per_cell,
354 x_vertices, y_vertices, cell_to_vertex));
355}
356
358 char const * name, size_t nbr_vertices, size_t nbr_cells,
359 int *num_vertices_per_cell, double *x_vertices, double *y_vertices,
360 int *cell_to_vertex) {
361
362 return
364 name,
366 nbr_vertices, nbr_cells, num_vertices_per_cell,
367 x_vertices, y_vertices, cell_to_vertex));
368}
369
371 char const * name, size_t nbr_vertices, size_t nbr_cells,
372 int *num_vertices_per_cell, double *x_vertices, double *y_vertices,
373 int *cell_to_vertex) {
374
375 return
377 name,
379 nbr_vertices, nbr_cells, num_vertices_per_cell,
380 x_vertices, y_vertices, cell_to_vertex));
381}
382
384 char const * name, size_t nbr_vertices, size_t nbr_cells,
385 int *num_vertices_per_cell, double *x_vertices, double *y_vertices,
386 int *cell_to_vertex) {
387
388 return
390 name,
392 nbr_vertices, nbr_cells, num_vertices_per_cell,
393 x_vertices, y_vertices, cell_to_vertex));
394}
395
397 char const * name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
398 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
399 int *cell_to_edge, int *edge_to_vertex) {
400
401 return
403 name,
405 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
406 x_vertices, y_vertices, cell_to_edge, edge_to_vertex));
407}
408
410 char const * name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
411 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
412 int *cell_to_edge, int *edge_to_vertex) {
413
414 return
416 name,
418 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
419 x_vertices, y_vertices, cell_to_edge, edge_to_vertex));
420}
421
423 char const * name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
424 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
425 int *cell_to_edge, int *edge_to_vertex) {
426
427 return
429 name,
431 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
432 x_vertices, y_vertices, cell_to_edge, edge_to_vertex));
433}
434
436 char const * name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
437 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
438 int *cell_to_edge, int *edge_to_vertex) {
439
440 return
442 name,
444 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
445 x_vertices, y_vertices, cell_to_edge, edge_to_vertex));
446}
447
449 char const * name, size_t nbr_points, double *x_points, double *y_points) {
450
451 return
453 name,
454 yac_generate_basic_grid_data_cloud(nbr_points, x_points, y_points));
455}
456
458 char const * name, size_t nbr_points, double *x_points, double *y_points) {
459
460 return
462 name,
463 yac_generate_basic_grid_data_cloud_deg(nbr_points, x_points, y_points));
464}
465
467 char const * name, size_t nbr_vertices[2], int cyclic[2],
468 double *lon_vertices, double *lat_vertices,
469 double north_pole_lon, double north_pole_lat) {
470
471 return
473 name,
475 nbr_vertices, cyclic, lon_vertices, lat_vertices,
476 north_pole_lon, north_pole_lat));
477}
478
480 char const * name, size_t nbr_vertices[2], int cyclic[2],
481 double *lon_vertices, double *lat_vertices,
482 double north_pole_lon, double north_pole_lat) {
483
484 return
486 name,
488 nbr_vertices, cyclic, lon_vertices, lat_vertices,
489 north_pole_lon, north_pole_lat));
490}
491
492#ifdef YAC_NETCDF_ENABLED
493
494static int def_dim(
495 char const * filename, int ncid, char const * name, size_t dim_len,
496 int file_is_new) {
497
498 int create_dim = file_is_new;
499 int dim_id;
500
501 // if the netcdf file already exists
502 if (!file_is_new) {
503
504 // check whether the dimension already exists in the file
505 int status = nc_inq_dimid(ncid, name, &dim_id);
506
507 // if the dimension already exists, check for a consistent dimension size
508 if (!((create_dim = (status == NC_EBADDIM)))) {
509
510 YAC_HANDLE_ERROR(status);
511
512 size_t temp_dim_len;
513 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &temp_dim_len));
514
516 dim_len == temp_dim_len,
517 "file \"%s\" already contains dimension \"%s\", "
518 "but it has a different size %zu != %zu",
519 filename, name, dim_len, temp_dim_len);
520 }
521 }
522
523 if (create_dim) YAC_HANDLE_ERROR(nc_def_dim(ncid, name, dim_len, &dim_id));
524
525 return dim_id;
526}
527
528static void def_var(
529 char const * filename, int ncid, char const * name, nc_type type,
530 int ndims, const int * dimids, char const * att_name, char const * att_value,
531 int file_is_new) {
532
533 int create_var = file_is_new;
534 int var_id;
535
536 // if the netcdf file already exists
537 if (!file_is_new) {
538
539 // check whether the variable already exists in the file
540 int status = nc_inq_varid(ncid, name, &var_id);
541
542 // if the variable already exists
543 if (!((create_var = (status == NC_ENOTVAR)))) {
544
545 YAC_HANDLE_ERROR(status);
546
547 // check the consistency of the variable definition
548 nc_type temp_type;
549 int temp_ndims;
550 int temp_dimids[NC_MAX_VAR_DIMS];
552 nc_inq_var(
553 ncid, var_id, NULL, &temp_type, &temp_ndims, temp_dimids, NULL));
555 type == temp_type,
556 "file \"%s\" already contains variable \"%s\", "
557 "but it has a different data type %d != %d",
558 filename, name, type, temp_type);
560 ndims == temp_ndims, "file \"%s\" already contains variable \"%s\", "
561 "but it has a different number of dimensions %d != %d",
562 filename, name, ndims, temp_ndims);
563 for (int i = 0; i < ndims; ++i) {
565 dimids[i] == temp_dimids[i],
566 "file \"%s\" already contains variable \"%s\", "
567 "but it has a different dimensions dimid[%d] %d != %d",
568 filename, name, i, dimids[i], temp_dimids[i]);
569 }
570
571 if (att_name != NULL) {
572
573 size_t att_len;
574 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id, att_name, &att_len));
575
576 char * temp_att_value = xcalloc((att_len + 1), sizeof(temp_att_value));
577 YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, att_name, temp_att_value));
578
580 !strcmp(att_value, temp_att_value),
581 "file \"%s\" already contains variable \"%s\", "
582 "but it has a different attribute value "
583 "(name: \"%s\") \"%s\" != \"%s\"",
584 filename, name, att_name, att_value, temp_att_value);
585 free(temp_att_value);
586 }
587 }
588 }
589
590 if (create_var) {
591 YAC_HANDLE_ERROR(nc_def_var(ncid, name, type, ndims, dimids, &var_id));
592 if (att_name != NULL)
594 nc_put_att_text(ncid, var_id, att_name, strlen(att_value), att_value));
595 }
596}
597
599 char const * filename, char const * grid_name, size_t num_cells,
600 int num_vertices_per_cell, int cell_center_coords_avaiable,
601 int cell_global_ids_available, int core_cell_mask_available,
602 int vertex_global_ids_available, int core_vertex_mask_available,
603 int edge_global_ids_available, int core_edge_mask_available) {
604
605 size_t grid_name_len = strlen(grid_name) + 1;
606
607 char nv_dim_name[3 + grid_name_len];
608 char nc_dim_name[3 + grid_name_len];
609
610 char cla_var_name[4 + grid_name_len];
611 char clo_var_name[4 + grid_name_len];
612 char lat_var_name[4 + grid_name_len];
613 char lon_var_name[4 + grid_name_len];
614 char rnk_var_name[4 + grid_name_len];
615 char cmk_var_name[4 + grid_name_len];
616 char gid_var_name[4 + grid_name_len];
617 char vcmk_var_name[5 + grid_name_len];
618 char vgid_var_name[5 + grid_name_len];
619 char ecmk_var_name[5 + grid_name_len];
620 char egid_var_name[5 + grid_name_len];
621 char const * unit_att = "units";
622 char const * coord_unit = "degree";
623
624 snprintf(nv_dim_name, 3 + grid_name_len, "nv_%s", grid_name);
625 snprintf(nc_dim_name, 3 + grid_name_len, "nc_%s", grid_name);
626
627 snprintf(cla_var_name, 4 + grid_name_len, "%s.cla", grid_name);
628 snprintf(clo_var_name, 4 + grid_name_len, "%s.clo", grid_name);
629 snprintf(lat_var_name, 4 + grid_name_len, "%s.lat", grid_name);
630 snprintf(lon_var_name, 4 + grid_name_len, "%s.lon", grid_name);
631 snprintf(rnk_var_name, 4 + grid_name_len, "%s.rnk", grid_name);
632 snprintf(cmk_var_name, 4 + grid_name_len, "%s.cmk", grid_name);
633 snprintf(gid_var_name, 4 + grid_name_len, "%s.gid", grid_name);
634 snprintf(vcmk_var_name, 5 + grid_name_len, "%s.vcmk", grid_name);
635 snprintf(vgid_var_name, 5 + grid_name_len, "%s.vgid", grid_name);
636 snprintf(ecmk_var_name, 5 + grid_name_len, "%s.ecmk", grid_name);
637 snprintf(egid_var_name, 5 + grid_name_len, "%s.egid", grid_name);
638
639 int ncid;
640
641 // create/open file
642 int file_is_new = !yac_file_exists(filename);
643 if (file_is_new) {
644 yac_nc_create(filename, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
645 } else {
646 yac_nc_open(filename, NC_WRITE | NC_SHARE, &ncid);
647 nc_redef(ncid);
648 }
649
650 // define dimensions
651 int nv_dim_id =
652 def_dim(filename, ncid, nv_dim_name, (size_t)num_vertices_per_cell, file_is_new);
653 int nc_dim_id =
654 def_dim(filename, ncid, nc_dim_name, (size_t)num_cells, file_is_new);
655
656 // define variables
657 int corner_dims[2] = {nc_dim_id, nv_dim_id};
658 int cell_dims[1] = {nc_dim_id};
659 def_var(
660 filename, ncid, cla_var_name, NC_DOUBLE, 2, corner_dims,
661 unit_att, coord_unit, file_is_new);
662 def_var(
663 filename, ncid, clo_var_name, NC_DOUBLE, 2, corner_dims,
664 unit_att, coord_unit, file_is_new);
665 if (cell_center_coords_avaiable) {
666 def_var(
667 filename, ncid, lat_var_name, NC_DOUBLE, 1, cell_dims,
668 unit_att, coord_unit, file_is_new);
669 def_var(
670 filename, ncid, lon_var_name, NC_DOUBLE, 1, cell_dims,
671 unit_att, coord_unit, file_is_new);
672 }
673 if (cell_global_ids_available)
674 def_var(
675 filename, ncid, gid_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
676 if (core_cell_mask_available)
677 def_var(
678 filename, ncid, cmk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
679 if (vertex_global_ids_available)
680 def_var(
681 filename, ncid, vgid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
682 if (core_vertex_mask_available)
683 def_var(
684 filename, ncid, vcmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
685 if (edge_global_ids_available)
686 def_var(
687 filename, ncid, egid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
688 if (core_edge_mask_available)
689 def_var(
690 filename, ncid, ecmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
691 def_var(
692 filename, ncid, rnk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
693
694 time_t now = time(NULL);
695 char str_now_UTC[32];
696 strftime(
697 str_now_UTC, sizeof(str_now_UTC), "%Y-%m-%dT%H:%M:%SZ",
698 gmtime(&now));
699 char const * yac_version = YAC_VERSION;
700 char const * yac_core_version = YAC_CORE_VERSION;
701 char const * created_by = "Created by YAC";
702 char const * grid_type = "curvilinear";
704 nc_put_att_text(ncid, NC_GLOBAL, "YAC", strlen(yac_version), yac_version));
706 nc_put_att_text(
707 ncid, NC_GLOBAL, "YAC_core", strlen(yac_core_version), yac_core_version));
709 nc_put_att_text(ncid, NC_GLOBAL, "title", strlen(created_by), created_by));
711 nc_put_att_text(ncid, NC_GLOBAL, "description", strlen(created_by), created_by));
713 nc_put_att_text(ncid, NC_GLOBAL, "grid", strlen(grid_type), grid_type));
715 nc_put_att_text(ncid, NC_GLOBAL, "timeStamp", strlen(str_now_UTC), str_now_UTC));
716
717 // end definition
718 YAC_HANDLE_ERROR(nc_enddef(ncid));
719
720 // close file
721 YAC_HANDLE_ERROR(nc_close(ncid));
722}
723
724static void put_vara(
725 int ncid, char const * grid_name, char const * var_ext,
726 size_t * start, size_t * count, void const * buffer) {
727
728 if (count[0] == 0) return;
729
730 char * var_name =
731 xmalloc((strlen(grid_name) + strlen(var_ext) + 2) * sizeof(*var_name));
732
733 sprintf(var_name, "%s.%s", grid_name, var_ext);
734
735 int var_id;
736
737 yac_nc_inq_varid(ncid, var_name, &var_id);
738
739 free(var_name);
740
742 nc_put_vara(ncid, var_id, start, count, buffer));
743}
744
745#endif // YAC_NETCDF_ENABLED
746
748 struct yac_basic_grid * grid, char const * filename, MPI_Comm comm) {
749
750#ifndef YAC_NETCDF_ENABLED
751
752 UNUSED(grid);
753 UNUSED(filename);
754 UNUSED(comm);
755
756 die(
757 "ERROR(yac_basic_grid_to_file_parallel): "
758 "YAC is built without the NetCDF support");
759#else
760
761 int comm_rank, comm_size;
762 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
763 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
764
765 { // consistency check
766 int filename_len = (int)strlen(filename) + 1;
767 yac_mpi_call(MPI_Bcast(&filename_len, 1, MPI_INT, 0, comm), comm);
768 char * filename_buffer =
769 xmalloc((size_t)filename_len * sizeof(*filename_buffer));
770 if (comm_rank == 0) strcpy(filename_buffer, filename);
772 MPI_Bcast(filename_buffer, filename_len, MPI_CHAR, 0, comm), comm);
773
775 !strcmp(filename, filename_buffer),
776 "inconsistent filename (\"%s\" on rank 0 != \"%s\" on rank %d)",
777 filename_buffer, filename, comm_rank);
778 free(filename_buffer);
779 }
780
781 struct yac_field_data * cell_field =
783 yac_const_coordinate_pointer cell_center_coords =
784 ((cell_field != NULL) &&
785 (yac_field_data_get_coordinates_count(cell_field) > 0))?
786 yac_field_data_get_coordinates_data(cell_field, 0):NULL;
788
789 uint64_t local_cell_count = (uint64_t)grid->data.num_cells;
790 uint64_t * global_cell_counts =
791 xmalloc((size_t)comm_size * sizeof(*global_cell_counts));
792 int max_num_vertices_per_cell = 0;
793 int cell_center_coords_avaiable =
794 (grid_data->num_cells == 0) || (cell_center_coords != NULL);
795 int cell_global_ids_available =
796 (grid_data->num_cells == 0) || (grid_data->cell_ids != NULL);
797 int core_cell_mask_available =
798 (grid_data->num_cells == 0) || (grid_data->core_cell_mask != NULL);
799 int vertex_global_ids_available =
800 (grid_data->num_vertices == 0) || (grid_data->vertex_ids != NULL);
801 int core_vertex_mask_available =
802 (grid_data->num_vertices == 0) || (grid_data->core_vertex_mask != NULL);
803 int edge_global_ids_available =
804 (grid_data->num_edges == 0) || (grid_data->edge_ids != NULL);
805 int core_edge_mask_available =
806 (grid_data->num_edges == 0) || (grid_data->core_edge_mask != NULL);
807
808 for (size_t i = 0; i < grid->data.num_cells; ++i)
809 if (grid->data.num_vertices_per_cell[i] > max_num_vertices_per_cell)
810 max_num_vertices_per_cell = grid->data.num_vertices_per_cell[i];
811
813 MPI_Allgather(
814 &local_cell_count, 1, MPI_UINT64_T,
815 global_cell_counts, 1, MPI_UINT64_T, comm), comm);
817 MPI_Allreduce(
818 MPI_IN_PLACE, &max_num_vertices_per_cell, 1, MPI_INT, MPI_MAX, comm),
819 comm);
820 int ints[7] = {cell_center_coords_avaiable,
821 cell_global_ids_available,
822 core_cell_mask_available,
823 vertex_global_ids_available,
824 core_vertex_mask_available,
825 edge_global_ids_available,
826 core_edge_mask_available};
828 MPI_Allreduce(
829 MPI_IN_PLACE, ints, sizeof(ints)/sizeof(ints[0]),
830 MPI_INT, MPI_MIN, comm), comm);
831 cell_center_coords_avaiable = ints[0];
832 cell_global_ids_available = ints[1];
833 core_cell_mask_available = ints[2];
834 vertex_global_ids_available = ints[3];
835 core_vertex_mask_available = ints[4];
836 edge_global_ids_available = ints[5];
837 core_edge_mask_available = ints[6];
838
839 size_t global_cell_count = 0;
840 for (int i = 0; i < comm_size; ++i)
841 global_cell_count += (size_t)(global_cell_counts[i]);
842
843 YAC_ASSERT_F(global_cell_count > 0, "grid \"%s\" has no cells", grid->name);
844
845 // create the grid file
846 if (comm_rank == 0)
848 filename, grid->name, global_cell_count, max_num_vertices_per_cell,
849 cell_center_coords_avaiable,
850 cell_global_ids_available, core_cell_mask_available,
851 vertex_global_ids_available, core_vertex_mask_available,
852 edge_global_ids_available, core_edge_mask_available);
853 yac_mpi_call(MPI_Barrier(comm), comm);
854
855 // determine processes that will do output
856 int io_flag;
857 int * io_ranks;
858 int num_io_ranks;
859 yac_get_io_ranks(comm, &io_flag, &io_ranks, &num_io_ranks);
860
861 size_t recv_count = 0;
862 size_t io_start_idx = SIZE_MAX;
863
864 if (io_flag) {
865
866 int io_rank_idx;
867 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
868 if (io_ranks[io_rank_idx] == comm_rank) break;
869
870 io_start_idx =
871 (size_t)(
872 ((long long)(io_rank_idx) * (long long)global_cell_count)/
873 (long long)num_io_ranks);
874 recv_count =
875 (size_t)(
876 ((long long)(io_rank_idx + 1) * (long long)global_cell_count)/
877 (long long)num_io_ranks - (long long)io_start_idx);
878 }
879
880 // generate transfer positions
881 struct Xt_com_pos * com_pos_buffer =
882 xmalloc(5 * (size_t)comm_size * sizeof(*com_pos_buffer));
883 struct Xt_com_pos * cell_src_com = com_pos_buffer;
884 struct Xt_com_pos * cell_dst_com = com_pos_buffer + (size_t)comm_size;
885 struct Xt_com_pos * vertex_src_com = com_pos_buffer + 2 * (size_t)comm_size;
886 struct Xt_com_pos * vertex_dst_com = com_pos_buffer + 3 * (size_t)comm_size;
887 struct Xt_com_pos * edge_src_com = com_pos_buffer + 4 * (size_t)comm_size;
888 struct Xt_com_pos * edge_dst_com = vertex_dst_com;
889 int num_src_msg = 0, num_dst_msg = 0;
890 int * transfer_pos_buffer =
891 xmalloc(
892 (size_t)(2 * max_num_vertices_per_cell + 1) *
893 (grid->data.num_cells + recv_count) * sizeof(*transfer_pos_buffer));
894 int * cell_send_pos = transfer_pos_buffer;
895 int * cell_recv_pos = transfer_pos_buffer + grid->data.num_cells;
896 int * vertex_send_pos =
897 transfer_pos_buffer + grid->data.num_cells + recv_count;
898 int * vertex_recv_pos =
899 transfer_pos_buffer + grid->data.num_cells + recv_count +
900 (size_t)max_num_vertices_per_cell * grid->data.num_cells;
901 int * edge_send_pos =
902 transfer_pos_buffer + grid->data.num_cells + recv_count +
903 (size_t)max_num_vertices_per_cell * grid->data.num_cells +
904 (size_t)max_num_vertices_per_cell * recv_count;
905
906 for (size_t i = 0; i < grid->data.num_cells; ++i) {
907
908 size_t * cell_to_vertex =
909 grid->data.cell_to_vertex + grid->data.cell_to_vertex_offsets[i];
910 size_t * cell_to_edge =
911 grid->data.cell_to_edge + grid->data.cell_to_edge_offsets[i];
912 int num_vertices = grid->data.num_vertices_per_cell[i];
913
914 cell_send_pos[i] = (int)i;
915 for (int j = 0; j < num_vertices; ++j)
916 vertex_send_pos[i * (size_t)max_num_vertices_per_cell + (size_t)j] =
918 for (int j = num_vertices; j < max_num_vertices_per_cell; ++j)
919 vertex_send_pos[i * (size_t)max_num_vertices_per_cell + (size_t)j] = 0;
920 for (int j = 0; j < num_vertices; ++j)
921 edge_send_pos[i * (size_t)max_num_vertices_per_cell + (size_t)j] =
922 cell_to_edge[j];
923 for (int j = num_vertices; j < max_num_vertices_per_cell; ++j)
924 edge_send_pos[i * (size_t)max_num_vertices_per_cell + (size_t)j] = 0;
925 }
926
927 for (size_t i = 0, k = 0; i < recv_count; ++i) {
928 cell_recv_pos[i] = (int)i;
929 for (int j = 0; j < max_num_vertices_per_cell; ++j, ++k)
930 vertex_recv_pos[k] = k;
931 }
932
933 size_t io_end_idx = 0;
934 size_t global_count_accu = 0;
935 for (int io_rank_idx = 0, curr_rank = 0; io_rank_idx < num_io_ranks;
936 ++io_rank_idx) {
937
938 int curr_io_rank = io_ranks[io_rank_idx];
939 size_t io_start_idx = io_end_idx;
940 io_end_idx =
941 (size_t)(
942 ((long long)(io_rank_idx + 1) * (long long)global_cell_count)/
943 (long long)num_io_ranks);
944 size_t io_size = io_end_idx - io_start_idx;
945 size_t curr_recv_size = 0;
946
947 while(global_count_accu < io_end_idx) {
948
949 size_t count =
950 MIN(
951 (global_count_accu + global_cell_counts[curr_rank]) -
952 (io_start_idx + curr_recv_size), io_size - curr_recv_size);
953
954 if (curr_rank == comm_rank) {
955 cell_src_com[num_src_msg].transfer_pos = cell_send_pos;
956 cell_src_com[num_src_msg].num_transfer_pos = (int)count;
957 cell_src_com[num_src_msg].rank = curr_io_rank;
958 cell_send_pos += count;
959
960 vertex_src_com[num_src_msg].transfer_pos = vertex_send_pos;
961 vertex_src_com[num_src_msg].num_transfer_pos =
962 (int)count * max_num_vertices_per_cell;
963 vertex_src_com[num_src_msg].rank = curr_io_rank;
964 vertex_send_pos +=
965 count * (size_t)max_num_vertices_per_cell;
966
967 edge_src_com[num_src_msg].transfer_pos = edge_send_pos;
968 edge_src_com[num_src_msg].num_transfer_pos =
969 (int)count * max_num_vertices_per_cell;
970 edge_src_com[num_src_msg].rank = curr_io_rank;
971 edge_send_pos +=
972 count * (size_t)max_num_vertices_per_cell;
973
974 num_src_msg++;
975 }
976
977 if (curr_io_rank == comm_rank) {
978 cell_dst_com[num_dst_msg].transfer_pos = cell_recv_pos;
979 cell_dst_com[num_dst_msg].num_transfer_pos = (int)count;
980 cell_dst_com[num_dst_msg].rank = curr_rank;
981 cell_recv_pos += count;
982
983 vertex_dst_com[num_dst_msg].transfer_pos = vertex_recv_pos;
984 vertex_dst_com[num_dst_msg].num_transfer_pos =
985 (int)count * max_num_vertices_per_cell;
986 vertex_dst_com[num_dst_msg].rank = curr_rank;
987 vertex_recv_pos += count * (size_t)max_num_vertices_per_cell;
988
989 num_dst_msg++;
990 }
991
992 if ((global_count_accu + global_cell_counts[curr_rank]) <=
993 io_end_idx) {
994 global_count_accu += global_cell_counts[curr_rank];
995 curr_rank++;
996 }
997
998 curr_recv_size += count;
999
1000 if (curr_recv_size >= io_size) break;
1001 }
1002 }
1003
1004 free(global_cell_counts);
1005
1006 // open grid file
1007 int ncid;
1008 size_t start[2], count[2];
1009 if (io_flag) {
1010
1011 int io_rank_idx;
1012 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
1013 if (io_ranks[io_rank_idx] == comm_rank) break;
1014
1015 start[0] = io_start_idx;
1016 start[1] = 0;
1017 count[0] = recv_count;
1018 count[1] = max_num_vertices_per_cell;
1019
1020 yac_nc_open(filename, NC_WRITE | NC_SHARE, &ncid);
1021 } else {
1022 count[0] = 0;
1023 count[1] = 0;
1024 }
1025
1026 void * recv_buffer =
1027 xmalloc(
1028 (size_t)max_num_vertices_per_cell * recv_count *
1029 MAX(MAX(sizeof(double), sizeof(int)), sizeof(yac_int)));
1030
1031 //----------------------------------------------------------------------------
1032 // redistribute cell based data
1033 //----------------------------------------------------------------------------
1034
1035 Xt_xmap cell_xmap =
1036 xt_xmap_intersection_pos_new(
1037 num_src_msg, cell_src_com, num_dst_msg, cell_dst_com, comm);
1038
1039 Xt_redist cell_redist_int = xt_redist_p2p_new(cell_xmap, MPI_INT);
1040
1041 // number of vertices per cell
1042 int * num_vertices_per_cell =
1043 xmalloc(recv_count * sizeof(*num_vertices_per_cell));
1044 xt_redist_s_exchange1(
1045 cell_redist_int, grid->data.num_vertices_per_cell, num_vertices_per_cell);
1046
1047 // cell center coordinates (if available)
1048 if (cell_center_coords_avaiable) {
1049
1050 // generate cell center lon/lat data
1051 double * send_buffer_dble =
1052 xmalloc(2 * grid->data.num_cells * sizeof(*send_buffer_dble));;
1053 double * send_buffer_lon = send_buffer_dble;
1054 double * send_buffer_lat = send_buffer_dble + grid->data.num_cells;
1055 for (size_t i = 0; i < grid->data.num_cells; ++i) {
1056 XYZtoLL(
1057 cell_center_coords[i], send_buffer_lon + i, send_buffer_lat + i);
1058 send_buffer_lon[i] /= YAC_RAD;
1059 send_buffer_lat[i] /= YAC_RAD;
1060 }
1061
1062 // exchange cell center lon/lat data and write it to file
1063 Xt_redist cell_redist_dble = xt_redist_p2p_new(cell_xmap, MPI_DOUBLE);
1064 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lon, recv_buffer);
1065 put_vara(ncid, grid->name, "lon", start, count, recv_buffer);
1066 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lat, recv_buffer);
1067 put_vara(ncid, grid->name, "lat", start, count, recv_buffer);
1068 xt_redist_delete(cell_redist_dble);
1069 free(send_buffer_dble);
1070 }
1071
1072 int * cell_send_buffer_int =
1073 xmalloc(grid->data.num_cells * sizeof(*cell_send_buffer_int));
1074
1075 // cell ranks
1076 {
1077 // generate cell owner rank data
1078 for (size_t i = 0; i < grid->data.num_cells; ++i)
1079 cell_send_buffer_int[i] = comm_rank;
1080
1081 // exchange cell owner ranks and write it to file
1082 xt_redist_s_exchange1(cell_redist_int, cell_send_buffer_int, recv_buffer);
1083 put_vara(ncid, grid->name, "rnk", start, count, recv_buffer);
1084 }
1085
1086 // cell core mask (if available)
1087 if (core_cell_mask_available) {
1088
1089 // exchange core cell mask and write to file
1090 xt_redist_s_exchange1(
1091 cell_redist_int, grid->data.core_cell_mask, recv_buffer);
1092 put_vara(ncid, grid->name, "cmk", start, count, recv_buffer);
1093 }
1094
1095 // cell global ids (if available)
1096 if (cell_global_ids_available) {
1097
1098 // convert global ids to int
1099 for (size_t i = 0; i < grid->data.num_cells; ++i)
1100 cell_send_buffer_int[i] = (int)(grid->data.cell_ids[i]);
1101
1102 // exchange cell global ids and write to file
1103 xt_redist_s_exchange1(
1104 cell_redist_int, cell_send_buffer_int, recv_buffer);
1105 put_vara(ncid, grid->name, "gid", start, count, recv_buffer);
1106 }
1107
1108 xt_redist_delete(cell_redist_int);
1109 free(cell_send_buffer_int);
1110
1111 xt_xmap_delete(cell_xmap);
1112
1113 //----------------------------------------------------------------------------
1114 // redistribute vertex based data
1115 //----------------------------------------------------------------------------
1116
1117 Xt_xmap vertex_xmap =
1118 xt_xmap_intersection_pos_new(
1119 num_src_msg, vertex_src_com, num_dst_msg, vertex_dst_com, comm);
1120
1121 // vertex coordinates
1122 {
1123 // generate vertex lon/lat data
1124 double * send_buffer_dble =
1125 xmalloc(2 * grid->data.num_vertices * sizeof(*send_buffer_dble));
1126 double * send_buffer_lon = send_buffer_dble;
1127 double * send_buffer_lat = send_buffer_dble + grid->data.num_vertices;
1128 for (size_t i = 0; i < grid->data.num_vertices; ++i) {
1129 XYZtoLL(
1130 grid->data.vertex_coordinates[i],
1131 send_buffer_lon + i, send_buffer_lat + i);
1132 send_buffer_lon[i] /= YAC_RAD;
1133 send_buffer_lat[i] /= YAC_RAD;
1134 }
1135
1136 // exchange vertex lon/lat data and write it to file
1137 Xt_redist vertex_redist_dble = xt_redist_p2p_new(vertex_xmap, MPI_DOUBLE);
1138 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lon, recv_buffer);
1139 for (size_t i = 0, k = 0; i < recv_count;
1140 ++i, k += (size_t)max_num_vertices_per_cell)
1141 for (size_t j = (size_t)num_vertices_per_cell[i];
1142 j < (size_t)max_num_vertices_per_cell; ++j)
1143 ((double*)recv_buffer)[k+j] = DBL_MAX;
1144 put_vara(ncid, grid->name, "clo", start, count, recv_buffer);
1145 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lat, recv_buffer);
1146 free(send_buffer_dble);
1147 for (size_t i = 0, k = 0; i < recv_count;
1148 ++i, k += (size_t)max_num_vertices_per_cell)
1149 for (size_t j = (size_t)num_vertices_per_cell[i];
1150 j < (size_t)max_num_vertices_per_cell; ++j)
1151 ((double*)recv_buffer)[k+j] = DBL_MAX;
1152 put_vara(ncid, grid->name, "cla", start, count, recv_buffer);
1153 xt_redist_delete(vertex_redist_dble);
1154 }
1155
1156 Xt_redist vertex_redist_int = xt_redist_p2p_new(vertex_xmap, MPI_INT);
1157 int * vertex_send_buffer_int =
1158 xmalloc(grid->data.num_vertices * sizeof(*vertex_send_buffer_int));
1159
1160 // core vertex mask (if available)
1161 if (core_vertex_mask_available) {
1162
1163 // exchange core vertex mask and write to file
1164 xt_redist_s_exchange1(
1165 vertex_redist_int, grid->data.core_vertex_mask, recv_buffer);
1166 for (size_t i = 0, k = 0; i < recv_count;
1167 ++i, k += (size_t)max_num_vertices_per_cell)
1168 for (size_t j = (size_t)num_vertices_per_cell[i];
1169 j < (size_t)max_num_vertices_per_cell; ++j)
1170 ((int*)recv_buffer)[k+j] = INT_MAX;
1171 put_vara(ncid, grid->name, "vcmk", start, count, recv_buffer);
1172 }
1173
1174 // vertex global ids (if available)
1175 if (vertex_global_ids_available) {
1176
1177 // convert global ids to int
1178 for (size_t i = 0; i < grid->data.num_vertices; ++i)
1179 vertex_send_buffer_int[i] = (int)(grid->data.vertex_ids[i]);
1180
1181 // exchange vertex global ids and write to file
1182 xt_redist_s_exchange1(
1183 vertex_redist_int, vertex_send_buffer_int, recv_buffer);
1184 for (size_t i = 0, k = 0; i < recv_count;
1185 ++i, k += (size_t)max_num_vertices_per_cell)
1186 for (size_t j = (size_t)num_vertices_per_cell[i];
1187 j < (size_t)max_num_vertices_per_cell; ++j)
1188 ((int*)recv_buffer)[k+j] = INT_MAX;
1189 put_vara(ncid, grid->name, "vgid", start, count, recv_buffer);
1190 }
1191
1192 free(vertex_send_buffer_int);
1193 xt_redist_delete(vertex_redist_int);
1194
1195 xt_xmap_delete(vertex_xmap);
1196
1197 //----------------------------------------------------------------------------
1198 // redistribute edge based data
1199 //----------------------------------------------------------------------------
1200
1201 if (core_edge_mask_available || edge_global_ids_available) {
1202
1203 Xt_xmap edge_xmap =
1204 xt_xmap_intersection_pos_new(
1205 num_src_msg, edge_src_com, num_dst_msg, edge_dst_com, comm);
1206
1207 Xt_redist edge_redist_int = xt_redist_p2p_new(edge_xmap, MPI_INT);
1208 int * edge_send_buffer_int =
1209 xmalloc(grid->data.num_edges * sizeof(*edge_send_buffer_int));
1210
1211 // core edge mask (if available)
1212 if (core_edge_mask_available) {
1213
1214 // exchange core edge mask and write to file
1215 xt_redist_s_exchange1(
1216 edge_redist_int, grid->data.core_edge_mask, recv_buffer);
1217 for (size_t i = 0, k = 0; i < recv_count;
1218 ++i, k += (size_t)max_num_vertices_per_cell)
1219 for (size_t j = (size_t)num_vertices_per_cell[i];
1220 j < (size_t)max_num_vertices_per_cell; ++j)
1221 ((int*)recv_buffer)[k+j] = INT_MAX;
1222 put_vara(ncid, grid->name, "ecmk", start, count, recv_buffer);
1223 }
1224
1225 // edge global ids (if available)
1226 if (edge_global_ids_available) {
1227
1228 // convert global ids to int
1229 for (size_t i = 0; i < grid->data.num_edges; ++i)
1230 edge_send_buffer_int[i] = (int)(grid->data.edge_ids[i]);
1231
1232 // exchange edge global ids and write to file
1233 xt_redist_s_exchange1(
1234 edge_redist_int, edge_send_buffer_int, recv_buffer);
1235 for (size_t i = 0, k = 0; i < recv_count;
1236 ++i, k += (size_t)max_num_vertices_per_cell)
1237 for (size_t j = (size_t)num_vertices_per_cell[i];
1238 j < (size_t)max_num_vertices_per_cell; ++j)
1239 ((int*)recv_buffer)[k+j] = INT_MAX;
1240 put_vara(ncid, grid->name, "egid", start, count, recv_buffer);
1241 }
1242
1243 free(edge_send_buffer_int);
1244 xt_redist_delete(edge_redist_int);
1245
1246 xt_xmap_delete(edge_xmap);
1247 }
1248
1249 // close file
1250 if (io_flag) YAC_HANDLE_ERROR(nc_close(ncid));
1251
1252 free(num_vertices_per_cell);
1253 free(recv_buffer);
1254 free(com_pos_buffer);
1255 free(transfer_pos_buffer);
1256 free(io_ranks);
1257
1258 // ensure that the writing of the weight file is complete
1259 yac_mpi_call(MPI_Barrier(comm), comm);
1260
1261#endif // YAC_NETCDF_ENABLED
1262}
1263
1265 struct yac_basic_grid * grid, double * cell_areas) {
1266
1268 grid->data, cell_areas);
1269}
1270
1271/* ---------------------------------------------------------------------- */
1272
1278 const char * grid_name, enum yac_location location,
1279 double const * coord, int is_fatal) {
1280
1281 double lon_rad, lat_rad;
1282 XYZtoLL(coord, &lon_rad, &lat_rad);
1283
1284 char msg[512];
1285 snprintf(
1286 msg, sizeof(msg),
1287 "%s(yac_check_point_coordinates): "
1288 "coordinate mismatch: grid '%s', location %s, "
1289 "coordinates (%.10g, %.10g) deg\n",
1290 is_fatal?"ERROR":"WARNING", grid_name, yac_loc2str(location),
1291 lon_rad / YAC_RAD, lat_rad / YAC_RAD);
1292
1293 YAC_ASSERT(!is_fatal, msg);
1294
1295 /* non-fatal: print warning and continue */
1296 fputs(msg, stderr);
1297}
1298
1299/* ---------------------------------------------------------------------- */
1300
1301static void get_grid_cell(
1302 struct yac_basic_grid_data const * grid_data, size_t cell_idx,
1303 struct yac_grid_cell * buffer_cell) {
1304
1305 size_t num_vertices = (size_t)(grid_data->num_vertices_per_cell[cell_idx]);
1306
1307 struct yac_grid_cell cell = *buffer_cell;
1308
1309 if (cell.array_size < num_vertices) {
1310 cell.coordinates_xyz =
1311 xrealloc(cell.coordinates_xyz, num_vertices *
1312 sizeof(*(cell.coordinates_xyz)));
1313 cell.edge_type = xrealloc(cell.edge_type, num_vertices *
1314 sizeof(*(cell.edge_type)));
1315 cell.array_size = num_vertices;
1316 *buffer_cell = cell;
1317 }
1318
1319 for (size_t i = 0; i < num_vertices; ++i) {
1320 size_t vertex_idx =
1322 grid_data->cell_to_vertex_offsets[cell_idx] + i];
1323 cell.coordinates_xyz[i][0] = grid_data->vertex_coordinates[vertex_idx][0];
1324 cell.coordinates_xyz[i][1] = grid_data->vertex_coordinates[vertex_idx][1];
1325 cell.coordinates_xyz[i][2] = grid_data->vertex_coordinates[vertex_idx][2];
1326 size_t edge_idx =
1327 grid_data->cell_to_edge[grid_data->cell_to_edge_offsets[cell_idx] + i];
1328 cell.edge_type[i] = grid_data->edge_type[edge_idx];
1329 }
1330 buffer_cell->num_corners = num_vertices;
1331}
1332
1342 struct yac_basic_grid * grid, int is_fatal) {
1343
1344 struct yac_basic_grid_data const *grid_data = &grid->data;
1345 const char *grid_name = grid->name;
1346
1347 size_t const num_cells = grid_data->num_cells;
1348 if (num_cells == 0) return 1;
1349
1350 /* reusable grid cell scratch space */
1351 struct yac_grid_cell cell;
1352 yac_init_grid_cell(&cell);
1353
1354 int found_mismatch = 0;
1355
1356 for (size_t cell_idx = 0; (cell_idx < num_cells) && !found_mismatch;
1357 ++cell_idx) {
1358
1359 /* skip cells flagged as non-core */
1360 if (grid_data->core_cell_mask &&
1361 !grid_data->core_cell_mask[cell_idx]) continue;
1362
1363 get_grid_cell(grid_data, cell_idx, &cell);
1364
1365 struct bounding_circle bc;
1367
1369 (double *)coords[cell_idx], &bc)) {
1370
1372 grid_name, YAC_LOC_CELL, coords[cell_idx], is_fatal);
1373 found_mismatch = 1;
1374 }
1375 }
1376
1377 yac_free_grid_cell(&cell);
1378 return found_mismatch;
1379}
1380
1381/* ---------------------------------------------------------------------- */
1382
1390 struct yac_basic_grid * grid, int is_fatal) {
1391
1392 struct yac_basic_grid_data const *grid_data = &grid->data;
1393 const char *grid_name = grid->name;
1394
1395 size_t const num_vertices = grid_data->num_vertices;
1396 if (num_vertices == 0) return 1;
1397
1398 int found_mismatch = 0;
1399
1400 for (size_t vertex_idx = 0; (vertex_idx < num_vertices) && !found_mismatch;
1401 ++vertex_idx) {
1402
1403 if (grid_data->core_vertex_mask &&
1404 !grid_data->core_vertex_mask[vertex_idx]) continue;
1405
1406 // check if points are identical
1408 coords[vertex_idx], grid_data->vertex_coordinates[vertex_idx])) {
1409
1411 grid_name, YAC_LOC_CORNER, coords[vertex_idx], is_fatal);
1412 found_mismatch = 1;
1413 }
1414 }
1415 return found_mismatch;
1416}
1417
1418/* ---------------------------------------------------------------------- */
1419
1428 struct yac_basic_grid * grid, int is_fatal) {
1429
1430 struct yac_basic_grid_data const *grid_data = &grid->data;
1431 const char *grid_name = grid->name;
1432
1433 size_t const num_edges = grid_data->num_edges;
1434 if (num_edges == 0) return 1;
1435
1436 int found_mismatch = 0;
1437
1438 for (size_t edge_idx = 0; (edge_idx < num_edges) && !found_mismatch;
1439 ++edge_idx) {
1440
1441 if (grid_data->core_edge_mask &&
1442 !grid_data->core_edge_mask[edge_idx]) continue;
1443
1444 size_t v0 = grid_data->edge_to_vertex[edge_idx][0];
1445 size_t v1 = grid_data->edge_to_vertex[edge_idx][1];
1446 double const * a = grid_data->vertex_coordinates[v0];
1447 double const * b = grid_data->vertex_coordinates[v1];
1448
1449 if (points_are_identically(a, b)) {
1450 /* degenerate edge: skip */
1451 continue;
1452 }
1453
1454 /* normalised midpoint */
1455 double m[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
1457
1458 /* angular radius = angle(m, a) + SIN_COS_TOL */
1459 struct sin_cos_angle inc = get_vector_angle_2(m, a);
1460 struct sin_cos_angle inc_tol = sum_angles_no_check(inc, SIN_COS_TOL);
1461
1462 struct bounding_circle bnd_circle;
1463 bnd_circle.base_vector[0] = m[0];
1464 bnd_circle.base_vector[1] = m[1];
1465 bnd_circle.base_vector[2] = m[2];
1466 bnd_circle.inc_angle = inc_tol;
1467 bnd_circle.sq_crd = DBL_MAX;
1468
1470 (double *)coords[edge_idx], &bnd_circle)) {
1471
1473 grid_name, YAC_LOC_EDGE, coords[edge_idx], is_fatal);
1474 found_mismatch = 1;
1475 }
1476 }
1477 return found_mismatch;
1478}
1479
1481
1482 int found_mismatch = 0;
1483
1484 // check cell center coordinates
1485 struct yac_field_data * cell_field =
1487 size_t num_cell_coords =
1488 cell_field?yac_field_data_get_coordinates_count(cell_field):0;
1489
1490 for (size_t i = 0; (i < num_cell_coords) && !found_mismatch; ++i) {
1491 yac_const_coordinate_pointer cell_center_coords =
1493 found_mismatch = check_cell_coords(cell_center_coords, grid, fatal);
1494 }
1495
1496 // check vertex coordinates
1497 struct yac_field_data * vertex_field =
1499 size_t num_vertex_coords =
1500 vertex_field?yac_field_data_get_coordinates_count(vertex_field):0;
1501 for (size_t i = 0; (i < num_vertex_coords) && !found_mismatch; ++i) {
1502 yac_const_coordinate_pointer vertex_coords =
1503 yac_field_data_get_coordinates_data(vertex_field, i);
1504 if (vertex_coords) {
1505 found_mismatch = check_corner_coords(vertex_coords, grid, fatal);
1506 }
1507 }
1508
1509 // check edge coordinates
1510 struct yac_field_data * edge_field =
1512 size_t num_edge_coords =
1513 edge_field?yac_field_data_get_coordinates_count(edge_field):0;
1514 for (size_t i = 0; (i < num_edge_coords) && !found_mismatch; ++i) {
1515 yac_const_coordinate_pointer edge_coords =
1517 found_mismatch = check_edge_coords(edge_coords, grid, fatal);
1518 }
1519 return found_mismatch;
1520}
#define YAC_ASSERT(exp, msg)
static int check_cell_coords(yac_const_coordinate_pointer coords, struct yac_basic_grid *grid, int is_fatal)
struct yac_basic_grid * yac_basic_grid_unstruct_edge_new(char const *name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
Definition basic_grid.c:396
struct yac_basic_grid * yac_basic_grid_unstruct_edge_ll_new(char const *name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
Definition basic_grid.c:422
static struct yac_basic_grid_data yac_basic_grid_data_empty
Definition basic_grid.c:31
struct yac_field_data * yac_basic_grid_get_field_data(struct yac_basic_grid *grid, enum yac_location location)
Definition basic_grid.c:287
size_t yac_basic_grid_get_named_mask_idx(struct yac_basic_grid *grid, enum yac_location location, char const *mask_name)
Definition basic_grid.c:172
int const * yac_basic_grid_get_field_mask(struct yac_basic_grid *grid, struct yac_interp_field field)
Definition basic_grid.c:120
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
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
static void create_grid_file(char const *filename, char const *grid_name, size_t num_cells, int num_vertices_per_cell, int cell_center_coords_avaiable, int cell_global_ids_available, int core_cell_mask_available, int vertex_global_ids_available, int core_vertex_mask_available, int edge_global_ids_available, int core_edge_mask_available)
Definition basic_grid.c:598
static int check_edge_coords(yac_const_coordinate_pointer coords, struct yac_basic_grid *grid, int is_fatal)
struct yac_basic_grid * yac_basic_grid_cloud_new(char const *name, size_t nbr_points, double *x_points, double *y_points)
Definition basic_grid.c:448
struct yac_basic_grid * yac_basic_grid_unstruct_deg_new(char const *name, size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
Definition basic_grid.c:357
struct yac_basic_grid * yac_basic_grid_unstruct_new(char const *name, size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
Definition basic_grid.c:344
yac_const_coordinate_pointer yac_basic_grid_get_field_coordinates(struct yac_basic_grid *grid, struct yac_interp_field field)
Definition basic_grid.c:86
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:137
static void def_var(char const *filename, int ncid, char const *name, nc_type type, int ndims, const int *dimids, char const *att_name, char const *att_value, int file_is_new)
Definition basic_grid.c:528
struct yac_basic_grid * yac_basic_grid_cloud_deg_new(char const *name, size_t nbr_points, double *x_points, double *y_points)
Definition basic_grid.c:457
struct yac_basic_grid * yac_basic_grid_unstruct_edge_deg_new(char const *name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
Definition basic_grid.c:409
size_t yac_basic_grid_add_mask(struct yac_basic_grid *grid, enum yac_location location, int const *mask, size_t count, char const *mask_name)
Definition basic_grid.c:266
struct yac_basic_grid * yac_basic_grid_reg_2d_new(char const *name, size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition basic_grid.c:300
static void report_mismatch(const char *grid_name, enum yac_location location, double const *coord, int is_fatal)
struct yac_basic_grid * yac_basic_grid_unstruct_ll_new(char const *name, size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
Definition basic_grid.c:370
size_t yac_basic_grid_get_data_size_f2c(struct yac_basic_grid *grid, int location)
Definition basic_grid.c:165
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
void yac_basic_grid_compute_cell_areas(struct yac_basic_grid *grid, double *cell_areas)
size_t yac_basic_grid_add_mask_nocpy_f2c(struct yac_basic_grid *grid, int location, int const *mask, char const *mask_name)
Definition basic_grid.c:257
size_t yac_basic_grid_add_coordinates_f2c(struct yac_basic_grid *grid, int location, double *coordinates, size_t count)
Definition basic_grid.c:234
struct yac_basic_grid * yac_basic_grid_reg_2d_rot_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:466
static int check_corner_coords(yac_const_coordinate_pointer coords, struct yac_basic_grid *grid, int is_fatal)
size_t yac_basic_grid_add_coordinates(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
Definition basic_grid.c:222
int yac_basic_grid_check_coordinates(struct yac_basic_grid *grid, int fatal)
size_t yac_basic_grid_get_data_size(struct yac_basic_grid *grid, enum yac_location location)
Definition basic_grid.c:145
struct yac_basic_grid * yac_basic_grid_unstruct_ll_deg_new(char const *name, size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
Definition basic_grid.c:383
static void put_vara(int ncid, char const *grid_name, char const *var_ext, size_t *start, size_t *count, void const *buffer)
Definition basic_grid.c:724
int const * yac_basic_grid_get_core_mask(struct yac_basic_grid *grid, enum yac_location location)
Definition basic_grid.c:104
size_t yac_basic_grid_add_coordinates_nocpy_f2c(struct yac_basic_grid *grid, int location, double *coordinates)
Definition basic_grid.c:214
static int def_dim(char const *filename, int ncid, char const *name, size_t dim_len, int file_is_new)
Definition basic_grid.c:494
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
size_t yac_basic_grid_add_mask_f2c(struct yac_basic_grid *grid, int location, int const *mask, size_t count, char const *mask_name)
Definition basic_grid.c:278
struct yac_basic_grid * yac_basic_grid_curve_2d_new(char const *name, size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition basic_grid.c:322
static void get_grid_cell(struct yac_basic_grid_data const *grid_data, size_t cell_idx, struct yac_grid_cell *buffer_cell)
struct yac_basic_grid * yac_basic_grid_curve_2d_deg_new(char const *name, size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition basic_grid.c:333
struct yac_basic_grid * yac_basic_grid_unstruct_edge_ll_deg_new(char const *name, size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
Definition basic_grid.c:435
size_t yac_basic_grid_add_mask_nocpy(struct yac_basic_grid *grid, enum yac_location location, int const *mask, char const *mask_name)
Definition basic_grid.c:244
void yac_basic_grid_data_compute_cell_areas(struct yac_basic_grid_data grid, double *cell_areas)
void yac_basic_grid_data_free(struct yac_basic_grid_data grid)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition grid_reg2d.c:62
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_ll(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_cloud(size_t nbr_points, double *x_points, double *y_points)
Definition grid_cloud.c:50
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_deg(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d_rot_deg(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_generate_basic_grid_data_reg_2d_rot(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_generate_basic_grid_data_unstruct_edge_ll(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_ll_deg(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_cloud_deg(size_t nbr_points, double *x_points, double *y_points)
Definition grid_cloud.c:58
struct yac_basic_grid_data yac_generate_basic_grid_data_curve_2d_deg(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
struct yac_basic_grid_data yac_generate_basic_grid_data_curve_2d(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d_deg(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition grid_reg2d.c:71
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_ll_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
void yac_get_cell_bounding_circle(struct yac_grid_cell cell, struct bounding_circle *bnd_circle)
Definition bnd_circle.c:422
#define UNUSED(x)
Definition core.h:72
static char * yac_core_version
Definition core_version.c:8
#define YAC_RAD
size_t yac_field_data_get_masks_count(struct yac_field_data *field_data)
Definition field_data.c:57
size_t yac_field_data_get_coordinates_count(struct yac_field_data *field_data)
Definition field_data.c:86
yac_const_coordinate_pointer yac_field_data_get_coordinates_data(struct yac_field_data *field_data, size_t coordinates_idx)
Definition field_data.c:91
int const * yac_field_data_get_mask_data(struct yac_field_data *field_data, size_t mask_idx)
Definition field_data.c:62
char const * yac_field_data_get_mask_name(struct yac_field_data *field_data, size_t mask_idx)
Definition field_data.c:78
void yac_field_data_set_delete(struct yac_field_data_set *field_data_set)
size_t yac_field_data_set_add_mask_nocpy(struct yac_field_data_set *field_data_set, enum yac_location location, int const *mask, char const *mask_name)
struct yac_field_data * yac_field_data_set_get_field_data(struct yac_field_data_set *field_data_set, enum yac_location location)
size_t yac_field_data_set_add_mask(struct yac_field_data_set *field_data_set, enum yac_location location, int const *mask, size_t count, char const *mask_name)
struct yac_field_data_set * yac_field_data_set_empty_new()
size_t yac_field_data_set_add_coordinates(struct yac_field_data_set *field_data_set, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
size_t yac_field_data_set_add_coordinates_nocpy(struct yac_field_data_set *field_data_set, enum yac_location location, yac_coordinate_pointer coordinates)
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
Definition geometry.h:484
static int points_are_identically(double const *a, double const *b)
Definition geometry.h:717
static int yac_point_in_bounding_circle_vec(double point_vector[3], struct bounding_circle *bnd_circle)
Definition geometry.h:197
static struct sin_cos_angle sum_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:593
static const struct sin_cos_angle SIN_COS_TOL
Definition geometry.h:37
static void normalise_vector(double v[])
Definition geometry.h:743
void yac_init_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:14
void yac_free_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:44
enum callback_type type
struct Xt_redist_ * Xt_redist
void yac_get_io_ranks(MPI_Comm comm, int *local_is_io_, int **io_ranks_, int *num_io_ranks_)
Definition io_utils.c:271
void yac_nc_create(const char *path, int cmode, int *ncidp)
Definition io_utils.c:326
void yac_nc_inq_varid(int ncid, char const *name, int *varidp)
Definition io_utils.c:369
int yac_file_exists(const char *filename)
Check whether a file exists.
Definition io_utils.c:394
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:311
char const * yac_loc2str(enum yac_location location)
Definition location.c:33
enum yac_location yac_get_location(int const location)
Definition location.c:45
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define xstrdup(s)
Definition ppm_xfuncs.h:84
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:64
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:53
double base_vector[3]
Definition geometry.h:51
double sq_crd
Definition geometry.h:56
yac_coordinate_pointer vertex_coordinates
struct yac_basic_grid_data data
Definition basic_grid.c:28
struct yac_field_data_set * field_data_set
Definition basic_grid.c:27
size_t masks_count
Definition field_data.c:15
yac_coordinate_pointer * coordinates
Definition field_data.c:16
size_t num_corners
Definition grid_cell.h:21
enum yac_edge_type * edge_type
Definition grid_cell.h:20
size_t array_size
Definition grid_cell.h:22
double(* coordinates_xyz)[3]
Definition grid_cell.h:19
int * cell_to_vertex
double * data
size_t num_cells[2]
unsigned cyclic[2]
static int mask[16]
#define MIN(a, b)
Definition toy_common.h:29
static void XYZtoLL(double const p_in[], double *lon, double *lat)
Definition toy_common.h:23
double * buffer
double * recv_buffer
int const * location
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
char const * name
Definition toy_scrip.c:114
#define MAX(a, b)
static char * yac_version
Definition version.h:7
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define die(msg)
Definition yac_assert.h:14
#define yac_mpi_call(call, comm)
double const (* yac_const_coordinate_pointer)[3]
Definition yac_types.h:22
YAC_INT yac_int
Definition yac_types.h:15
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21