YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
read_scrip_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#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <stdlib.h>
10#include <stdio.h>
11#include <stdint.h>
12#include <string.h>
13#include <limits.h>
14
15#include <mpi.h>
16
17#include "read_scrip_grid.h"
18#include "geometry.h"
19#include "utils_common.h"
20#include "io_utils.h"
21#include "yac_mpi_internal.h"
22
23#ifdef YAC_NETCDF_ENABLED
24
25#include <netcdf.h>
26
27struct point_with_index {
28
29 int32_t lon, lat;
30 int rank;
32 size_t i;
33 double dlon, dlat;
34};
35
41
48
50 double ** vertex_lon, double ** vertex_lat,
51 size_t * nbr_vertices, int * old_to_new_id);
53 double ** vertex_lon, double ** vertex_lat,
54 size_t * nbr_vertices, int * old_to_new_id,
55 yac_int ** vertex_ids, MPI_Comm comm);
56static void detect_duplicated_cells(
57 int * cell_to_vertex, int * num_vertices_per_cell, int * cell_mask,
58 size_t nbr_cells, size_t ** duplicated_cell_idx,
59 size_t ** orig_cell_idx, size_t * nbr_duplicated_cells);
61 int * cell_to_vertex, int * num_vertices_per_cell, int * cell_mask,
62 yac_int * cell_ids, size_t num_cells, yac_int * vertex_ids,
63 MPI_Comm comm, size_t ** duplicated_cell_idx,
64 yac_int ** orig_cell_ids, size_t * num_duplicated_cells_);
65
66static inline int compare_int(
67 const void * a,const void * b) {
68 return *(int const *)a - *(int const*)b;
69}
70
71static inline int compare_yac_int(
72 const void * a, const void * b) {
73 return (*(yac_int const *)a > *(yac_int const*)b) -
74 (*(yac_int const *)a < *(yac_int const*)b);
75}
76
78 const void * a_, const void * b_) {
79
80 struct cell_vertex_ids_with_index const * a =
81 (struct cell_vertex_ids_with_index const *)a_;
82 struct cell_vertex_ids_with_index const * b =
83 (struct cell_vertex_ids_with_index const *)b_;
84
85 size_t num_vertices_a = a->num_vertices;
86 size_t num_vertices_b = b->num_vertices;
87 int ret = (num_vertices_a > num_vertices_b) -
88 (num_vertices_a < num_vertices_b);
89
90 for (size_t i = 0; (i < num_vertices_a) && !ret; ++i)
91 ret = (a->vertex_ids[i] > b->vertex_ids[i]) -
92 (a->vertex_ids[i] < b->vertex_ids[i]);
93
94 return ret;
95}
96
98 const void * a_, const void * b_) {
99
101 if (ret) return ret;
102
103 struct cell_vertex_ids_with_index const * a =
104 (struct cell_vertex_ids_with_index const *)a_;
105 struct cell_vertex_ids_with_index const * b =
106 (struct cell_vertex_ids_with_index const *)b_;
107
108 return (a->cell_id > b->cell_id) - (a->cell_id < b->cell_id);
109}
110
112 const void * a_, const void * b_) {
113
114 struct point_with_index * a = (struct point_with_index *)a_;
115 struct point_with_index * b = (struct point_with_index *)b_;
116
117 int ret = (a->lon > b->lon) - (a->lon < b->lon);
118 if (ret) return ret;
119 ret = (a->lat > b->lat) - (a->lat < b->lat);
120 if (ret) return ret;
121 return (a->id > b->id) - (a->id < b->id);
122}
123
125 const void * a_, const void * b_) {
126
127 struct point_with_index * a = (struct point_with_index *)a_;
128 struct point_with_index * b = (struct point_with_index *)b_;
129
130 int ret = (a->lon > b->lon) - (a->lon < b->lon);
131 if (ret) return ret;
132 return (a->lat > b->lat) - (a->lat < b->lat);
133}
134
136 const void * a_, const void * b_) {
137
138 struct point_with_index * a = (struct point_with_index *)a_;
139 struct point_with_index * b = (struct point_with_index *)b_;
140
141 return (a->rank > b->rank) - (a->rank < b->rank);
142}
143
145 const void * a_, const void * b_) {
146
147 struct point_with_index * a = (struct point_with_index *)a_;
148 struct point_with_index * b = (struct point_with_index *)b_;
149
150 return (a->i > b->i) - (a->i < b->i);
151}
152
154 const char * filename, const char * grid_name,
155 size_t cell_mask_size, int * cell_mask,
156 size_t * num_vertices_, size_t * num_cells_, int ** num_vertices_per_cell_,
157 int ** cell_to_vertex_, double ** x_vertices, double ** y_vertices,
158 double ** x_cells, double ** y_cells,
159 size_t ** duplicated_cell_idx_, size_t ** orig_cell_idx_,
160 size_t * nbr_duplicated_cells_, int with_vertices) {
161
162 size_t grid_name_len = strlen(grid_name) + 1;
163 char cla_var_name[4 + grid_name_len];
164 char clo_var_name[4 + grid_name_len];
165 char lat_var_name[4 + grid_name_len];
166 char lon_var_name[4 + grid_name_len];
167
168 snprintf(cla_var_name, 4 + grid_name_len, "%s.cla", grid_name);
169 snprintf(clo_var_name, 4 + grid_name_len, "%s.clo", grid_name);
170 snprintf(lat_var_name, 4 + grid_name_len, "%s.lat", grid_name);
171 snprintf(lon_var_name, 4 + grid_name_len, "%s.lon", grid_name);
172
173 int ncid;
174 yac_nc_open(filename, NC_NOWRITE, &ncid);
175
176 // get variable ids
177 int cla_var_id;
178 int clo_var_id;
179 int lat_var_id;
180 int lon_var_id;
181 if (with_vertices) {
182 yac_nc_inq_varid(ncid, cla_var_name, &cla_var_id);
183 yac_nc_inq_varid(ncid, clo_var_name, &clo_var_id);
184 }
185 yac_nc_inq_varid(ncid, lat_var_name, &lat_var_id);
186 yac_nc_inq_varid(ncid, lon_var_name, &lon_var_id);
187
188 // get dimension ids
189 int dim_ids[NC_MAX_VAR_DIMS];
190 if (with_vertices) {
191 int ndims;
193 nc_inq_var(ncid, cla_var_id, NULL, NULL, &ndims, dim_ids, NULL));
195 ndims == 3,
196 "invalid number of dimensions for variable \"%s\" (has to be 3 not %d)",
197 cla_var_name, ndims);
198 } else {
199 int ndims;
201 nc_inq_var(ncid, lat_var_id, NULL, NULL, &ndims, dim_ids, NULL));
203 ndims == 2,
204 "invalid number of dimensions for variable \"%s\" (has to be 2 not %d)",
205 lat_var_name, ndims);
206 dim_ids[2] = dim_ids[1];
207 dim_ids[1] = dim_ids[0];
208 dim_ids[0] = -1;
209 }
210 int crn_dim_id = dim_ids[0];
211 int x_dim_id = dim_ids[2];
212 int y_dim_id = dim_ids[1];
213
214 // get dimension length
215 size_t crn_dim_len, x_dim_len, y_dim_len;
216 if (with_vertices)
217 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, crn_dim_id, &crn_dim_len));
218 else
219 crn_dim_len = 1;
220 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, x_dim_id, &x_dim_len));
221 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, y_dim_id, &y_dim_len));
222
223 size_t num_cells = x_dim_len * y_dim_len;
224 size_t num_vertices = num_cells * crn_dim_len;
225
227 num_cells == cell_mask_size,
228 "cell mask size is inconsistent with number of grid cells")
229
230 if ((x_cells != NULL) && (y_cells != NULL)) {
231 double * lat = xmalloc(num_cells * sizeof(*lat));
232 double * lon = xmalloc(num_cells * sizeof(*lon));
233 YAC_HANDLE_ERROR(nc_get_var_double(ncid, lat_var_id, lat));
234 YAC_HANDLE_ERROR(nc_get_var_double(ncid, lon_var_id, lon));
235 *x_cells = lon;
236 *y_cells = lat;
237 }
238
239 // allocate variables
240 double * cla = xmalloc(num_vertices * sizeof(*cla));
241 double * clo = xmalloc(num_vertices * sizeof(*clo));
242
243 //read variables
244 if (with_vertices) {
245
246 YAC_HANDLE_ERROR(nc_get_var_double(ncid, cla_var_id, cla));
247 YAC_HANDLE_ERROR(nc_get_var_double(ncid, clo_var_id, clo));
248
249 } else {
250
252 (x_cells != NULL) && (y_cells != NULL),
253 "no pointers for cell coordinates were provided")
254
255 memcpy(cla, *y_cells, num_cells * sizeof(*cla));
256 memcpy(clo, *x_cells, num_cells * sizeof(*clo));
257 }
258
259 YAC_HANDLE_ERROR(nc_close(ncid));
260
261 size_t * reorder_idx = xmalloc(num_vertices * sizeof(*reorder_idx));
262 for (size_t y = 0, l = 0; y < y_dim_len; ++y)
263 for (size_t x = 0; x < x_dim_len; ++x)
264 for (size_t n = 0; n < crn_dim_len; ++n, ++l)
265 reorder_idx[x + y * x_dim_len + n * x_dim_len * y_dim_len] = l;
266
267 // remove duplicated vertices
268 int * cell_to_vertex = xmalloc(num_vertices * sizeof(*cell_to_vertex));
269 remove_duplicated_vertices(&clo, &cla, &num_vertices, cell_to_vertex);
270
271 // we have to reorder cell_to_vertex
273 reorder_idx, num_cells * crn_dim_len, cell_to_vertex);
274 free(reorder_idx);
275
276 // determine number of vertices per cell and compact cell_to_vertex
277 int * num_vertices_per_cell =
278 xmalloc(num_cells * sizeof(*num_vertices_per_cell));
279 size_t total_num_cell_vertices = 0;
280 int * to_vertices = cell_to_vertex;
281 int * from_vertices = cell_to_vertex;
282 if (crn_dim_len > 1) {
283 for (size_t i = 0; i < num_cells; ++i) {
284 size_t curr_num_vertices = 0;
285 if (cell_mask[i]) {
286 if (crn_dim_len > 1) {
287 int prev_vertex = from_vertices[crn_dim_len-1];
288 for (size_t j = 0; j < crn_dim_len; ++j, ++from_vertices) {
289 int curr_vertex = *from_vertices;
290 if (prev_vertex != curr_vertex) {
291 prev_vertex = curr_vertex;
292 if (to_vertices != from_vertices) *to_vertices = curr_vertex;
293 ++curr_num_vertices;
294 ++to_vertices;
295 }
296 }
297 }
298 } else {
299 from_vertices += crn_dim_len;
300 }
301 num_vertices_per_cell[i] = (int)curr_num_vertices;
302 total_num_cell_vertices += curr_num_vertices;
303 }
304 } else {
305 for (size_t i = 0; i < num_cells; ++i) {
306 if (cell_mask[i]) {
307 if (to_vertices != from_vertices) *to_vertices = *from_vertices;
308 ++to_vertices;
309 ++total_num_cell_vertices;
310 num_vertices_per_cell[i] = 1;
311 } else {
312 num_vertices_per_cell[i] = 0;
313 }
314 ++from_vertices;
315 }
316 }
317
318 if (total_num_cell_vertices != num_cells * crn_dim_len)
320 xrealloc(
321 cell_to_vertex, total_num_cell_vertices * sizeof(*cell_to_vertex));
322
323 // make a copy of cell_to_vertex and sort the vertex indices of each cell,
324 // this is required by the detection of duplicated cells
325 int * cell_to_vertex_copy =
326 xmalloc(total_num_cell_vertices * sizeof(*cell_to_vertex_copy));
327 memcpy(
328 cell_to_vertex_copy, cell_to_vertex,
329 total_num_cell_vertices * sizeof(*cell_to_vertex_copy));
330 for (size_t i = 0, offset = 0; i < num_cells; ++i) {
331 qsort(
332 cell_to_vertex_copy + offset, (size_t)(num_vertices_per_cell[i]),
333 sizeof(*cell_to_vertex_copy), compare_int);
334 offset += num_vertices_per_cell[i];
335 }
336
337 // detect duplicated cells
338 size_t * duplicated_cell_idx;
339 size_t * orig_cell_idx;
340 size_t nbr_duplicated_cells;
342 cell_to_vertex_copy, num_vertices_per_cell, cell_mask, num_cells,
343 &duplicated_cell_idx, &orig_cell_idx, &nbr_duplicated_cells);
344 free(cell_to_vertex_copy);
345
346 // mask out duplicated cells
347 for (size_t i = 0; i < nbr_duplicated_cells; ++i)
348 cell_mask[duplicated_cell_idx[i]] = 0;
349
350 if ((duplicated_cell_idx_ != NULL) && (orig_cell_idx_ != NULL) &&
351 (nbr_duplicated_cells_ != NULL)) {
352 *duplicated_cell_idx_ = duplicated_cell_idx;
353 *orig_cell_idx_ = orig_cell_idx;
354 *nbr_duplicated_cells_ = nbr_duplicated_cells;
355 } else {
356 free(duplicated_cell_idx);
357 free(orig_cell_idx);
358 }
359
360 if (with_vertices) {
361
362 *num_vertices_ = num_vertices;
363 *num_vertices_per_cell_ = num_vertices_per_cell;
364 *cell_to_vertex_ = cell_to_vertex;
365 *x_vertices = clo;
366 *y_vertices = cla;
367
368 } else {
369
370 free(num_vertices_per_cell);
371 free(cell_to_vertex);
372 free(clo);
373 free(cla);
374
375 }
376 *num_cells_ = num_cells;
377}
378
380 const char * filename, const char * grid_name,
381 size_t cell_mask_size, int * cell_mask,
382 size_t * num_vertices_, size_t * num_cells_, int ** num_vertices_per_cell_,
383 int ** cell_to_vertex_,
384 double ** x_vertices_, double ** y_vertices_, yac_int ** vertex_ids_,
385 double ** x_cells_, double ** y_cells_, yac_int ** cell_ids_,
386 size_t ** duplicated_cell_idx_, yac_int ** orig_cell_ids_,
387 size_t * nbr_duplicated_cells_,
388 int io_rank_idx, int num_io_ranks, MPI_Comm comm, int with_vertices) {
389
390 size_t num_cells = 0;
391 size_t num_vertices = 0;
392 size_t * reorder_idx = NULL;
393 size_t max_num_vertices_per_cell = 0;
394
395 double * x_vertices = NULL;
396 double * y_vertices = NULL;
397 yac_int * vertex_ids = NULL;
398 double * x_cells = NULL;
399 double * y_cells = NULL;
400 yac_int * cell_ids = NULL;
401
402 if ((io_rank_idx >= 0) && (io_rank_idx < num_io_ranks)) {
403
404 size_t grid_name_len = strlen(grid_name) + 1;
405 char cla_var_name[4 + grid_name_len];
406 char clo_var_name[4 + grid_name_len];
407 char lat_var_name[4 + grid_name_len];
408 char lon_var_name[4 + grid_name_len];
409
410 snprintf(cla_var_name, 4 + grid_name_len, "%s.cla", grid_name);
411 snprintf(clo_var_name, 4 + grid_name_len, "%s.clo", grid_name);
412 snprintf(lat_var_name, 4 + grid_name_len, "%s.lat", grid_name);
413 snprintf(lon_var_name, 4 + grid_name_len, "%s.lon", grid_name);
414
415 int ncid;
416 yac_nc_open(filename, NC_NOWRITE, &ncid);
417
418 // get variable ids
419 int cla_var_id, clo_var_id, lat_var_id, lon_var_id;
420 if (with_vertices) {
421 yac_nc_inq_varid(ncid, cla_var_name, &cla_var_id);
422 yac_nc_inq_varid(ncid, clo_var_name, &clo_var_id);
423 }
424 yac_nc_inq_varid(ncid, lat_var_name, &lat_var_id);
425 yac_nc_inq_varid(ncid, lon_var_name, &lon_var_id);
426
427 // get dimension ids
428 int dim_ids[NC_MAX_VAR_DIMS];
429 if (with_vertices) {
430 int ndims;
432 nc_inq_var(ncid, cla_var_id, NULL, NULL, &ndims, dim_ids, NULL));
434 ndims == 3,
435 "invalid number of dimensions for variable \"%s\" (has to be 3 not %d)",
436 cla_var_name, ndims);
437 } else {
438 int ndims;
440 nc_inq_var(ncid, lat_var_id, NULL, NULL, &ndims, dim_ids, NULL));
442 ndims == 2,
443 "invalid number of dimensions for variable \"%s\" (has to be 2 not %d)",
444 lat_var_name, ndims);
445 dim_ids[2] = dim_ids[1];
446 dim_ids[1] = dim_ids[0];
447 dim_ids[0] = -1;
448 }
449 int crn_dim_id = dim_ids[0];
450 int x_dim_id = dim_ids[2];
451 int y_dim_id = dim_ids[1];
452
453 // get dimension length
454 size_t crn_dim_len, x_dim_len, y_dim_len;
455 if (with_vertices)
456 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, crn_dim_id, &crn_dim_len));
457 else
458 crn_dim_len = 1;
459 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, x_dim_id, &x_dim_len));
460 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, y_dim_id, &y_dim_len));
461
462 // decompose x dimension among io ranks
463 size_t x_start_local =
464 (size_t)
465 (((unsigned long)x_dim_len * (unsigned long)io_rank_idx) /
466 (unsigned long)num_io_ranks);
467 size_t x_count_local =
468 (size_t)
469 (((unsigned long)x_dim_len * (io_rank_idx + 1)) /
470 (unsigned long)num_io_ranks) - x_start_local;
471
472 num_cells = x_count_local * y_dim_len;
473
474 if (with_vertices) {
475
476 num_vertices = num_cells * crn_dim_len;
477 max_num_vertices_per_cell = crn_dim_len;
478
479 } else {
480
481 num_vertices = num_cells;
482 max_num_vertices_per_cell = 1;
483 }
484
486 num_cells == cell_mask_size,
487 "cell mask size is inconsistent with number of grid cells")
488
489 if ((x_cells_ != NULL) && (y_cells_ != NULL)) {
490 x_cells = xmalloc(num_cells * sizeof(*x_cells));
491 y_cells = xmalloc(num_cells * sizeof(*y_cells));
492 size_t start[2] = {0, x_start_local};
493 size_t count[2] = {y_dim_len, x_count_local};
495 nc_get_vara_double(ncid, lon_var_id, start, count, x_cells));
497 nc_get_vara_double(ncid, lat_var_id, start, count, y_cells));
498 }
499
500 if (with_vertices) {
501
502 // allocate variables
503 x_vertices = xmalloc(num_vertices * sizeof(*x_vertices));
504 y_vertices = xmalloc(num_vertices * sizeof(*y_vertices));
505
506 //read variables
507 size_t start[3] = {0, 0, x_start_local};
508 size_t count[3] = {crn_dim_len, y_dim_len, x_count_local};
510 nc_get_vara_double(ncid, clo_var_id, start, count, x_vertices));
512 nc_get_vara_double(ncid, cla_var_id, start, count, y_vertices));
513
514 } else {
515
516 x_vertices = xmalloc(num_cells * sizeof(*x_vertices));
517 y_vertices = xmalloc(num_cells * sizeof(*y_vertices));
518
520 (x_cells_ != NULL) && (y_cells_ != NULL),
521 "no pointers for cell coordinates were provided")
522
523 memcpy(x_vertices, x_cells, num_cells * sizeof(*x_vertices));
524 memcpy(y_vertices, y_cells, num_cells * sizeof(*y_vertices));
525 }
526
527 YAC_HANDLE_ERROR(nc_close(ncid));
528
529 reorder_idx = xmalloc(num_vertices * sizeof(*reorder_idx));
530 for (size_t y = 0, l = 0; y < y_dim_len; ++y)
531 for (size_t x = 0; x < x_count_local; ++x)
532 for (size_t n = 0; n < crn_dim_len; ++n, ++l)
533 reorder_idx[
534 x + y * x_count_local + n * x_count_local * y_dim_len] = l;
535
536 // generate global cell ids
537 cell_ids = xmalloc(num_cells * sizeof(*cell_ids));
538 for (size_t y = 0, k = 0; y < y_dim_len; ++y)
539 for (size_t x = 0; x < x_count_local; ++x, ++k)
540 cell_ids[k] = y * x_dim_len + x + x_start_local;
541
542
544 (y_dim_len * x_dim_len * crn_dim_len) <= YAC_INT_MAX,
545 "number of vertices exceed maximum global id (%zu)",
546 (size_t)YAC_INT_MAX);
547
548 // generate global vertex ids
549 vertex_ids = xmalloc(num_cells * crn_dim_len * sizeof(*vertex_ids));
550 for (size_t n = 0, l = 0; n < crn_dim_len; ++n)
551 for (size_t i = 0; i < num_cells; ++i, ++l)
552 vertex_ids[l] = cell_ids[i] * crn_dim_len + n;
553 }
554
555 // remove duplicated vertices
556 int * cell_to_vertex = xmalloc(num_vertices * sizeof(*cell_to_vertex));
558 &x_vertices, &y_vertices, &num_vertices,
559 cell_to_vertex, &vertex_ids, comm);
560
561 // we have to reorder cell_to_vertex
563 reorder_idx, num_cells * max_num_vertices_per_cell, cell_to_vertex);
564 free(reorder_idx);
565
566 // determine number of vertices per cell and compact cell_to_vertex
567 int * num_vertices_per_cell =
568 xmalloc(num_cells * sizeof(*num_vertices_per_cell));
569 size_t total_num_cell_vertices = 0;
570 int * to_vertices = cell_to_vertex;
571 int * from_vertices = cell_to_vertex;
572 if (max_num_vertices_per_cell > 1) {
573 for (size_t i = 0; i < num_cells; ++i) {
574 size_t curr_num_vertices = 0;
575 if (cell_mask[i]) {
576 if (max_num_vertices_per_cell > 1) {
577 int prev_vertex = from_vertices[max_num_vertices_per_cell-1];
578 for (size_t j = 0; j < max_num_vertices_per_cell; ++j, ++from_vertices) {
579 int curr_vertex = *from_vertices;
580 if (prev_vertex != curr_vertex) {
581 prev_vertex = curr_vertex;
582 if (to_vertices != from_vertices) *to_vertices = curr_vertex;
583 ++curr_num_vertices;
584 ++to_vertices;
585 }
586 }
587 }
588 } else {
589 from_vertices += max_num_vertices_per_cell;
590 }
591 num_vertices_per_cell[i] = (int)curr_num_vertices;
592 total_num_cell_vertices += curr_num_vertices;
593 }
594 } else {
595 for (size_t i = 0; i < num_cells; ++i) {
596 if (cell_mask[i]) {
597 if (to_vertices != from_vertices) *to_vertices = *from_vertices;
598 ++to_vertices;
599 ++total_num_cell_vertices;
600 num_vertices_per_cell[i] = 1;
601 } else {
602 num_vertices_per_cell[i] = 0;
603 }
604 ++from_vertices;
605 }
606 }
607
608 if (total_num_cell_vertices != num_cells * max_num_vertices_per_cell)
610 xrealloc(
611 cell_to_vertex, total_num_cell_vertices * sizeof(*cell_to_vertex));
612
613 // detect duplicated cells
614 size_t * duplicated_cell_idx;
615 yac_int * orig_cell_ids;
616 size_t nbr_duplicated_cells;
618 cell_to_vertex, num_vertices_per_cell, cell_mask, cell_ids, num_cells,
619 vertex_ids, comm, &duplicated_cell_idx, &orig_cell_ids,
620 &nbr_duplicated_cells);
621
622 // mask out duplicated cells
623 for (size_t i = 0; i < nbr_duplicated_cells; ++i)
624 cell_mask[duplicated_cell_idx[i]] = 0;
625
626 if ((duplicated_cell_idx_ != NULL) && (orig_cell_ids_ != NULL) &&
627 (nbr_duplicated_cells_ != NULL)) {
628 *duplicated_cell_idx_ = duplicated_cell_idx;
629 *orig_cell_ids_ = orig_cell_ids;
630 *nbr_duplicated_cells_ = nbr_duplicated_cells;
631 } else {
632 free(duplicated_cell_idx);
633 free(orig_cell_ids);
634 }
635
636 if (with_vertices) {
637
638 *num_vertices_ = num_vertices;
639 *num_vertices_per_cell_ = num_vertices_per_cell;
640 *x_vertices_ = x_vertices;
641 *y_vertices_ = y_vertices;
642 *cell_to_vertex_ = cell_to_vertex;
643 *vertex_ids_ = vertex_ids;
644
645 } else {
646
647 free(num_vertices_per_cell);
648 free(x_vertices);
649 free(y_vertices);
650 free(cell_to_vertex);
651 free(vertex_ids);
652 }
653 *num_cells_ = num_cells;
654 if ((x_cells_ != NULL) && (y_cells_ != NULL)) {
655 *x_cells_ = x_cells;
656 *y_cells_ = y_cells;
657 }
658 *cell_ids_ = cell_ids;
659}
660
662 const char * filename, const char * grid_name, size_t * num_cells_,
663 int ** cell_mask) {
664
665 size_t grid_name_len = strlen(grid_name) + 1;
666 char msk_var_name[4 + grid_name_len];
667
668 snprintf(msk_var_name, 4 + grid_name_len, "%s.msk", grid_name);
669
670 int ncid;
671 yac_nc_open(filename, NC_NOWRITE, &ncid);
672
673 // get variable id
674 int msk_var_id;
675 yac_nc_inq_varid(ncid, msk_var_name, &msk_var_id);
676
677 // get dimension ids
678 int ndims;
679 int dim_ids[NC_MAX_VAR_DIMS];
681 nc_inq_var(ncid, msk_var_id, NULL, NULL, &ndims, dim_ids, NULL));
683 ndims == 2,
684 "invalid number of dimensions for variable \"%s\" (has to be 2 not %d)",
685 msk_var_name, ndims);
686 int x_dim_id = dim_ids[1];
687 int y_dim_id = dim_ids[0];
688
689 // get dimension length
690 size_t x_dim_len;
691 size_t y_dim_len;
692 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, x_dim_id, &x_dim_len));
693 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, y_dim_id, &y_dim_len));
694
695 size_t num_cells = x_dim_len * y_dim_len;
696
697 // allocate variable
698 *cell_mask = xmalloc(num_cells * sizeof(**cell_mask));
699
700 //read variable
701 YAC_HANDLE_ERROR(nc_get_var_int(ncid, msk_var_id, *cell_mask));
702
703 YAC_HANDLE_ERROR(nc_close(ncid));
704
705 *num_cells_ = num_cells;
706}
707
709 const char * filename, const char * grid_name, size_t * num_cells_,
710 int ** cell_mask, int io_rank_idx, int num_io_ranks) {
711
712 if ((io_rank_idx >= 0) && (io_rank_idx < num_io_ranks)) {
713
714 size_t grid_name_len = strlen(grid_name) + 1;
715 char msk_var_name[4 + grid_name_len];
716
717 snprintf(msk_var_name, 4 + grid_name_len, "%s.msk", grid_name);
718
719 int ncid;
720 yac_nc_open(filename, NC_NOWRITE, &ncid);
721
722 // get variable id
723 int msk_var_id;
724 yac_nc_inq_varid(ncid, msk_var_name, &msk_var_id);
725
726 // get dimension ids
727 int ndims;
728 int dim_ids[NC_MAX_VAR_DIMS];
730 nc_inq_var(ncid, msk_var_id, NULL, NULL, &ndims, dim_ids, NULL));
732 ndims == 2,
733 "invalid number of dimensions for variable \"%s\" (has to be 2 not %d)",
734 msk_var_name, ndims);
735 int x_dim_id = dim_ids[1];
736 int y_dim_id = dim_ids[0];
737
738 // get dimension length
739 size_t x_dim_len;
740 size_t y_dim_len;
741 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, x_dim_id, &x_dim_len));
742 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, y_dim_id, &y_dim_len));
743
744 // decompose x dimension among io ranks
745 size_t x_start_local =
746 (size_t)
747 (((unsigned long)x_dim_len * (unsigned long)io_rank_idx) /
748 (unsigned long)num_io_ranks);
749 size_t x_count_local =
750 (size_t)
751 (((unsigned long)x_dim_len * (io_rank_idx+1)) /
752 (unsigned long)num_io_ranks) - x_start_local;
753
754 size_t num_cells = x_count_local * y_dim_len;
755
756 // allocate variable
757 *cell_mask = xmalloc(num_cells * sizeof(**cell_mask));
758
759 //read variable
760 size_t start[2] = {0, x_start_local};
761 size_t count[2] = {y_dim_len, x_count_local};
763 nc_get_vara_int(ncid, msk_var_id, start, count, *cell_mask));
764
765 YAC_HANDLE_ERROR(nc_close(ncid));
766
767 *num_cells_ = num_cells;
768
769 } else {
770 *cell_mask = NULL;
771 *num_cells_ = 0;
772 }
773}
774
776 char const * grid_filename, char const * mask_filename,
777 char const * grid_name, int valid_mask_value,
778 size_t * num_vertices, size_t * num_cells, int ** num_vertices_per_cell,
779 double ** x_vertices, double ** y_vertices,
780 double ** x_cells, double ** y_cells,
781 int ** cell_to_vertex, int ** cell_core_mask, size_t ** duplicated_cell_idx,
782 size_t ** orig_cell_idx, size_t * nbr_duplicated_cells, int with_vertices) {
783
784 size_t cell_mask_size;
785 int * cell_mask;
787 mask_filename, grid_name, &cell_mask_size, &cell_mask);
788
789 for (size_t i = 0; i < cell_mask_size; ++i)
790 cell_mask[i] = cell_mask[i] == valid_mask_value;
791
793 grid_filename, grid_name, cell_mask_size, cell_mask,
794 num_vertices, num_cells, num_vertices_per_cell, cell_to_vertex,
795 x_vertices, y_vertices, x_cells, y_cells, duplicated_cell_idx,
796 orig_cell_idx, nbr_duplicated_cells, with_vertices);
797
798 if (with_vertices) {
799 for (size_t i = 0; i < *num_vertices; ++i) {
800 (*x_vertices)[i] *= YAC_RAD;
801 (*y_vertices)[i] *= YAC_RAD;
802 }
803 }
804 if ((x_cells != NULL) && (y_cells != NULL)) {
805 for (size_t i = 0; i < *num_cells; ++i) {
806 (*x_cells)[i] *= YAC_RAD;
807 (*y_cells)[i] *= YAC_RAD;
808 }
809 }
810
812 !with_vertices || (*num_vertices <= INT_MAX), "too man vertices in grid")
813 YAC_ASSERT(*num_cells <= INT_MAX, "too man cells in grid")
814
816}
817
819 char const * grid_filename, char const * mask_filename,
820 char const * grid_name, int valid_mask_value,
821 size_t * num_vertices, size_t * num_cells, int ** num_vertices_per_cell,
822 double ** x_vertices, double ** y_vertices,
823 double ** x_cells, double ** y_cells,
824 int ** cell_to_vertex, int ** cell_core_mask, size_t ** duplicated_cell_idx,
825 size_t ** orig_cell_idx, size_t * nbr_duplicated_cells) {
826
828 grid_filename, mask_filename, grid_name, valid_mask_value,
829 num_vertices, num_cells, num_vertices_per_cell, x_vertices, y_vertices,
830 x_cells, y_cells, cell_to_vertex, cell_core_mask,
831 duplicated_cell_idx, orig_cell_idx, nbr_duplicated_cells, 1);
832}
833
835 MPI_Comm comm, int * io_rank_idx, int * num_io_ranks) {
836
837 int local_is_io, * io_ranks;
838 yac_get_io_ranks(comm, &local_is_io, &io_ranks, num_io_ranks);
839
840 int comm_rank;
841 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
842
843 *io_rank_idx = 0;
844 while ((*io_rank_idx < *num_io_ranks) &&
845 (comm_rank != io_ranks[*io_rank_idx]))
846 ++*io_rank_idx;
848 !local_is_io || (*io_rank_idx < *num_io_ranks),
849 "unable to determine io_rank_idx");
850 free(io_ranks);
851
852 return local_is_io;
853}
854
856 char const * grid_filename, char const * mask_filename,
857 MPI_Comm comm, char const * grid_name, int valid_mask_value,
858 size_t * num_vertices, size_t * num_cells, int ** num_vertices_per_cell,
859 double ** x_vertices, double ** y_vertices, yac_int ** vertex_ids,
860 double ** x_cells, double ** y_cells, yac_int ** cell_ids,
861 int ** cell_to_vertex, int ** cell_core_mask, size_t ** duplicated_cell_idx,
862 yac_int ** orig_cell_ids, size_t * nbr_duplicated_cells, int with_vertices) {
863
864 // if no communicator was provided
865 if (comm == MPI_COMM_NULL) {
866
867 size_t * orig_cell_idx = NULL;
868
870 grid_filename, mask_filename, grid_name, valid_mask_value,
871 num_vertices, num_cells, num_vertices_per_cell,
872 x_vertices, y_vertices, x_cells, y_cells, cell_to_vertex,
873 cell_core_mask, duplicated_cell_idx,
874 (orig_cell_ids != NULL)?&orig_cell_idx:NULL,
875 nbr_duplicated_cells, with_vertices);
876
877 if (with_vertices) {
878 *vertex_ids = xmalloc(*num_vertices * sizeof(**vertex_ids));
879 for (size_t i = 0; i < *num_vertices; ++i) (*vertex_ids)[i] = i;
880 }
881
882 *cell_ids = xmalloc(*num_cells * sizeof(**cell_ids));
883 for (size_t i = 0; i < *num_cells; ++i) (*cell_ids)[i] = i;
884
885 if (orig_cell_ids != NULL) {
886 *orig_cell_ids =
887 xmalloc(*nbr_duplicated_cells * sizeof(**orig_cell_ids));
888 for (size_t i = 0; i < *nbr_duplicated_cells; ++i)
889 (*orig_cell_ids)[i] = (*cell_ids)[orig_cell_idx[i]];
890 free(orig_cell_idx);
891 }
892
893 } else {
894
895 int io_rank_idx, num_io_ranks;
896 get_io_configuration(comm, &io_rank_idx, &num_io_ranks);
897
898 int * cell_mask;
899 size_t cell_mask_size;
901 mask_filename, grid_name, &cell_mask_size, &cell_mask,
902 io_rank_idx, num_io_ranks);
903
904 for (size_t i = 0; i < cell_mask_size; ++i)
905 cell_mask[i] = cell_mask[i] == valid_mask_value;
906
908 grid_filename, grid_name, cell_mask_size, cell_mask,
909 num_vertices, num_cells, num_vertices_per_cell, cell_to_vertex,
910 x_vertices, y_vertices, vertex_ids,
911 x_cells, y_cells, cell_ids, duplicated_cell_idx,
912 orig_cell_ids, nbr_duplicated_cells,
913 io_rank_idx, num_io_ranks, comm, with_vertices);
914
915 if (with_vertices) {
916 for (size_t i = 0; i < *num_vertices; ++i) {
917 (*x_vertices)[i] *= YAC_RAD;
918 (*y_vertices)[i] *= YAC_RAD;
919 }
920 }
921 if ((x_cells != NULL) && (y_cells != NULL)) {
922 for (size_t i = 0; i < *num_cells; ++i) {
923 (*x_cells)[i] *= YAC_RAD;
924 (*y_cells)[i] *= YAC_RAD;
925 }
926 }
927
929 !with_vertices || (*num_vertices <= INT_MAX), "too man vertices in grid")
931 *num_cells <= INT_MAX, "too man cells in grid")
933 cell_mask_size == *num_cells,
934 "mask and grid size do not match "
935 "(mask_file: \"%s\" grid_file: \"%s\" grid_name: \"%s\"",
936 mask_filename, grid_filename, grid_name)
937
939 }
940}
941
943 char const * grid_filename, char const * mask_filename,
944 MPI_Comm comm, char const * grid_name, int valid_mask_value, int use_ll,
945 double ** x_cells, double ** y_cells, size_t ** duplicated_cell_idx,
946 yac_int ** orig_cell_global_ids, size_t * nbr_duplicated_cells) {
947
948 size_t num_vertices;
949 size_t num_cells;
950
952 double * x_vertices;
953 double * y_vertices;
956 int * cell_to_vertex;
957 int * cell_core_mask;
958
960 grid_filename, mask_filename, comm, grid_name, valid_mask_value,
962 &x_vertices, &y_vertices, &vertex_ids, x_cells, y_cells, &cell_ids,
963 &cell_to_vertex, &cell_core_mask, duplicated_cell_idx,
964 orig_cell_global_ids, nbr_duplicated_cells, 1);
965
966 // check whether any cell has more then four vertices
967 // --> write out a warning and switch to gc edges
968 if (use_ll) {
969 for (size_t i = 0; (i < num_cells) && use_ll; ++i)
970 use_ll = !cell_core_mask[i] || (num_vertices_per_cell[i] <= 4);
971 int comm_rank = 0;
972 if (comm != MPI_COMM_NULL) {
974 MPI_Allreduce(
975 MPI_IN_PLACE, &use_ll, 1, MPI_INT, MPI_MIN, comm), comm);
976 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
977 }
978 if (!use_ll && (comm_rank == 0))
979 fprintf(
980 stderr, "WARNING(yac_read_scrip_basic_grid_data_): "
981 "grid \"%s\" from \"%s\": required LL but stored as GC "
982 "(>4 vertices per cell)\n",
983 grid_name, grid_filename);
984 }
985
987 (*generate_basic_grid_data_unstruct_ptr)(
988 size_t, size_t, int *, double *, double *, int *) =
989 (use_ll)?
992
994 generate_basic_grid_data_unstruct_ptr(
996 x_vertices, y_vertices, cell_to_vertex);
997
999 free(x_vertices);
1000 free(y_vertices);
1001 free(cell_to_vertex);
1002
1003 free(grid_data.core_cell_mask);
1004 grid_data.core_cell_mask = cell_core_mask;
1005
1006 free(grid_data.vertex_ids);
1007 grid_data.vertex_ids = vertex_ids;
1008 free(grid_data.cell_ids);
1009 grid_data.cell_ids = cell_ids;
1010
1011 return grid_data;
1012}
1013
1015 char const * grid_filename, char const * mask_filename,
1016 char const * grid_name, int valid_mask_value, int use_ll_edges) {
1017
1018 return
1020 grid_filename, mask_filename, MPI_COMM_NULL,
1021 grid_name, valid_mask_value, use_ll_edges,
1022 NULL, NULL, NULL, NULL, NULL);
1023}
1024
1026 char const * grid_filename, char const * mask_filename,
1027 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1028 char const * name, int use_ll_edges, size_t * cell_coord_idx,
1029 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
1030 size_t * nbr_duplicated_cells) {
1031
1032 // generate basic grid
1033 double * x_cells, * y_cells;
1034 struct yac_basic_grid * basic_grid =
1036 name,
1038 grid_filename, mask_filename, comm, grid_name, valid_mask_value,
1039 use_ll_edges, (cell_coord_idx != NULL)?&x_cells:NULL,
1040 (cell_coord_idx != NULL)?&y_cells:NULL, duplicated_cell_idx,
1041 orig_cell_global_ids, nbr_duplicated_cells));
1042
1043 if (cell_coord_idx != NULL) {
1044
1045 // generate 3d cell center coordinates
1046 size_t num_cells =
1049 xmalloc(num_cells * sizeof(*cell_coords));
1050 for (size_t i = 0; i < num_cells; ++i)
1051 LLtoXYZ(x_cells[i], y_cells[i], cell_coords[i]);
1052 free(x_cells);
1053 free(y_cells);
1054
1055 // register cell center coordinates in basic grid
1056 *cell_coord_idx =
1058 basic_grid, YAC_LOC_CELL, cell_coords);
1059 }
1060
1061 return basic_grid;
1062}
1063
1065 char const * grid_filename, char const * mask_filename,
1066 MPI_Fint comm, char const * grid_name, int valid_mask_value,
1067 char const * name, int use_ll_edges, size_t * cell_coord_idx,
1068 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
1069 size_t * nbr_duplicated_cells) {
1070
1071 return
1073 grid_filename, mask_filename, MPI_Comm_f2c(comm), grid_name,
1074 valid_mask_value, name, use_ll_edges, cell_coord_idx,
1075 duplicated_cell_idx, orig_cell_global_ids, nbr_duplicated_cells);
1076}
1077
1079 char const * grid_filename, char const * mask_filename,
1080 char const * grid_name, int valid_mask_value, char const * name,
1081 int use_ll_edges, size_t * cell_coord_idx,
1082 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
1083 size_t * nbr_duplicated_cells) {
1084
1085 return
1087 grid_filename, mask_filename, MPI_COMM_NULL, grid_name, valid_mask_value,
1088 name, use_ll_edges, cell_coord_idx, duplicated_cell_idx,
1089 orig_cell_global_ids, nbr_duplicated_cells);
1090}
1091
1093 char const * grid_filename, char const * mask_filename, MPI_Comm comm,
1094 char const * grid_name, int valid_mask_value, size_t ** duplicated_vertex_idx,
1095 yac_int ** orig_vertex_global_ids, size_t * nbr_duplicated_vertices) {
1096
1097 size_t file_num_cells;
1098
1099 double * file_x_cells;
1100 double * file_y_cells;
1101 yac_int * file_cell_ids;
1102 int * file_cell_core_mask;
1103
1105 grid_filename, mask_filename, comm, grid_name, valid_mask_value,
1106 NULL, &file_num_cells, NULL, NULL, NULL, NULL,
1107 &file_x_cells, &file_y_cells, &file_cell_ids,
1108 NULL, &file_cell_core_mask, duplicated_vertex_idx,
1109 orig_vertex_global_ids, nbr_duplicated_vertices, 0);
1110
1113 file_num_cells, file_x_cells, file_y_cells);
1114
1115 free(file_x_cells);
1116 free(file_y_cells);
1117
1118 free(grid_data.core_vertex_mask);
1119 grid_data.core_vertex_mask = file_cell_core_mask;
1120
1121 free(grid_data.vertex_ids);
1122 grid_data.vertex_ids = file_cell_ids;
1123
1124 return grid_data;
1125}
1126
1128 char const * grid_filename, char const * mask_filename,
1129 char const * grid_name, int valid_mask_value) {
1130
1131 return
1133 grid_filename, mask_filename, MPI_COMM_NULL,
1134 grid_name, valid_mask_value, NULL, NULL, NULL);
1135}
1136
1138 char const * grid_filename, char const * mask_filename,
1139 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1140 char const * name, size_t * vertex_coord_idx,
1141 size_t ** duplicated_vertex_idx, yac_int ** orig_vertex_global_ids,
1142 size_t * nbr_duplicated_vertices) {
1143
1144 // generate basic grid
1145 struct yac_basic_grid_data basic_grid_data =
1147 grid_filename, mask_filename, comm, grid_name, valid_mask_value,
1148 duplicated_vertex_idx, orig_vertex_global_ids, nbr_duplicated_vertices);
1149 struct yac_basic_grid * basic_grid =
1150 yac_basic_grid_new(name, basic_grid_data);
1151
1152 if (vertex_coord_idx != NULL) {
1153
1154 size_t num_vertices = basic_grid_data.num_vertices;
1155 yac_coordinate_pointer vertex_coords =
1156 xmalloc(num_vertices * sizeof(*vertex_coords));
1157 memcpy(
1158 vertex_coords, basic_grid_data.vertex_coordinates,
1159 num_vertices * sizeof(*vertex_coords));
1160 *vertex_coord_idx =
1162 basic_grid, YAC_LOC_CORNER, vertex_coords);
1163 }
1164
1165 return basic_grid;
1166}
1167
1169 char const * grid_filename, char const * mask_filename,
1170 MPI_Fint comm, char const * grid_name, int valid_mask_value,
1171 char const * name, size_t * vertex_coord_idx,
1172 size_t ** duplicated_vertex_idx, yac_int ** orig_vertex_global_ids,
1173 size_t * nbr_duplicated_vertices) {
1174
1175 return
1177 grid_filename, mask_filename, MPI_Comm_f2c(comm), grid_name,
1178 valid_mask_value, name, vertex_coord_idx, duplicated_vertex_idx,
1179 orig_vertex_global_ids, nbr_duplicated_vertices);
1180}
1181
1183 char const * grid_filename, char const * mask_filename,
1184 char const * grid_name, int valid_mask_value, char const * name,
1185 size_t * vertex_coord_idx, size_t ** duplicated_vertex_idx,
1186 yac_int ** orig_vertex_global_ids, size_t * nbr_duplicated_vertices) {
1187
1188 return
1190 grid_filename, mask_filename, MPI_COMM_NULL, grid_name, valid_mask_value,
1191 name, vertex_coord_idx, duplicated_vertex_idx, orig_vertex_global_ids,
1192 nbr_duplicated_vertices);
1193}
1194
1196 char const * grid_filename, MPI_Comm comm, char const * grid_name) {
1197
1198 int local_is_io, * io_ranks, num_io_ranks;
1199 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
1200 int root_rank = io_ranks[0];
1201
1202 int comm_rank;
1203 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1204
1205 int contains_corner_information = 0;
1206
1207 if (local_is_io && (comm_rank == root_rank)) {
1208
1209 size_t grid_name_len = strlen(grid_name) + 1;
1210 char cla_var_name[4 + grid_name_len];
1211 char clo_var_name[4 + grid_name_len];
1212
1213 snprintf(cla_var_name, 4 + grid_name_len, "%s.cla", grid_name);
1214 snprintf(clo_var_name, 4 + grid_name_len, "%s.clo", grid_name);
1215
1216 int ncid;
1217 yac_nc_open(grid_filename, NC_NOWRITE, &ncid);
1218
1219 // get variable ids
1220 int cla_var_id, clo_var_id;
1221
1222 contains_corner_information =
1223 (NC_NOERR == nc_inq_varid(ncid, cla_var_name, &cla_var_id)) &&
1224 (NC_NOERR == nc_inq_varid(ncid, clo_var_name, &clo_var_id));
1225
1226 YAC_HANDLE_ERROR(nc_close(ncid));
1227 }
1228
1230 MPI_Bcast(
1231 &contains_corner_information, 1, MPI_INT, root_rank, comm), comm);
1232
1233 return contains_corner_information;
1234}
1235
1237 char const * grid_filename, char const * mask_filename,
1238 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1239 char const * name, int use_ll_edges, size_t * point_coord_idx,
1240 size_t ** duplicated_point_idx, yac_int ** orig_point_global_ids,
1241 size_t * nbr_duplicated_points, int * point_location) {
1242
1243 int contains_corner_information =
1244 check_corner_information(grid_filename, comm, grid_name);
1245
1246 if (contains_corner_information) {
1247 *point_location = YAC_LOC_CELL;
1248 return
1250 grid_filename, mask_filename, comm, grid_name,
1251 valid_mask_value, name, use_ll_edges, point_coord_idx,
1252 duplicated_point_idx, orig_point_global_ids, nbr_duplicated_points);
1253 } else {
1254 *point_location = YAC_LOC_CORNER;
1255 return
1257 grid_filename, mask_filename, comm, grid_name,
1258 valid_mask_value, name, point_coord_idx, duplicated_point_idx,
1259 orig_point_global_ids, nbr_duplicated_points);
1260 }
1261}
1262
1264 char const * grid_filename, char const * mask_filename,
1265 MPI_Fint comm, char const * grid_name, int valid_mask_value,
1266 char const * name, int use_ll_edges, size_t * point_coord_idx,
1267 size_t ** duplicated_point_idx, yac_int ** orig_point_global_ids,
1268 size_t * nbr_duplicated_points, int * point_location) {
1269
1270 return
1272 grid_filename, mask_filename, MPI_Comm_f2c(comm), grid_name,
1273 valid_mask_value, name, use_ll_edges, point_coord_idx,
1274 duplicated_point_idx, orig_point_global_ids, nbr_duplicated_points,
1275 point_location);
1276}
1277
1278/* ---------------------------------------------------------------- */
1279
1281 const void * a,const void * b) {
1282
1283 int ret = ((struct cell_vertices_with_index const *)a)->num_vertices -
1284 ((struct cell_vertices_with_index const *)b)->num_vertices;
1285 if (ret) return ret;
1286 int count = ((struct cell_vertices_with_index const *)a)->num_vertices;
1287 for (int i = 0; (i < count) && !ret; ++i)
1288 ret = ((struct cell_vertices_with_index const *)a)->cell_to_vertex[i] -
1289 ((struct cell_vertices_with_index const *)b)->cell_to_vertex[i];
1290 return ret;
1291}
1292
1294 double ** vertex_lon, double ** vertex_lat, yac_int ** vertex_ids,
1295 size_t * nbr_vertices, int * old_to_new_id) {
1296
1297 struct point_with_index * sort_array =
1298 xmalloc(*nbr_vertices * sizeof(*sort_array));
1299
1300 double const scale = (double)(2 << 20);
1301 int32_t const periode = (int32_t)(360.0 * scale);
1302
1303 for (size_t i = 0; i < *nbr_vertices; ++i) {
1304
1305 int32_t curr_lon = (int32_t)round((*vertex_lon)[i] * scale);
1306 int32_t curr_lat = (int32_t)round((*vertex_lat)[i] * scale);
1307
1308 if ((curr_lat == (int32_t)(90.0 * scale)) ||
1309 (curr_lat == (int32_t)(-90.0 * scale))) {
1310
1311 curr_lon = 0;
1312
1313 } else {
1314 if (curr_lon <= 0)
1315 curr_lon = curr_lon - (((curr_lon - periode) / periode) * periode);
1316 else if (curr_lon > periode)
1317 curr_lon = curr_lon - ((curr_lon / periode) * periode);
1318 }
1319
1320 sort_array[i].lon = curr_lon;
1321 sort_array[i].lat = curr_lat;
1322 sort_array[i].dlon = (*vertex_lon)[i];
1323 sort_array[i].dlat = (*vertex_lat)[i];
1324 sort_array[i].id = (vertex_ids != NULL)?(*vertex_ids)[i]:YAC_INT_MAX;
1325
1326 sort_array[i].i = i;
1327 }
1328
1329 yac_mergesort(sort_array, *nbr_vertices, sizeof(*sort_array),
1331
1332 struct point_with_index dummy =
1333 {.lon = INT32_MAX, .lat = INT32_MAX, .i = SIZE_MAX};
1334 struct point_with_index * prev = &dummy, * curr = sort_array;
1335 size_t new_nbr_vertices = 0;
1336 for (size_t i = 0; i < *nbr_vertices; ++i, ++curr) {
1337
1338 if (compare_point_with_index_coord(prev, curr)) {
1339
1340 (*vertex_lon)[new_nbr_vertices] = curr->dlon;
1341 (*vertex_lat)[new_nbr_vertices] = curr->dlat;
1342 if (vertex_ids != NULL)
1343 (*vertex_ids)[new_nbr_vertices] = curr->id;
1344 sort_array[new_nbr_vertices] = *curr;
1345 new_nbr_vertices++;
1346 prev = curr;
1347 }
1348 old_to_new_id[curr->i] = (int)(new_nbr_vertices - 1);
1349 }
1350
1351 (*vertex_lon) = xrealloc(*vertex_lon, new_nbr_vertices * sizeof(**vertex_lon));
1352 (*vertex_lat) = xrealloc(*vertex_lat, new_nbr_vertices * sizeof(**vertex_lat));
1353 if (vertex_ids != NULL)
1354 (*vertex_ids) = xrealloc(*vertex_ids, new_nbr_vertices * sizeof(**vertex_ids));
1355 *nbr_vertices = new_nbr_vertices;
1356
1357 return sort_array;
1358}
1359
1361 double ** vertex_lon, double ** vertex_lat,
1362 size_t * nbr_vertices, int * old_to_new_id) {
1363
1364 free(
1366 vertex_lon, vertex_lat, NULL, nbr_vertices, old_to_new_id));
1367}
1368
1369// djb2 hash function
1370unsigned long djb2_hash(unsigned char * values, size_t count) {
1371
1372 unsigned long hash = 5381;
1373
1374 for (size_t i = 0; i < count; ++i) {
1375 unsigned int value = values[i];
1376 hash = ((hash << 5) + hash) + value; /* hash * 33 + value */
1377 }
1378
1379 return hash;
1380}
1381
1383 void * data, size_t data_size, int comm_size) {
1384
1385 return
1386 djb2_hash((unsigned char*)data, data_size) % (unsigned long)comm_size;
1387}
1388
1389static MPI_Datatype get_point_with_index_mpi_datatype(MPI_Comm comm) {
1390
1391 struct point_with_index dummy = {0};
1392 MPI_Datatype point_with_index_dt;
1393 enum {NUM_MEMBERS = 5};
1394 int array_of_blocklengths[NUM_MEMBERS] = {1, 1, 1, 1, 1};
1395 MPI_Aint array_of_displacements[NUM_MEMBERS];
1396 {
1397 MPI_Aint base_addr;
1398 yac_mpi_call(MPI_Get_address(&dummy, &base_addr), comm);
1400 MPI_Get_address(
1401 &(dummy.lon), &array_of_displacements[0]), comm);
1402 array_of_displacements[0] -= base_addr;
1404 MPI_Get_address(
1405 &(dummy.lat), &array_of_displacements[1]), comm);
1406 array_of_displacements[1] -= base_addr;
1408 MPI_Get_address(
1409 &(dummy.id), &array_of_displacements[2]), comm);
1410 array_of_displacements[2] -= base_addr;
1412 MPI_Get_address(
1413 &(dummy.dlon), &array_of_displacements[3]), comm);
1414 array_of_displacements[3] -= base_addr;
1416 MPI_Get_address(
1417 &(dummy.dlat), &array_of_displacements[4]), comm);
1418 array_of_displacements[4] -= base_addr;
1419 }
1420 const MPI_Datatype array_of_types[NUM_MEMBERS] =
1421 {MPI_INT32_T, MPI_INT32_T, yac_int_dt, MPI_DOUBLE, MPI_DOUBLE};
1423 MPI_Type_create_struct(
1424 NUM_MEMBERS, array_of_blocklengths, array_of_displacements,
1425 array_of_types, &point_with_index_dt), comm);
1426 return yac_create_resized(point_with_index_dt, sizeof(dummy), comm);
1427}
1428
1430 double ** vertex_lon, double ** vertex_lat,
1431 size_t * nbr_vertices_, int * old_to_new_id, yac_int ** vertex_ids,
1432 MPI_Comm comm) {
1433
1434 char const * routine = "remove_duplicated_vertices_parallel";
1435
1436 // remove the locally duplicated vertices
1437 struct point_with_index * sort_array =
1439 vertex_lon, vertex_lat, vertex_ids, nbr_vertices_, old_to_new_id);
1440
1441 sort_array = xrealloc(sort_array, *nbr_vertices_ * sizeof(*sort_array));
1442
1443 size_t nbr_vertices = *nbr_vertices_;
1444
1445 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1447 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
1448
1449 int comm_rank, comm_size;
1450 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1451 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1452
1453 // set up counts and displs for redistribution of points
1454 for (size_t i = 0; i < nbr_vertices; ++i) {
1455 int rank =
1457 &(sort_array[i].lon), 2 * sizeof(sort_array[i].lon), comm_size);
1458 sendcounts[rank]++;
1459 sort_array[i].rank = rank;
1460 sort_array[i].i = i;
1461 }
1462
1463 // sort points by bucket ranks
1464 yac_mergesort(sort_array, nbr_vertices, sizeof(*sort_array),
1466
1468 1, sendcounts, recvcounts, sdispls, rdispls, comm);
1469
1470 size_t recv_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
1471 struct point_with_index * dist_sort_array =
1472 xmalloc(recv_count * sizeof(*dist_sort_array));
1473
1474 // redistribute point information
1475 MPI_Datatype point_with_index_dt =
1477 yac_mpi_call(MPI_Type_commit(&point_with_index_dt), comm);
1479 sort_array, sendcounts, sdispls+1,
1480 dist_sort_array, recvcounts, rdispls,
1481 sizeof(*sort_array), point_with_index_dt, comm, routine, __LINE__);
1482
1483 for (size_t i = 0; i < recv_count; ++i) dist_sort_array[i].i = i;
1484
1485 // sort received point data based on coordinates
1486 yac_mergesort(dist_sort_array, recv_count, sizeof(*dist_sort_array),
1488
1489 struct point_with_index dummy =
1490 {.lon = INT32_MAX, .lat = INT32_MAX};
1491 struct point_with_index * prev = &dummy, * curr = dist_sort_array;
1492 for (size_t i = 0; i < recv_count; ++i, ++curr) {
1493 if (compare_point_with_index_coord(prev, curr)) {
1494
1495 prev = curr;
1496
1497 } else {
1498
1499 curr->id = prev->id;
1500 curr->dlon = prev->dlon;
1501 curr->dlat = prev->dlat;
1502 }
1503 }
1504
1505 // bring array into original order
1506 yac_mergesort(dist_sort_array, recv_count, sizeof(*dist_sort_array),
1508
1509 // redistribute point information
1511 dist_sort_array, recvcounts, rdispls,
1512 sort_array, sendcounts, sdispls+1,
1513 sizeof(*sort_array), point_with_index_dt, comm, routine, __LINE__);
1514 free(dist_sort_array);
1515 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1516 yac_mpi_call(MPI_Type_free(&point_with_index_dt), comm);
1517
1518 // bring vertex indices into original order
1519 for (size_t i = 0; i < nbr_vertices; ++i) {
1520
1521 (*vertex_lon)[sort_array[i].i] = sort_array[i].dlon;
1522 (*vertex_lat)[sort_array[i].i] = sort_array[i].dlat;
1523 (*vertex_ids)[sort_array[i].i] = sort_array[i].id;
1524 }
1525
1526 free(sort_array);
1527}
1528
1530 int * cell_to_vertex, int * num_vertices_per_cell, int * cell_mask,
1531 size_t nbr_cells, size_t ** duplicated_cell_idx,
1532 size_t ** orig_cell_idx, size_t * nbr_duplicated_cells) {
1533
1534 // count number of unmasked cells
1535 size_t nbr_unmasked_cells = 0;
1536 for (size_t i = 0; i < nbr_cells; ++i)
1537 if (cell_mask[i]) ++nbr_unmasked_cells;
1538
1539 struct cell_vertices_with_index * sort_array =
1540 xmalloc(nbr_unmasked_cells * sizeof(*sort_array));
1541
1542 // get all unmasked cells
1543 for (size_t i = 0, offset = 0, j = 0; i < nbr_cells; ++i) {
1544
1545 if (cell_mask[i]) {
1546
1547 sort_array[j].num_vertices = num_vertices_per_cell[i];
1548 sort_array[j].cell_to_vertex = cell_to_vertex + offset;
1549 sort_array[j].i = i;
1550 ++j;
1551 }
1552
1553 offset += (size_t)(num_vertices_per_cell[i]);
1554 }
1555
1556 // sort cells
1557 yac_mergesort(sort_array, nbr_unmasked_cells, sizeof(*sort_array),
1559
1560 // count number of duplicated cells
1561 *nbr_duplicated_cells = 0;
1562 for (size_t i = 1; i < nbr_unmasked_cells; ++i)
1563 if (!compare_cell_vertices_with_index(sort_array + (i-1), sort_array + i))
1564 ++*nbr_duplicated_cells;
1565
1566 // get duplicated cells
1567 *duplicated_cell_idx =
1568 xmalloc(*nbr_duplicated_cells * sizeof(**duplicated_cell_idx));
1569 *orig_cell_idx =
1570 xmalloc(*nbr_duplicated_cells * sizeof(**orig_cell_idx));
1571 struct cell_vertices_with_index *prev = sort_array, *curr = sort_array + 1;
1572 for (size_t i = 1, j = 0; i < nbr_unmasked_cells; ++i, ++curr) {
1573 if (compare_cell_vertices_with_index(prev, curr)) {
1574 prev = curr;
1575 } else {
1576 (*duplicated_cell_idx)[j] = (size_t)(curr->i);
1577 (*orig_cell_idx)[j] = (size_t)(prev->i);
1578 ++j;
1579 }
1580 }
1581
1582 free(sort_array);
1583}
1584
1586 MPI_Comm comm, size_t count) {
1587
1588 MPI_Datatype cell_to_vertex_ids_dt;
1590 MPI_Type_contiguous(
1591 (int)count, yac_int_dt, &cell_to_vertex_ids_dt), comm);
1592 return cell_to_vertex_ids_dt;
1593}
1594
1596 int * cell_to_vertex, int * num_vertices_per_cell, int * cell_mask,
1597 yac_int * cell_ids, size_t num_cells, yac_int * vertex_ids,
1598 MPI_Comm comm, size_t ** duplicated_cell_idx_,
1599 yac_int ** orig_cell_ids_, size_t * num_duplicated_cells_) {
1600
1601 char const * routine = "detect_duplicated_cells_parallel";
1602
1603 int comm_size;
1604 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1605
1606 // determine the local maximum number of vertices per cell and count
1607 // number of unmasked cells
1608 size_t max_num_vertices_per_cell = 0;
1609 size_t local_num_cells = 0;
1610 for (size_t i = 0; i < num_cells; ++i) {
1611 if (cell_mask[i]) {
1612 if ((size_t)(num_vertices_per_cell[i]) > max_num_vertices_per_cell)
1613 max_num_vertices_per_cell = (size_t)(num_vertices_per_cell[i]);
1614 local_num_cells++;
1615 }
1616 }
1617
1618 // determine the global maximum number of vertices per cell
1620 MPI_Allreduce(
1621 MPI_IN_PLACE, &max_num_vertices_per_cell, 1, YAC_MPI_SIZE_T, MPI_MAX,
1622 comm), comm);
1623
1624 // generate local cell to vertex ids array
1625 yac_int * local_cell_ids =
1626 xmalloc(local_num_cells * (1 + max_num_vertices_per_cell) *
1627 sizeof(*local_cell_ids));
1628 yac_int * local_cell_to_vertex_ids = local_cell_ids + local_num_cells;
1629
1630 // fill local cell to vertex ids array
1631 yac_int * curr_local_cell_ids = local_cell_ids;
1632 yac_int * curr_local_cell_to_vertex_ids = local_cell_to_vertex_ids;
1633 int * curr_cell_to_vertex = cell_to_vertex;
1634 for (size_t i = 0; i < num_cells; ++i) {
1635
1636 size_t curr_num_vertices_per_cell = (size_t)(num_vertices_per_cell[i]);
1637 if (cell_mask[i]) {
1638
1639 *curr_local_cell_ids = cell_ids[i];
1640
1641 // get global vertex ids for current cell
1642 size_t j = 0;
1643 for (; j < curr_num_vertices_per_cell; ++j)
1644 curr_local_cell_to_vertex_ids[j] =
1645 vertex_ids[curr_cell_to_vertex[j]];
1646
1647 // sort global vertex ids
1648 qsort(curr_local_cell_to_vertex_ids, curr_num_vertices_per_cell,
1649 sizeof(*curr_local_cell_to_vertex_ids), compare_yac_int);
1650
1651 // fill remaining entries
1652 for (; j < max_num_vertices_per_cell; ++j)
1653 curr_local_cell_to_vertex_ids[j] = YAC_INT_MAX;
1654
1655 curr_local_cell_ids++;
1656 curr_local_cell_to_vertex_ids += max_num_vertices_per_cell;
1657 }
1658 curr_cell_to_vertex += curr_num_vertices_per_cell;
1659 }
1660
1661 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1663 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
1664
1665 // determine distributed owners for all cells
1666 int * dist_cell_ranks = xmalloc(local_num_cells * sizeof(*dist_cell_ranks));
1667 for (size_t i = 0; i < local_num_cells; ++i) {
1668 int rank =
1670 local_cell_to_vertex_ids + i * max_num_vertices_per_cell,
1671 max_num_vertices_per_cell * sizeof(*local_cell_to_vertex_ids),
1672 comm_size);
1673 sendcounts[rank]++;
1674 dist_cell_ranks[i] = rank;
1675 }
1676
1678 1, sendcounts, recvcounts, sdispls, rdispls, comm);
1679
1680 size_t dist_num_cells = recvcounts[comm_size-1] + rdispls[comm_size-1];
1681 yac_int * yac_int_buffer =
1682 xmalloc((local_num_cells + dist_num_cells) *
1683 (1 + max_num_vertices_per_cell) * sizeof(*yac_int_buffer));
1684 yac_int * dist_cell_ids = yac_int_buffer;
1685 yac_int * dist_cell_vertex_ids = yac_int_buffer + dist_num_cells;
1686 yac_int * send_local_cell_ids =
1687 yac_int_buffer + dist_num_cells * (1 + max_num_vertices_per_cell);
1688 yac_int * send_local_cell_to_vertex_ids =
1689 yac_int_buffer + local_num_cells +
1690 dist_num_cells * (1 + max_num_vertices_per_cell);
1691
1692 // pack send data
1693 for (size_t i = 0; i < local_num_cells; ++i) {
1694 size_t pos = sdispls[dist_cell_ranks[i] + 1]++;
1695 send_local_cell_ids[pos] = local_cell_ids[i];
1696 memcpy(
1697 send_local_cell_to_vertex_ids + pos * max_num_vertices_per_cell,
1698 local_cell_to_vertex_ids + i * max_num_vertices_per_cell,
1699 max_num_vertices_per_cell * sizeof(*send_local_cell_to_vertex_ids));
1700 }
1701 local_cell_ids =
1702 xrealloc(local_cell_ids, local_num_cells * sizeof(*local_cell_ids));
1703
1704 // redistribute cell ids and cell vertex ids
1705 MPI_Datatype cell_to_vertex_ids_dt =
1706 get_cell_to_vertex_ids_mpi_datatype(comm, max_num_vertices_per_cell);
1707 yac_mpi_call(MPI_Type_commit(&cell_to_vertex_ids_dt), comm);
1708 yac_alltoallv_yac_int_p2p(
1709 send_local_cell_ids, sendcounts, sdispls,
1710 dist_cell_ids, recvcounts, rdispls, comm, routine, __LINE__);
1712 send_local_cell_to_vertex_ids, sendcounts, sdispls,
1713 dist_cell_vertex_ids, recvcounts, rdispls,
1714 max_num_vertices_per_cell * sizeof(*dist_cell_vertex_ids),
1715 cell_to_vertex_ids_dt, comm, routine, __LINE__);
1716 yac_mpi_call(MPI_Type_free(&cell_to_vertex_ids_dt), comm);
1717
1718 // free some memory
1719 yac_int_buffer =
1720 xrealloc(
1721 yac_int_buffer,
1722 dist_num_cells * (1 + max_num_vertices_per_cell) *
1723 sizeof(*yac_int_buffer));
1724 dist_cell_ids = yac_int_buffer;
1725 dist_cell_vertex_ids = yac_int_buffer + dist_num_cells;
1726
1727 // generate sortable data structure
1728 struct cell_vertex_ids_with_index * sort_array =
1729 xmalloc(dist_num_cells * sizeof(*sort_array));
1730 for (size_t i = 0; i < dist_num_cells; ++i) {
1731 sort_array[i].cell_id = dist_cell_ids[i];
1732 sort_array[i].vertex_ids =
1733 dist_cell_vertex_ids + i * max_num_vertices_per_cell;
1734 sort_array[i].num_vertices = max_num_vertices_per_cell;
1735 sort_array[i].i = i;
1736 }
1737
1738 // sort cells by vertex ids
1740 sort_array, dist_num_cells, sizeof(*sort_array),
1742
1743 // determine duplicated cells
1744 struct cell_vertex_ids_with_index * prev = sort_array;
1745 struct cell_vertex_ids_with_index * curr = sort_array + 1;
1746 for (size_t i = 1; i < dist_num_cells; ++i, ++curr) {
1747
1749 prev = curr;
1750 } else {
1751 curr->cell_id = prev->cell_id;
1752 }
1753 }
1754
1755 // pack cell ids
1756 yac_int_buffer =
1757 xrealloc(
1758 yac_int_buffer,
1759 (local_num_cells + dist_num_cells) * sizeof(*yac_int_buffer));
1760 yac_int * recv_local_cell_ids = yac_int_buffer;
1761 dist_cell_ids = yac_int_buffer + local_num_cells;
1762 for (size_t i = 0; i < dist_num_cells; ++i)
1763 dist_cell_ids[sort_array[i].i] = sort_array[i].cell_id;
1764 free(sort_array);
1765
1766 // redistribute cell ids
1767 yac_alltoallv_yac_int_p2p(
1768 dist_cell_ids, recvcounts, rdispls,
1769 recv_local_cell_ids, sendcounts, sdispls, comm, routine, __LINE__);
1770 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1771
1772 // bring received local cell ids into original order and
1773 // count number of duplicated cells
1774 size_t num_duplicated_cells = 0;
1775 for (size_t i = 0; i < local_num_cells; ++i) {
1776
1777 size_t pos = sdispls[dist_cell_ranks[i]]++;
1778
1779 if (local_cell_ids[i] != recv_local_cell_ids[pos]) {
1780 num_duplicated_cells++;
1781 local_cell_ids[i] = recv_local_cell_ids[pos];
1782 } else {
1783 local_cell_ids[i] = YAC_INT_MAX;
1784 }
1785 }
1786 free(yac_int_buffer);
1787 free(dist_cell_ranks);
1788
1789 size_t * duplicated_cell_idx =
1790 xmalloc(num_duplicated_cells * sizeof(*duplicated_cell_idx));
1791 yac_int * orig_cell_ids =
1792 xmalloc(num_duplicated_cells * sizeof(*orig_cell_ids));
1793
1794 // get duplicated cells
1795 for (size_t i = 0, j = 0, k = 0; i < num_cells; ++i) {
1796
1797 if (cell_mask[i]) {
1798
1799 if (local_cell_ids[j] != YAC_INT_MAX) {
1800 duplicated_cell_idx[k] = i;
1801 orig_cell_ids[k] = local_cell_ids[j];
1802 ++k;
1803 }
1804 ++j;
1805 }
1806 }
1807 free(local_cell_ids);
1808
1809 *duplicated_cell_idx_ = duplicated_cell_idx;
1810 *orig_cell_ids_ = orig_cell_ids;
1811 *num_duplicated_cells_ = num_duplicated_cells;
1812}
1813
1814#else
1815
1817 char const * grid_filename, char const * mask_filename,
1818 char const * grid_name, int valid_mask_value, int use_ll_edges) {
1819
1820 UNUSED(grid_filename);
1821 UNUSED(mask_filename);
1822 UNUSED(grid_name);
1823 UNUSED(valid_mask_value);
1824 UNUSED(use_ll_edges);
1825 die(
1826 "ERROR(yac_read_scrip_basic_grid_data): "
1827 "YAC is built without the NetCDF support");
1828
1829 return
1831 (size_t[]){0,0}, (int[]){0,0}, NULL, NULL);
1832}
1833
1835 char const * grid_filename, char const * mask_filename,
1836 char const * grid_name, int valid_mask_value, char const * name,
1837 int use_ll_edges, size_t * cell_coord_idx,
1838 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
1839 size_t * nbr_duplicated_cells) {
1840
1841 UNUSED(grid_filename);
1842 UNUSED(mask_filename);
1843 UNUSED(grid_name);
1844 UNUSED(valid_mask_value);
1845 UNUSED(name);
1846 UNUSED(use_ll_edges);
1847 UNUSED(cell_coord_idx);
1848 UNUSED(duplicated_cell_idx);
1849 UNUSED(orig_cell_global_ids);
1850 UNUSED(nbr_duplicated_cells);
1851 die(
1852 "ERROR(yac_read_scrip_basic_grid): "
1853 "YAC is built without the NetCDF support");
1854
1855 return NULL;
1856}
1857
1859 char const * grid_filename, char const * mask_filename,
1860 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1861 char const * name, int use_ll_edges, size_t * cell_coord_idx,
1862 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
1863 size_t * nbr_duplicated_cells) {
1864
1865 UNUSED(grid_filename);
1866 UNUSED(mask_filename);
1867 UNUSED(comm);
1868 UNUSED(grid_name);
1869 UNUSED(valid_mask_value);
1870 UNUSED(name);
1871 UNUSED(use_ll_edges);
1872 UNUSED(cell_coord_idx);
1873 UNUSED(duplicated_cell_idx);
1874 UNUSED(orig_cell_global_ids);
1875 UNUSED(nbr_duplicated_cells);
1876 die(
1877 "ERROR(yac_read_scrip_basic_grid_parallel): "
1878 "YAC is built without the NetCDF support");
1879
1880 return NULL;
1881}
1882
1884 char const * grid_filename, char const * mask_filename,
1885 char const * grid_name, int valid_mask_value) {
1886
1887 UNUSED(grid_filename);
1888 UNUSED(mask_filename);
1889 UNUSED(grid_name);
1890 UNUSED(valid_mask_value);
1891 die(
1892 "ERROR(yac_read_scrip_cloud_basic_grid_data): "
1893 "YAC is built without the NetCDF support");
1894
1895 return
1897 (size_t[]){0,0}, (int[]){0,0}, NULL, NULL);
1898}
1899
1901 char const * grid_filename, char const * mask_filename,
1902 char const * grid_name, int valid_mask_value, char const * name,
1903 size_t * vertex_coord_idx, size_t ** duplicated_vertex_idx,
1904 yac_int ** orig_vertex_global_ids, size_t * nbr_duplicated_vertices) {
1905
1906 UNUSED(grid_filename);
1907 UNUSED(mask_filename);
1908 UNUSED(grid_name);
1909 UNUSED(valid_mask_value);
1910 UNUSED(name);
1911 UNUSED(vertex_coord_idx);
1912 UNUSED(duplicated_vertex_idx);
1913 UNUSED(orig_vertex_global_ids);
1914 UNUSED(nbr_duplicated_vertices);
1915 die(
1916 "ERROR(yac_read_scrip_cloud_basic_grid): "
1917 "YAC is built without the NetCDF support");
1918
1919 return NULL;
1920}
1921
1923 char const * grid_filename, char const * mask_filename,
1924 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1925 char const * name, size_t * vertex_coord_idx,
1926 size_t ** duplicated_vertex_idx, yac_int ** orig_vertex_global_ids,
1927 size_t * nbr_duplicated_vertices) {
1928
1929 UNUSED(grid_filename);
1930 UNUSED(mask_filename);
1931 UNUSED(comm);
1932 UNUSED(grid_name);
1933 UNUSED(valid_mask_value);
1934 UNUSED(name);
1935 UNUSED(vertex_coord_idx);
1936 UNUSED(duplicated_vertex_idx);
1937 UNUSED(orig_vertex_global_ids);
1938 UNUSED(nbr_duplicated_vertices);
1939 die(
1940 "ERROR(yac_read_scrip_cloud_basic_grid_parallel): "
1941 "YAC is built without the NetCDF support");
1942
1943 return NULL;
1944}
1945
1947 char const * grid_filename, char const * mask_filename,
1948 MPI_Comm comm, char const * grid_name, int valid_mask_value,
1949 char const * name, int use_ll_edges, size_t * point_coord_idx,
1950 size_t ** duplicated_point_idx, yac_int ** orig_point_global_ids,
1951 size_t * nbr_duplicated_points, int * point_location) {
1952
1953 UNUSED(grid_filename);
1954 UNUSED(mask_filename);
1955 UNUSED(comm);
1956 UNUSED(grid_name);
1957 UNUSED(valid_mask_value);
1958 UNUSED(name);
1959 UNUSED(use_ll_edges);
1960 UNUSED(point_coord_idx);
1961 UNUSED(duplicated_point_idx);
1962 UNUSED(orig_point_global_ids);
1963 UNUSED(nbr_duplicated_points);
1964 UNUSED(point_location);
1965 die(
1966 "ERROR(yac_read_scrip_generic_basic_grid_parallel): "
1967 "YAC is built without the NetCDF support");
1968
1969 return NULL;
1970}
1971
1973 char const * grid_filename, char const * mask_filename,
1974 char const * grid_name, int valid_mask_value,
1975 size_t * num_vertices, size_t * num_cells, int ** num_vertices_per_cell,
1976 double ** x_vertices, double ** y_vertices,
1977 double ** x_cells, double ** y_cells,
1978 int ** cell_to_vertex, int ** cell_core_mask, size_t ** duplicated_cell_idx,
1979 size_t ** orig_cell_idx, size_t * nbr_duplicated_cells) {
1980
1981 UNUSED(grid_filename);
1982 UNUSED(mask_filename);
1983 UNUSED(grid_name);
1984 UNUSED(valid_mask_value);
1985 UNUSED(num_vertices);
1987 UNUSED(num_vertices_per_cell);
1988 UNUSED(x_vertices);
1989 UNUSED(y_vertices);
1990 UNUSED(x_cells);
1991 UNUSED(y_cells);
1994 UNUSED(duplicated_cell_idx);
1995 UNUSED(orig_cell_idx);
1996 UNUSED(nbr_duplicated_cells);
1997 die(
1998 "ERROR(yac_read_scrip_grid_information): "
1999 "YAC is built without the NetCDF support");
2000}
2001
2003 char const * grid_filename, char const * mask_filename,
2004 MPI_Fint comm, char const * grid_name, int valid_mask_value,
2005 char const * name, int use_ll_edges, size_t * cell_coord_idx,
2006 size_t ** duplicated_cell_idx, yac_int ** orig_cell_global_ids,
2007 size_t * nbr_duplicated_cells) {
2008
2009 UNUSED(grid_filename);
2010 UNUSED(mask_filename);
2011 UNUSED(comm);
2012 UNUSED(grid_name);
2013 UNUSED(valid_mask_value);
2014 UNUSED(name);
2015 UNUSED(use_ll_edges);
2016 UNUSED(cell_coord_idx);
2017 UNUSED(duplicated_cell_idx);
2018 UNUSED(orig_cell_global_ids);
2019 UNUSED(nbr_duplicated_cells);
2020 die(
2021 "ERROR(yac_read_scrip_basic_grid_parallel_f2c): "
2022 "YAC is built without the NetCDF support");
2023 return NULL;
2024}
2025
2027 char const * grid_filename, char const * mask_filename,
2028 MPI_Fint comm, char const * grid_name, int valid_mask_value,
2029 char const * name, size_t * vertex_coord_idx,
2030 size_t ** duplicated_vertex_idx, yac_int ** orig_vertex_global_ids,
2031 size_t * nbr_duplicated_vertices) {
2032
2033 UNUSED(grid_filename);
2034 UNUSED(mask_filename);
2035 UNUSED(comm);
2036 UNUSED(grid_name);
2037 UNUSED(valid_mask_value);
2038 UNUSED(name);
2039 UNUSED(vertex_coord_idx);
2040 UNUSED(duplicated_vertex_idx);
2041 UNUSED(orig_vertex_global_ids);
2042 UNUSED(nbr_duplicated_vertices);
2043 die(
2044 "ERROR(yac_read_scrip_cloud_basic_grid_parallel_f2c): "
2045 "YAC is built without the NetCDF support");
2046 return NULL;
2047}
2048
2050 char const * grid_filename, char const * mask_filename,
2051 MPI_Fint comm, char const * grid_name, int valid_mask_value,
2052 char const * name, int use_ll_edges, size_t * point_coord_idx,
2053 size_t ** duplicated_point_idx, yac_int ** orig_point_global_ids,
2054 size_t * nbr_duplicated_points, int * point_location) {
2055
2056 UNUSED(grid_filename);
2057 UNUSED(mask_filename);
2058 UNUSED(comm);
2059 UNUSED(grid_name);
2060 UNUSED(valid_mask_value);
2061 UNUSED(name);
2062 UNUSED(use_ll_edges);
2063 UNUSED(point_coord_idx);
2064 UNUSED(duplicated_point_idx);
2065 UNUSED(orig_point_global_ids);
2066 UNUSED(nbr_duplicated_points);
2067 UNUSED(point_location);
2068 die(
2069 "ERROR(yac_read_scrip_generic_basic_grid_parallel_f2c): "
2070 "YAC is built without the NetCDF support");
2071 return NULL;
2072}
2073
2074#endif // YAC_NETCDF_ENABLED
#define YAC_ASSERT(exp, msg)
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
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
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_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_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(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
#define UNUSED(x)
Definition core.h:72
#define YAC_RAD
struct @23::@24 value
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_inq_varid(int ncid, char const *name, int *varidp)
Definition io_utils.c:369
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:311
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_CELL
Definition location.h:14
void yac_mergesort(void *base, size_t num, size_t size, int(*compar)(const void *, const void *))
Definition mergesort.c:134
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct yac_basic_grid * yac_read_scrip_cloud_basic_grid_parallel_f2c(char const *grid_filename, char const *mask_filename, MPI_Fint comm, char const *grid_name, int valid_mask_value, char const *name, size_t *vertex_coord_idx, size_t **duplicated_vertex_idx, yac_int **orig_vertex_global_ids, size_t *nbr_duplicated_vertices)
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)
unsigned long djb2_hash(unsigned char *values, size_t count)
static void yac_read_part_scrip_grid_information(char const *grid_filename, char const *mask_filename, MPI_Comm comm, char const *grid_name, int valid_mask_value, size_t *num_vertices, size_t *num_cells, int **num_vertices_per_cell, double **x_vertices, double **y_vertices, yac_int **vertex_ids, double **x_cells, double **y_cells, yac_int **cell_ids, int **cell_to_vertex, int **cell_core_mask, size_t **duplicated_cell_idx, yac_int **orig_cell_ids, size_t *nbr_duplicated_cells, int with_vertices)
static void yac_read_part_scrip_basic_grid_information(const char *filename, const char *grid_name, size_t cell_mask_size, int *cell_mask, size_t *num_vertices_, size_t *num_cells_, int **num_vertices_per_cell_, int **cell_to_vertex_, double **x_vertices_, double **y_vertices_, yac_int **vertex_ids_, double **x_cells_, double **y_cells_, yac_int **cell_ids_, size_t **duplicated_cell_idx_, yac_int **orig_cell_ids_, size_t *nbr_duplicated_cells_, int io_rank_idx, int num_io_ranks, MPI_Comm comm, int with_vertices)
struct yac_basic_grid_data yac_read_scrip_basic_grid_data(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value, int use_ll_edges)
static void yac_read_scrip_basic_grid_information(const char *filename, const char *grid_name, size_t cell_mask_size, int *cell_mask, size_t *num_vertices_, size_t *num_cells_, int **num_vertices_per_cell_, int **cell_to_vertex_, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, size_t **duplicated_cell_idx_, size_t **orig_cell_idx_, size_t *nbr_duplicated_cells_, int with_vertices)
static int compare_point_with_index_coord_id(const void *a_, const void *b_)
static void yac_read_part_scrip_mask_information(const char *filename, const char *grid_name, size_t *num_cells_, int **cell_mask, int io_rank_idx, int num_io_ranks)
void yac_read_scrip_grid_information(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value, size_t *num_vertices, size_t *num_cells, int **num_vertices_per_cell, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **cell_to_vertex, int **cell_core_mask, size_t **duplicated_cell_idx, size_t **orig_cell_idx, size_t *nbr_duplicated_cells)
static void yac_read_scrip_mask_information(const char *filename, const char *grid_name, size_t *num_cells_, int **cell_mask)
static int compare_cell_vertices_with_index(const void *a, const void *b)
static void detect_duplicated_cells_parallel(int *cell_to_vertex, int *num_vertices_per_cell, int *cell_mask, yac_int *cell_ids, size_t num_cells, yac_int *vertex_ids, MPI_Comm comm, size_t **duplicated_cell_idx, yac_int **orig_cell_ids, size_t *num_duplicated_cells_)
static MPI_Datatype get_point_with_index_mpi_datatype(MPI_Comm comm)
struct yac_basic_grid * yac_read_scrip_generic_basic_grid_parallel_f2c(char const *grid_filename, char const *mask_filename, MPI_Fint comm, char const *grid_name, int valid_mask_value, char const *name, int use_ll_edges, size_t *point_coord_idx, size_t **duplicated_point_idx, yac_int **orig_point_global_ids, size_t *nbr_duplicated_points, int *point_location)
static void remove_duplicated_vertices_parallel(double **vertex_lon, double **vertex_lat, size_t *nbr_vertices, int *old_to_new_id, yac_int **vertex_ids, MPI_Comm comm)
struct yac_basic_grid_data yac_read_scrip_cloud_basic_grid_data(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value)
static struct point_with_index * remove_duplicated_vertices_(double **vertex_lon, double **vertex_lat, yac_int **vertex_ids, size_t *nbr_vertices, int *old_to_new_id)
struct yac_basic_grid * yac_read_scrip_cloud_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, size_t *vertex_coord_idx, size_t **duplicated_vertex_idx, yac_int **orig_vertex_global_ids, size_t *nbr_duplicated_vertices)
struct yac_basic_grid * yac_read_scrip_cloud_basic_grid(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value, char const *name, size_t *vertex_coord_idx, size_t **duplicated_vertex_idx, yac_int **orig_vertex_global_ids, size_t *nbr_duplicated_vertices)
struct yac_basic_grid * yac_read_scrip_generic_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 *point_coord_idx, size_t **duplicated_point_idx, yac_int **orig_point_global_ids, size_t *nbr_duplicated_points, int *point_location)
static int check_corner_information(char const *grid_filename, MPI_Comm comm, char const *grid_name)
static int compare_cell_vertex_ids_with_index_ids_id(const void *a_, const void *b_)
static int compute_bucket(void *data, size_t data_size, int comm_size)
struct yac_basic_grid * yac_read_scrip_basic_grid_parallel_f2c(char const *grid_filename, char const *mask_filename, MPI_Fint 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)
static struct yac_basic_grid_data yac_read_scrip_basic_grid_data_(char const *grid_filename, char const *mask_filename, MPI_Comm comm, char const *grid_name, int valid_mask_value, int use_ll, double **x_cells, double **y_cells, size_t **duplicated_cell_idx, yac_int **orig_cell_global_ids, size_t *nbr_duplicated_cells)
static int compare_yac_int(const void *a, const void *b)
static int compare_point_with_index_rank(const void *a_, const void *b_)
static void detect_duplicated_cells(int *cell_to_vertex, int *num_vertices_per_cell, int *cell_mask, size_t nbr_cells, size_t **duplicated_cell_idx, size_t **orig_cell_idx, size_t *nbr_duplicated_cells)
static MPI_Datatype get_cell_to_vertex_ids_mpi_datatype(MPI_Comm comm, size_t count)
static int compare_cell_vertex_ids_with_index_ids(const void *a_, const void *b_)
static int get_io_configuration(MPI_Comm comm, int *io_rank_idx, int *num_io_ranks)
static int compare_point_with_index_i(const void *a_, const void *b_)
static struct yac_basic_grid_data yac_read_scrip_cloud_basic_grid_data_(char const *grid_filename, char const *mask_filename, MPI_Comm comm, char const *grid_name, int valid_mask_value, size_t **duplicated_vertex_idx, yac_int **orig_vertex_global_ids, size_t *nbr_duplicated_vertices)
static int compare_int(const void *a, const void *b)
static void yac_read_scrip_grid_information_(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value, size_t *num_vertices, size_t *num_cells, int **num_vertices_per_cell, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **cell_to_vertex, int **cell_core_mask, size_t **duplicated_cell_idx, size_t **orig_cell_idx, size_t *nbr_duplicated_cells, int with_vertices)
static void remove_duplicated_vertices(double **vertex_lon, double **vertex_lat, size_t *nbr_vertices, int *old_to_new_id)
struct yac_basic_grid * yac_read_scrip_basic_grid(char const *grid_filename, char const *mask_filename, 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)
static int compare_point_with_index_coord(const void *a_, const void *b_)
yac_coordinate_pointer vertex_coordinates
int * cell_to_vertex
int * cell_mask
double * data
size_t num_cells[2]
double cell_coords[36][3]
int * cell_core_mask
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
char const * name
Definition toy_scrip.c:114
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
void yac_quicksort_index_size_t_int(size_t *a, size_t n, int *idx)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define die(msg)
Definition yac_assert.h:14
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
Definition yac_mpi.c:583
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:639
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
Definition yac_mpi.c:608
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:562
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const *caller, int line)
Definition yac_mpi.c:129
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T
YAC_INT yac_int
Definition yac_types.h:15
#define yac_int_dt
Definition yac_types.h:18
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21