YetAnotherCoupler 3.2.0_a
Loading...
Searching...
No Matches
read_icon_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 <string.h>
12#include <assert.h>
13#include <math.h>
14
15#ifdef YAC_NETCDF_ENABLED
16#include <netcdf.h>
17#endif
18
19#include "read_icon_grid.h"
20#include "utils_common.h"
21#include "io_utils.h"
22#include "geometry.h"
23#include "read_grid.h"
24
25static int * get_icon_cell_mask( int ncid, size_t nbr_cells );
26static int * get_icon_connect(int ncid, size_t nbr_cells);
27
29 const char * filename, int * nbr_vertices, int * nbr_cells,
30 int ** num_vertices_per_cell, int ** cell_to_vertex,
31 double ** x_vertices, double ** y_vertices,
32 double ** x_cells, double ** y_cells, int ** global_cell_id,
33 int ** cell_mask, int ** cell_core_mask,
34 int ** global_corner_id, int ** corner_core_mask, int rank, int size) {
35
36 // read the global grid
38 filename, nbr_vertices, nbr_cells, num_vertices_per_cell, cell_to_vertex,
39 x_vertices, y_vertices, x_cells, y_cells, cell_mask);
40
41 // determine local range
42 int local_start =
43 ((unsigned long)(*nbr_cells) * (unsigned long)rank) /
44 (unsigned long)size;
45 int num_local_cells =
46 ((unsigned long)(*nbr_cells) * ((unsigned long)rank+1)) /
47 (unsigned long)size - (unsigned long)local_start;
48
49 // mask for required vertices and cells
50 int * required_vertices = xcalloc(*nbr_vertices, sizeof(*required_vertices));
51 int * required_cells = xcalloc(*nbr_cells, sizeof(*required_cells));
52
53 int offset = 0;
54 for (int i = 0; i < local_start; ++i)
55 offset += (*num_vertices_per_cell)[i];
56
57 // mark all local cells and their vertices as required
58 for (int i = local_start; i < local_start + num_local_cells; ++i) {
59
60 required_cells[i] = 2;
61 for (int j = 0; j < (*num_vertices_per_cell)[i]; ++j)
62 required_vertices[(*cell_to_vertex)[offset+j]] = 2;
63
64 offset += (*num_vertices_per_cell)[i];
65 }
66
67 // mark all halo cells as required
68 offset = 0;
69 for (int i = 0; i < *nbr_cells; ++i) {
70
71 if (!required_cells[i]) {
72
73 for (int j = 0; j < (*num_vertices_per_cell)[i]; ++j) {
74
75 if (required_vertices[(*cell_to_vertex)[offset+j]]) {
76
77 required_cells[i] = 1;
78 break;
79 }
80 }
81
82 }
83
84 offset += (*num_vertices_per_cell)[i];
85 }
86
87 // mark all halo vertices as required
88 offset = 0;
89 for (int i = 0; i < *nbr_cells; ++i) {
90
91 if (required_cells[i] == 1) {
92
93 for (int j = 0; j < (*num_vertices_per_cell)[i]; ++j) {
94
95 if (!required_vertices[(*cell_to_vertex)[offset+j]]) {
96
97 required_vertices[(*cell_to_vertex)[offset+j]] = 1;
98 }
99 }
100 }
101
102 offset += (*num_vertices_per_cell)[i];
103 }
104
105 // count the number of cells and vertices
106 int part_num_vertices = 0;
107 int part_num_cells = 0;
108 for (int i = 0; i < *nbr_vertices; ++i)
109 if (required_vertices[i])
110 part_num_vertices++;
111 for (int i = 0; i < *nbr_cells; ++i)
112 if(required_cells[i])
113 part_num_cells++;
114
115 *global_cell_id = xmalloc(part_num_cells * sizeof(**global_cell_id));
116 *cell_core_mask = xmalloc(part_num_cells * sizeof(**cell_core_mask));
117 *global_corner_id = xmalloc(part_num_vertices * sizeof(**global_corner_id));
118 *corner_core_mask = xmalloc(part_num_vertices * sizeof(**corner_core_mask));
119
120 // generate final vertex data
121 part_num_vertices = 0;
122 int * global_to_local_vertex =
123 xmalloc(*nbr_vertices * sizeof(*global_to_local_vertex));
124 for (int i = 0; i < *nbr_vertices; ++i) {
125
126 if (required_vertices[i]) {
127
128 (*global_corner_id)[part_num_vertices] = i;
129 (*corner_core_mask)[part_num_vertices] = required_vertices[i] == 2;
130 (*x_vertices)[part_num_vertices] = (*x_vertices)[i];
131 (*y_vertices)[part_num_vertices] = (*y_vertices)[i];
132 global_to_local_vertex[i] = part_num_vertices;
133 part_num_vertices++;
134 }
135 }
136
137 *x_vertices = xrealloc(*x_vertices, part_num_vertices * sizeof(**x_vertices));
138 *y_vertices = xrealloc(*y_vertices, part_num_vertices * sizeof(**y_vertices));
139 *nbr_vertices = part_num_vertices;
140 free(required_vertices);
141
142 // generate final cell data
143 int num_cell_vertex_dependencies = 0;
144 part_num_cells = 0;
145 offset = 0;
146 for (int i = 0; i < *nbr_cells; ++i) {
147
148 if (required_cells[i]) {
149
150 (*global_cell_id)[part_num_cells] = i;
151 (*cell_core_mask)[part_num_cells] = required_cells[i] == 2;
152 (*x_cells)[part_num_cells] = (*x_cells)[i];
153 (*y_cells)[part_num_cells] = (*y_cells)[i];
154 (*cell_mask)[part_num_cells] = (*cell_mask)[i];
155
156 for (int j = 0; j < (*num_vertices_per_cell)[i]; ++j)
157 (*cell_to_vertex)[num_cell_vertex_dependencies++] =
158 global_to_local_vertex[(*cell_to_vertex)[offset+j]];
159
160 (*num_vertices_per_cell)[part_num_cells] = (*num_vertices_per_cell)[i];
161
162 part_num_cells++;
163 }
164
165 offset += (*num_vertices_per_cell)[i];
166 }
167
168 *x_cells = xrealloc(*x_cells, part_num_cells * sizeof(**x_cells));
169 *y_cells = xrealloc(*y_cells, part_num_cells * sizeof(**y_cells));
170 *cell_mask = xrealloc(*cell_mask, part_num_cells * sizeof(**cell_mask));
171
172 *num_vertices_per_cell = xrealloc(*num_vertices_per_cell, part_num_cells *
173 sizeof(**num_vertices_per_cell));
174 *cell_to_vertex = xrealloc(*cell_to_vertex, num_cell_vertex_dependencies *
175 sizeof(**cell_to_vertex));
176 *nbr_cells = part_num_cells;
177 free(required_cells);
178 free(global_to_local_vertex);
179}
180
181void yac_read_icon_grid_information(const char * filename, int * nbr_vertices,
182 int * nbr_cells, int ** num_vertices_per_cell,
183 int ** cell_to_vertex, double ** x_vertices,
184 double ** y_vertices, double ** x_cells,
185 double ** y_cells, int ** cell_mask) {
186
187#ifndef YAC_NETCDF_ENABLED
188
189 UNUSED(filename);
190 UNUSED(nbr_vertices);
191 UNUSED(nbr_cells);
192 UNUSED(num_vertices_per_cell);
193 UNUSED(cell_to_vertex);
194 UNUSED(x_vertices);
195 UNUSED(y_vertices);
196 UNUSED(x_cells);
197 UNUSED(y_cells);
198 UNUSED(cell_mask);
199 die(
200 "ERROR(yac_read_icon_grid_information): "
201 "YAC is built without the NetCDF support");
202#else
203
204 /* Open file */
205 int ncid;
206 yac_nc_open(filename, NC_NOWRITE, &ncid);
207
208 /* Get vertex longitudes and latitudes of cells */
209 size_t nbr_vertices_;
211 ncid, "vlon", "vlat", x_vertices, y_vertices, &nbr_vertices_);
212 *nbr_vertices = (int)nbr_vertices_;
213
214 /* Get cell center longitudes and latitudes of cells */
215 size_t nbr_cells_;
216 yac_read_coords(ncid, "clon", "clat", x_cells, y_cells, &nbr_cells_);
217 *nbr_cells = (int)nbr_cells_;
218
219 /* Get mask of cells */
220 *cell_mask = get_icon_cell_mask ( ncid, *nbr_cells );
221
222 /* Get relations between vertices and cells */
223 int * vertex_of_cell = get_icon_connect(ncid, *nbr_cells);
224
225 /* Close file */
226 YAC_HANDLE_ERROR(nc_close(ncid));
227
228 //-------------------------------------------------------------------------//
229
230 *num_vertices_per_cell = xmalloc(*nbr_cells * sizeof(**num_vertices_per_cell));
231 for (int i = 0; i < *nbr_cells; (*num_vertices_per_cell)[i++] = 3);
232
233 *cell_to_vertex = xmalloc(*nbr_cells * 3 * sizeof(**cell_to_vertex));
234
235 // Unfortunately the data is only available in Fortran order
236 for (int i = 0; i < *nbr_cells; ++i) {
237
238 (*cell_to_vertex)[3*i+0] = vertex_of_cell[i+0*(*nbr_cells)] - 1;
239 (*cell_to_vertex)[3*i+1] = vertex_of_cell[i+1*(*nbr_cells)] - 1;
240 (*cell_to_vertex)[3*i+2] = vertex_of_cell[i+2*(*nbr_cells)] - 1;
241 }
242
243 free(vertex_of_cell);
244#endif
245}
246
247// taken from scales-ppm library
248// https://www.dkrz.de/redmine/projects/scales-ppm
249static inline int
250partition_idx_from_element_idx(unsigned element_idx, unsigned num_elements,
251 int num_partitions) {
252
253 return (int)((((unsigned long)element_idx) * ((unsigned long)num_partitions) +
254 (unsigned long)num_partitions - 1) /
255 ((unsigned long)num_elements));
256}
257
258static void convert_to_rad(int ncid, int varid, double * array, size_t count) {
259
260 if (yac_check_coord_units(ncid, varid))
261 for (size_t i = 0; i < count; ++i) array[i] *= YAC_RAD;
262}
263
265 const char * filename, MPI_Comm comm, int * nbr_vertices, int * nbr_cells,
266 int ** num_vertices_per_cell, int ** cell_to_vertex, int ** global_cell_ids,
267 int ** cell_owner, int ** global_vertex_ids, int ** vertex_owner,
268 double ** x_vertices, double ** y_vertices,
269 double ** x_cells, double ** y_cells, int ** cell_msk) {
270
271#ifndef YAC_NETCDF_ENABLED
272
273 UNUSED(filename);
274 UNUSED(comm);
275 UNUSED(nbr_vertices);
276 UNUSED(nbr_cells);
277 UNUSED(num_vertices_per_cell);
278 UNUSED(cell_to_vertex);
279 UNUSED(global_cell_ids);
280 UNUSED(cell_owner);
281 UNUSED(global_vertex_ids);
282 UNUSED(vertex_owner);
283 UNUSED(x_vertices);
284 UNUSED(y_vertices);
285 UNUSED(x_cells);
286 UNUSED(y_cells);
287 UNUSED(cell_msk);
288 die(
289 "ERROR(yac_read_icon_grid_information_parallel): "
290 "YAC is built without the NetCDF support");
291#else
292
293 int comm_rank, comm_size;
294
295 MPI_Comm_rank(comm, &comm_rank);
296 MPI_Comm_size(comm, &comm_size);
297
298 int local_is_io, * io_ranks, num_io_ranks;
299 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
300
301 size_t ncells, nvertices;
302
303 size_t read_local_start_cell = 0;
304 size_t read_num_local_cells = 0;
305 size_t read_local_start_vertex = 0;
306 size_t read_num_local_vertices = 0;
307 double * read_cell_lon = NULL;
308 double * read_cell_lat = NULL;
309 int * read_cell_mask = NULL;
310 double * read_vertex_lon = NULL;
311 double * read_vertex_lat = NULL;
312 int * read_dist_vertex_of_cell = NULL;
313 int * read_dist_cells_of_vertex = NULL;
314
315 if (local_is_io) {
316
317 unsigned long io_proc_idx = ULONG_MAX;
318 for (int i = 0; (i < num_io_ranks) && (io_proc_idx == ULONG_MAX); ++i)
319 if (io_ranks[i] == comm_rank)
320 io_proc_idx = (unsigned long)i;
321
322 // open file
323 int ncid;
324 yac_nc_open(filename, NC_NOWRITE, &ncid);
325
326 // get number of cells and vertices
327 int dim_id;
328 yac_nc_inq_dimid(ncid, "cell", &dim_id);
329 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &ncells));
330 yac_nc_inq_dimid(ncid, "vertex", &dim_id);
331 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &nvertices));
332
333 // determine local range for cell and vertex data
334 read_local_start_cell =
335 ((unsigned long)ncells * io_proc_idx) / (unsigned long)num_io_ranks;
336 read_num_local_cells =
337 ((unsigned long)ncells * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
338 (unsigned long)read_local_start_cell;
339 read_local_start_vertex =
340 ((unsigned long)nvertices * io_proc_idx) / (unsigned long)num_io_ranks;
341 read_num_local_vertices =
342 ((unsigned long)nvertices * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
343 (unsigned long)read_local_start_vertex;
344
345 // read basic grid data (each process its individual part)
346 read_cell_lon = xmalloc(read_num_local_cells * sizeof(*read_cell_lon));
347 read_cell_lat = xmalloc(read_num_local_cells * sizeof(*read_cell_lat));
348 read_cell_mask = xmalloc(read_num_local_cells * sizeof(*read_cell_mask));
349 read_vertex_lon = xmalloc(read_num_local_vertices * sizeof(*read_vertex_lon));
350 read_vertex_lat = xmalloc(read_num_local_vertices * sizeof(*read_vertex_lat));
351 read_dist_vertex_of_cell =
352 xmalloc(read_num_local_cells * 3 * sizeof(*read_dist_vertex_of_cell));
353 read_dist_cells_of_vertex =
354 xmalloc(read_num_local_vertices * 6 * sizeof(*read_dist_cells_of_vertex));
355 int varid;
356 yac_nc_inq_varid(ncid, "clon", &varid);
357 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_cell,
358 &read_num_local_cells, read_cell_lon));
359 convert_to_rad(ncid, varid, read_cell_lon, read_num_local_cells);
360 yac_nc_inq_varid(ncid, "clat", &varid);
361 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_cell,
362 &read_num_local_cells, read_cell_lat));
363 convert_to_rad(ncid, varid, read_cell_lat, read_num_local_cells);
364 yac_nc_inq_varid(ncid, "cell_sea_land_mask", &varid);
365 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, &read_local_start_cell,
366 &read_num_local_cells, read_cell_mask));
367 yac_nc_inq_varid(ncid, "vlon", &varid);
368 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_vertex,
369 &read_num_local_vertices, read_vertex_lon));
370 convert_to_rad(ncid, varid, read_vertex_lon, read_num_local_vertices);
371 yac_nc_inq_varid(ncid, "vlat", &varid);
372 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_vertex,
373 &read_num_local_vertices, read_vertex_lat));
374 convert_to_rad(ncid, varid, read_vertex_lat, read_num_local_vertices);
375 {
376 int * buffer = xmalloc(MAX(3*read_num_local_cells,
377 6*read_num_local_vertices) * sizeof(*buffer));
378 {
379 size_t tmp_start[2] = {0, read_local_start_cell};
380 size_t tmp_count[2] = {3, read_num_local_cells};
381 yac_nc_inq_varid(ncid, "vertex_of_cell", &varid);
382 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, tmp_start, tmp_count, buffer));
383 for (size_t i = 0; i < read_num_local_cells; ++i)
384 for (int j = 0; j < 3; ++j)
385 read_dist_vertex_of_cell[i * 3 + j] =
386 buffer[i + j * read_num_local_cells];
387 }
388 {
389 size_t tmp_start[2] = {0, read_local_start_vertex};
390 size_t tmp_count[2] = {6, read_num_local_vertices};
391 yac_nc_inq_varid(ncid, "cells_of_vertex", &varid);
392 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, tmp_start, tmp_count, buffer));
393 for (size_t i = 0; i < read_num_local_vertices; ++i)
394 for (int j = 0; j < 6; ++j)
395 read_dist_cells_of_vertex[i * 6 + j] =
396 buffer[i + j * read_num_local_vertices];
397 }
398 free(buffer);
399
400 // adjust for c indices
401 for (size_t i = 0; i < read_num_local_cells * 3; ++i)
402 if (read_dist_vertex_of_cell[i] > 0) read_dist_vertex_of_cell[i]--;
403 for (size_t i = 0; i < read_num_local_vertices * 6; ++i)
404 read_dist_cells_of_vertex[i]--;
405 }
406
407 YAC_HANDLE_ERROR(nc_close(ncid));
408 } else {
409 read_cell_lon = xmalloc(1 * sizeof(*read_cell_lon));
410 read_cell_lat = xmalloc(1 * sizeof(*read_cell_lat));
411 read_cell_mask = xmalloc(1 * sizeof(*read_cell_mask));
412 read_vertex_lon = xmalloc(1 * sizeof(*read_vertex_lon));
413 read_vertex_lat = xmalloc(1 * sizeof(*read_vertex_lat));
414 read_dist_vertex_of_cell = xmalloc(1 * sizeof(*read_dist_vertex_of_cell));
415 read_dist_cells_of_vertex = xmalloc(1 * sizeof(*read_dist_cells_of_vertex));
416 }
417
418 free(io_ranks);
419
420 {
421 int tmp;
422 if (comm_rank == 0) tmp = (int)ncells;
423 MPI_Bcast(&tmp, 1, MPI_INT, 0, comm);
424 ncells = (size_t)tmp;
425 if (comm_rank == 0) tmp = (int)nvertices;
426 MPI_Bcast(&tmp, 1, MPI_INT, 0, comm);
427 nvertices = (size_t)tmp;
428 }
429
430 // determine local range for cell and vertex data
431 size_t local_start_cell =
432 ((unsigned long)ncells * (unsigned long)comm_rank) /
433 (unsigned long)comm_size;
434 size_t num_local_cells =
435 ((unsigned long)ncells * ((unsigned long)comm_rank+1)) /
436 (unsigned long)comm_size - (unsigned long)local_start_cell;
437 size_t local_start_vertex =
438 ((unsigned long)nvertices * (unsigned long)comm_rank) /
439 (unsigned long)comm_size;
440 size_t num_local_vertices =
441 ((unsigned long)nvertices * ((unsigned long)comm_rank+1)) /
442 (unsigned long)comm_size - (unsigned long)local_start_vertex;
443
444 // redistribute basic cell data (from io decomposition)
445 double * cell_lon = xmalloc(num_local_cells * sizeof(*cell_lon));
446 double * cell_lat = xmalloc(num_local_cells * sizeof(*cell_lat));
447 int * cell_mask = xmalloc(num_local_cells * sizeof(*cell_mask));
448 int * dist_vertex_of_cell =
449 xmalloc(num_local_cells * 3 * sizeof(*dist_vertex_of_cell));
450 {
451 int * send_count = xcalloc(comm_size, sizeof(*send_count));
452 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
453
454 for (size_t i = 0; i < read_num_local_cells; ++i)
455 send_count[
457 read_local_start_cell + i, ncells, comm_size)]++;
458
459 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
460
461 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
462 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
463 int send_accum = 0, recv_accum = 0;
464 for (int i = 0; i < comm_size; ++i) {
465 send_displ[i] = send_accum;
466 recv_displ[i] = recv_accum;
467 send_accum += send_count[i];
468 recv_accum += recv_count[i];
469 }
470
471 MPI_Alltoallv(read_cell_lon, send_count, send_displ, MPI_DOUBLE,
472 cell_lon, recv_count, recv_displ, MPI_DOUBLE, comm);
473 MPI_Alltoallv(read_cell_lat, send_count, send_displ, MPI_DOUBLE,
474 cell_lat, recv_count, recv_displ, MPI_DOUBLE, comm);
475 MPI_Alltoallv(read_cell_mask, send_count, send_displ, MPI_INT,
476 cell_mask, recv_count, recv_displ, MPI_INT, comm);
477
478 for (int i = 0; i < comm_size; ++i) {
479 send_count[i] *= 3;
480 send_displ[i] *= 3;
481 recv_count[i] *= 3;
482 recv_displ[i] *= 3;
483 }
484
485 MPI_Alltoallv(read_dist_vertex_of_cell, send_count, send_displ, MPI_INT,
486 dist_vertex_of_cell, recv_count, recv_displ, MPI_INT, comm);
487
488 free(recv_displ);
489 free(send_displ);
490 free(recv_count);
491 free(send_count);
492 free(read_cell_lon);
493 free(read_cell_lat);
494 free(read_cell_mask);
495 free(read_dist_vertex_of_cell);
496 }
497
498 // redistribute basic vertex data (from io decomposition)
499 double * vertex_lon = xmalloc(num_local_vertices * sizeof(*vertex_lon));
500 double * vertex_lat = xmalloc(num_local_vertices * sizeof(*vertex_lat));
501 int * dist_cells_of_vertex =
502 xmalloc(num_local_vertices * 6 * sizeof(*dist_cells_of_vertex));
503 {
504 int * send_count = xcalloc(comm_size, sizeof(*send_count));
505 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
506
507 for (size_t i = 0; i < read_num_local_vertices; ++i)
508 send_count[
510 read_local_start_vertex + i, nvertices, comm_size)]++;
511
512 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
513
514 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
515 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
516 int send_accum = 0, recv_accum = 0;
517 for (int i = 0; i < comm_size; ++i) {
518 send_displ[i] = send_accum;
519 recv_displ[i] = recv_accum;
520 send_accum += send_count[i];
521 recv_accum += recv_count[i];
522 }
523
524 MPI_Alltoallv(read_vertex_lon, send_count, send_displ, MPI_DOUBLE,
525 vertex_lon, recv_count, recv_displ, MPI_DOUBLE, comm);
526 MPI_Alltoallv(read_vertex_lat, send_count, send_displ, MPI_DOUBLE,
527 vertex_lat, recv_count, recv_displ, MPI_DOUBLE, comm);
528
529 for (int i = 0; i < comm_size; ++i) {
530 send_count[i] *= 6;
531 send_displ[i] *= 6;
532 recv_count[i] *= 6;
533 recv_displ[i] *= 6;
534 }
535
536 MPI_Alltoallv(read_dist_cells_of_vertex, send_count, send_displ, MPI_INT,
537 dist_cells_of_vertex, recv_count, recv_displ, MPI_INT, comm);
538
539 free(recv_displ);
540 free(send_displ);
541 free(recv_count);
542 free(send_count);
543 free(read_vertex_lon);
544 free(read_vertex_lat);
545 free(read_dist_cells_of_vertex);
546 }
547
548 // determine required vertices for core cells
549 size_t num_core_vertices = num_local_cells * 3;
550 int * core_vertices = xmalloc(num_core_vertices * sizeof(*core_vertices));
551 {
552 memcpy(core_vertices, dist_vertex_of_cell,
553 num_core_vertices * sizeof(*core_vertices));
554 yac_quicksort_index(core_vertices, num_core_vertices, NULL);
555 yac_remove_duplicates_int(core_vertices, &num_core_vertices);
556 core_vertices =
557 xrealloc(core_vertices, num_core_vertices * sizeof(*core_vertices));
558 }
559
560 // get cells_of_vertex for core vertices and compute dist_vertex_owner
561 int * cells_of_vertex_core =
562 xmalloc(num_core_vertices * 6 * sizeof(*cells_of_vertex_core));
563 int * dist_vertex_owner =
564 xmalloc(num_local_vertices * sizeof(*dist_vertex_owner));
565 {
566 int * send_count = xcalloc(comm_size, sizeof(*send_count));
567 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
568
569 for (size_t i = 0; i < num_core_vertices; ++i)
570 send_count[((unsigned long)(core_vertices[i]) *
571 (unsigned long)comm_size + (unsigned long)comm_size - 1) /
572 (unsigned long)nvertices]++;
573
574 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
575
576 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
577 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
578 int send_accum = 0, recv_accum = 0;
579 for (int i = 0; i < comm_size; ++i) {
580 send_displ[i] = send_accum;
581 recv_displ[i] = recv_accum;
582 send_accum += send_count[i];
583 recv_accum += recv_count[i];
584 }
585
586 int num_core_vertices_remote = 0;
587 for (int i = 0; i < comm_size; ++i)
588 num_core_vertices_remote += recv_count[i];
589
590 int * remote_vertex_buffer =
591 xmalloc(num_core_vertices_remote * sizeof(*remote_vertex_buffer));
592
593 MPI_Alltoallv(core_vertices, send_count, send_displ, MPI_INT,
594 remote_vertex_buffer, recv_count, recv_displ, MPI_INT, comm);
595
596 for (size_t i = 0; i < num_local_vertices; ++i) dist_vertex_owner[i] = -1;
597
598 for (int i = 0, j = 0; i < comm_size; ++i)
599 for (int k = 0; k < recv_count[i]; ++k, ++j)
600 dist_vertex_owner[remote_vertex_buffer[j] - local_start_vertex] = i;
601
602 int * send_cell_of_vertex =
603 xmalloc(num_core_vertices_remote * 6 * sizeof(*send_cell_of_vertex));
604
605 for (int i = 0, l = 0, m = 0; i < comm_size; ++i) {
606 for (int j = 0; j < recv_count[i]; ++j, ++l) {
607 int idx = remote_vertex_buffer[l] - local_start_vertex;
608 for (int k = 0; k < 6; ++k, ++m)
609 send_cell_of_vertex[m] = dist_cells_of_vertex[idx * 6 + k];
610 }
611 }
612 free(dist_cells_of_vertex);
613
614 for (int i = 0; i < comm_size; ++i) {
615 send_count[i] *= 6;
616 send_displ[i] *= 6;
617 recv_count[i] *= 6;
618 recv_displ[i] *= 6;
619 }
620
621 MPI_Alltoallv(send_cell_of_vertex, recv_count, recv_displ, MPI_INT,
622 cells_of_vertex_core, send_count, send_displ, MPI_INT, comm);
623
624 free(send_cell_of_vertex);
625 free(remote_vertex_buffer);
626 free(recv_displ);
627 free(send_displ);
628 free(recv_count);
629 free(send_count);
630 }
631
632 // determine halo cells
633 int * halo_cells;
634 size_t num_halo_cells = 0;
635 {
636 int * tmp_cells = cells_of_vertex_core;
637 size_t num_tmp_cells = num_core_vertices * 6;
638
639 yac_quicksort_index(tmp_cells, num_tmp_cells, NULL);
640 yac_remove_duplicates_int(tmp_cells, &num_tmp_cells);
641
642 if ((num_tmp_cells > 0) && (tmp_cells[0] == -1)) {
643 num_tmp_cells--;
644 tmp_cells++;
645 }
646
647 halo_cells = xmalloc((num_tmp_cells - num_local_cells) * sizeof(*halo_cells));
648
649 size_t i = 0;
650 for (; i < num_tmp_cells && tmp_cells[i] < (int)local_start_cell; ++i)
651 halo_cells[num_halo_cells++] = tmp_cells[i];
652 i += num_local_cells;
653 for (; i < num_tmp_cells; ++i) halo_cells[num_halo_cells++] = tmp_cells[i];
654
655 assert(num_halo_cells == num_tmp_cells - num_local_cells);
656
657 free(cells_of_vertex_core);
658 }
659
660 // determine all vertices and get coordinates of halo cells
661 size_t num_all_local_vertices = num_halo_cells * 3 + num_core_vertices;
662 int * all_cell_to_vertex;
663 int * all_local_vertices = xrealloc(core_vertices, num_all_local_vertices *
664 sizeof(*all_local_vertices));
665 cell_lon = xrealloc(cell_lon, (num_local_cells + num_halo_cells) *
666 sizeof(*cell_lon));
667 cell_lat = xrealloc(cell_lat, (num_local_cells + num_halo_cells) *
668 sizeof(*cell_lat));
669 cell_mask = xrealloc(cell_mask, (num_local_cells + num_halo_cells) *
670 sizeof(*cell_mask));
671 {
672 int * send_count = xcalloc(comm_size, sizeof(*send_count));
673 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
674
675 for (size_t i = 0; i < num_halo_cells; ++i)
676 send_count[((unsigned long)(halo_cells[i]) *
677 (unsigned long)comm_size + (unsigned long)comm_size - 1) /
678 (unsigned long)ncells]++;
679
680 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
681
682 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
683 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
684 int send_accum = 0, recv_accum = 0;
685 for (int i = 0; i < comm_size; ++i) {
686 send_displ[i] = send_accum;
687 recv_displ[i] = recv_accum;
688 send_accum += send_count[i];
689 recv_accum += recv_count[i];
690 }
691
692 int num_halo_cells_remote = 0;
693 for (int i = 0; i < comm_size; ++i)
694 num_halo_cells_remote += recv_count[i];
695
696 int * remote_halo_cell_buffer =
697 xmalloc(num_halo_cells_remote * sizeof(*remote_halo_cell_buffer));
698
699 MPI_Alltoallv(halo_cells, send_count, send_displ, MPI_INT,
700 remote_halo_cell_buffer, recv_count, recv_displ, MPI_INT,
701 comm);
702
703 int * send_halo_cell_vertices =
704 xmalloc(num_halo_cells_remote * 3 * sizeof(*send_halo_cell_vertices));
705 double * send_cell_lon =
706 xmalloc(num_halo_cells_remote * sizeof(*send_cell_lon));
707 double * send_cell_lat =
708 xmalloc(num_halo_cells_remote * sizeof(*send_cell_lat));
709 int * send_cell_mask =
710 xmalloc(num_halo_cells_remote * sizeof(*send_cell_mask));
711
712 for (int i = 0, l = 0, m = 0; i < comm_size; ++i) {
713 for (int j = 0; j < recv_count[i]; ++j, ++l) {
714 int idx = remote_halo_cell_buffer[l] - local_start_cell;
715 for (int k = 0; k < 3; ++k, ++m)
716 send_halo_cell_vertices[m] = dist_vertex_of_cell[idx * 3 + k];
717 send_cell_lon[l] = cell_lon[idx];
718 send_cell_lat[l] = cell_lat[idx];
719 send_cell_mask[l] = cell_mask[idx];
720 }
721 }
722
723 MPI_Alltoallv(send_cell_lon, recv_count, recv_displ, MPI_DOUBLE,
724 cell_lon + num_local_cells, send_count, send_displ,
725 MPI_DOUBLE, comm);
726 MPI_Alltoallv(send_cell_lat, recv_count, recv_displ, MPI_DOUBLE,
727 cell_lat + num_local_cells, send_count, send_displ,
728 MPI_DOUBLE, comm);
729 MPI_Alltoallv(send_cell_mask, recv_count, recv_displ, MPI_INT,
730 cell_mask + num_local_cells, send_count, send_displ,
731 MPI_INT, comm);
732
733 for (int i = 0; i < comm_size; ++i) {
734 send_count[i] *= 3;
735 send_displ[i] *= 3;
736 recv_count[i] *= 3;
737 recv_displ[i] *= 3;
738 }
739
740 all_cell_to_vertex =
741 xrealloc(dist_vertex_of_cell, (num_local_cells + num_halo_cells) * 3 *
742 sizeof(*all_cell_to_vertex));
743
744 MPI_Alltoallv(send_halo_cell_vertices, recv_count, recv_displ, MPI_INT,
745 all_cell_to_vertex + num_local_cells * 3, send_count,
746 send_displ, MPI_INT, comm);
747
748 memcpy(all_local_vertices + num_core_vertices,
749 all_cell_to_vertex + num_local_cells * 3,
750 num_halo_cells * 3 * sizeof(*all_local_vertices));
751
752 free(send_cell_mask);
753 free(send_cell_lat);
754 free(send_cell_lon);
755 free(send_halo_cell_vertices);
756 free(remote_halo_cell_buffer);
757 free(recv_displ);
758 free(send_displ);
759 free(recv_count);
760 free(send_count);
761
763 all_local_vertices, num_all_local_vertices, NULL);
764 yac_remove_duplicates_int(all_local_vertices, &num_all_local_vertices);
765 }
766
767 // determine owner and coordinates for all vertices
768 double * all_vertex_lon =
769 xmalloc(num_all_local_vertices * sizeof(*all_vertex_lon));
770 double * all_vertex_lat =
771 xmalloc(num_all_local_vertices * sizeof(*all_vertex_lat));
772 int * all_local_vertices_owner =
773 xmalloc(num_all_local_vertices * sizeof(*all_local_vertices_owner));
774 {
775 int * send_count = xcalloc(comm_size, sizeof(*send_count));
776 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
777
778 for (size_t i = 0; i < num_all_local_vertices; ++i)
779 send_count[((unsigned long)(all_local_vertices[i]) *
780 (unsigned long)comm_size + (unsigned long)comm_size - 1) /
781 (unsigned long)nvertices]++;
782
783 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
784
785 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
786 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
787 int send_accum = 0, recv_accum = 0;
788 for (int i = 0; i < comm_size; ++i) {
789 send_displ[i] = send_accum;
790 recv_displ[i] = recv_accum;
791 send_accum += send_count[i];
792 recv_accum += recv_count[i];
793 }
794
795 int num_all_local_vertices_remote = 0;
796 for (int i = 0; i < comm_size; ++i)
797 num_all_local_vertices_remote += recv_count[i];
798
799 int * remote_vertex_buffer =
800 xmalloc(num_all_local_vertices_remote * sizeof(*remote_vertex_buffer));
801
802 MPI_Alltoallv(all_local_vertices, send_count, send_displ, MPI_INT,
803 remote_vertex_buffer, recv_count, recv_displ, MPI_INT, comm);
804
805 int * send_vertex_owner = remote_vertex_buffer;
806 double * send_vertex_lon =
807 xmalloc(num_all_local_vertices_remote * sizeof(*send_vertex_lon));
808 double * send_vertex_lat =
809 xmalloc(num_all_local_vertices_remote * sizeof(*send_vertex_lat));
810
811 for (int i = 0, l = 0; i < comm_size; ++i) {
812 for (int j = 0; j < recv_count[i]; ++j, ++l) {
813 int idx = remote_vertex_buffer[l] - local_start_vertex;
814 send_vertex_owner[l] = dist_vertex_owner[idx];
815 send_vertex_lon[l] = vertex_lon[idx];
816 send_vertex_lat[l] = vertex_lat[idx];
817 }
818 }
819
820 free(dist_vertex_owner);
821 free(vertex_lon);
822 free(vertex_lat);
823
824 MPI_Alltoallv(send_vertex_owner, recv_count, recv_displ, MPI_INT,
825 all_local_vertices_owner, send_count, send_displ, MPI_INT,
826 comm);
827 MPI_Alltoallv(send_vertex_lon, recv_count, recv_displ, MPI_DOUBLE,
828 all_vertex_lon, send_count, send_displ, MPI_DOUBLE, comm);
829 MPI_Alltoallv(send_vertex_lat, recv_count, recv_displ, MPI_DOUBLE,
830 all_vertex_lat, send_count, send_displ, MPI_DOUBLE, comm);
831
832 free(send_vertex_lat);
833 free(send_vertex_lon);
834 free(send_vertex_owner);
835 free(recv_displ);
836 free(send_displ);
837 free(recv_count);
838 free(send_count);
839 }
840
841 // convert global ids within all_cell_to_vertex into local ids
842 {
843 size_t vertex_count = 3 * (num_local_cells + num_halo_cells);
844 int * permutation = xmalloc(vertex_count * sizeof(*permutation));
845 for (size_t i = 0; i < vertex_count; ++i) permutation[i] = (int)i;
846
847 yac_quicksort_index(all_cell_to_vertex, vertex_count, permutation);
848
849 for (size_t i = 0, j = 0; i < vertex_count; ++i) {
850 while (all_local_vertices[j] != all_cell_to_vertex[i]) ++j;
851 all_cell_to_vertex[i] = (int)j;
852 }
853
854 yac_quicksort_index(permutation, vertex_count, all_cell_to_vertex);
855 free(permutation);
856 }
857
858 *nbr_vertices = num_all_local_vertices;
859 *nbr_cells = num_local_cells + num_halo_cells;
860
861 *num_vertices_per_cell =
862 xmalloc((num_local_cells + num_halo_cells) * sizeof(**num_vertices_per_cell));
863 for (size_t i = 0; i < num_local_cells + num_halo_cells; ++i)
864 (*num_vertices_per_cell)[i] = 3;
865
866 *cell_to_vertex = all_cell_to_vertex;
867
868 *global_cell_ids =
869 xmalloc((num_local_cells + num_halo_cells) * sizeof(**global_cell_ids));
870 for (size_t i = 0; i < num_local_cells; ++i)
871 (*global_cell_ids)[i] = local_start_cell + i;
872 memcpy(*global_cell_ids + num_local_cells, halo_cells,
873 num_halo_cells * sizeof(*halo_cells));
874 *global_vertex_ids = xrealloc(all_local_vertices, num_all_local_vertices *
875 sizeof(*all_local_vertices));
876
877 *cell_owner =
878 xmalloc((num_local_cells + num_halo_cells) * sizeof(**cell_owner));
879 for (size_t i = 0; i < num_local_cells; ++i)
880 (*cell_owner)[i] = -1;
881 for (size_t i = 0; i < num_halo_cells; ++i)
882 (*cell_owner)[num_local_cells + i] =
883 ((unsigned long)(halo_cells[i]) * (unsigned long)comm_size +
884 (unsigned long)comm_size - 1) / (unsigned long)ncells;
885 free(halo_cells);
886
887 for (size_t i = 0; i < num_all_local_vertices; ++i)
888 if (all_local_vertices_owner[i] == comm_rank)
889 all_local_vertices_owner[i] = -1;
890 *vertex_owner = all_local_vertices_owner;
891
892 *x_vertices = all_vertex_lon;
893 *y_vertices = all_vertex_lat;
894 *x_cells = cell_lon;
895 *y_cells = cell_lat;
896 *cell_msk = cell_mask;
897#endif
898}
899
901 const char * filename, MPI_Fint comm, int * nbr_vertices, int * nbr_cells,
902 int ** num_vertices_per_cell, int ** cell_to_vertex, int ** global_cell_ids,
903 int ** cell_owner, int ** global_vertex_ids, int ** vertex_owner,
904 double ** x_vertices, double ** y_vertices,
905 double ** x_cells, double ** y_cells, int ** cell_msk) {
906
908 filename, MPI_Comm_f2c(comm), nbr_vertices, nbr_cells,
909 num_vertices_per_cell, cell_to_vertex, global_cell_ids,
910 cell_owner, global_vertex_ids, vertex_owner,
911 x_vertices, y_vertices, x_cells, y_cells, cell_msk);
912}
913
914static int * generate_simple_core_mask(size_t N) {
915 int * mask = xmalloc(N * sizeof(*mask));
916 for (size_t i = 0; i < N; ++i) mask[i] = 1;
917 return mask;
918}
919
920static size_t * generate_offsets(size_t N, int * counts) {
921
922 size_t * offsets = xmalloc(N * sizeof(*offsets));
923 for (size_t i = 0, accu = 0; i < N; ++i) {
924 offsets[i] = accu;
925 accu += (size_t)(counts[i]);
926 }
927 return offsets;
928}
929
931 const char * filename, MPI_Comm comm) {
932
933#ifndef YAC_NETCDF_ENABLED
934
935 UNUSED(filename);
936 UNUSED(comm);
937 die(
938 "ERROR(yac_read_icon_basic_grid_data_parallel): "
939 "YAC is built without the NetCDF support");
940#else
941
942 int comm_rank, comm_size;
943
944 MPI_Comm_rank(comm, &comm_rank);
945 MPI_Comm_size(comm, &comm_size);
946
947 int local_is_io, * io_ranks, num_io_ranks;
948 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
949
950 size_t ncells, nvertices, nedges;
951
952 size_t read_local_start_cell = 0;
953 size_t read_num_local_cells = 0;
954 size_t read_local_start_vertex = 0;
955 size_t read_num_local_vertices = 0;
956 size_t read_local_start_edge = 0;
957 size_t read_num_local_edges = 0;
958 double * read_vertex_lon = NULL;
959 double * read_vertex_lat = NULL;
960 int * read_dist_vertex_of_cell = NULL;
961 int * read_dist_edge_of_cell = NULL;
962 int * read_dist_edge_vertices = NULL;
963
964 if (local_is_io) {
965
966 unsigned long io_proc_idx = ULONG_MAX;
967 for (int i = 0; (i < num_io_ranks) && (io_proc_idx == ULONG_MAX); ++i)
968 if (io_ranks[i] == comm_rank)
969 io_proc_idx = (unsigned long)i;
970
971 // open file
972 int ncid;
973 yac_nc_open(filename, NC_NOWRITE, &ncid);
974
975 // get number of cells and vertices
976 int dim_id;
977 yac_nc_inq_dimid(ncid, "cell", &dim_id);
978 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &ncells));
979 yac_nc_inq_dimid(ncid, "vertex", &dim_id);
980 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &nvertices));
981 yac_nc_inq_dimid(ncid, "edge", &dim_id);
982 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &nedges));
983
984 // determine local range for cell and vertex data
985 read_local_start_cell =
986 ((unsigned long)ncells * io_proc_idx) / (unsigned long)num_io_ranks;
987 read_num_local_cells =
988 ((unsigned long)ncells * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
989 (unsigned long)read_local_start_cell;
990 read_local_start_vertex =
991 ((unsigned long)nvertices * io_proc_idx) / (unsigned long)num_io_ranks;
992 read_num_local_vertices =
993 ((unsigned long)nvertices * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
994 (unsigned long)read_local_start_vertex;
995 read_local_start_edge =
996 ((unsigned long)nedges * io_proc_idx) / (unsigned long)num_io_ranks;
997 read_num_local_edges =
998 ((unsigned long)nedges * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
999 (unsigned long)read_local_start_edge;
1000
1001 // read basic grid data (each process its individual part)
1002 read_vertex_lon = xmalloc(read_num_local_vertices * sizeof(*read_vertex_lon));
1003 read_vertex_lat = xmalloc(read_num_local_vertices * sizeof(*read_vertex_lat));
1004 read_dist_vertex_of_cell =
1005 xmalloc(read_num_local_cells * 3 * sizeof(*read_dist_vertex_of_cell));
1006 read_dist_edge_of_cell =
1007 xmalloc(read_num_local_cells * 3 * sizeof(*read_dist_edge_of_cell));
1008 read_dist_edge_vertices =
1009 xmalloc(read_num_local_edges * 2 * sizeof(*read_dist_edge_vertices));
1010 int varid;
1011 yac_nc_inq_varid(ncid, "vlon", &varid);
1012 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_vertex,
1013 &read_num_local_vertices, read_vertex_lon));
1014 convert_to_rad(ncid, varid, read_vertex_lon, read_num_local_vertices);
1015 yac_nc_inq_varid(ncid, "vlat", &varid);
1016 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, varid, &read_local_start_vertex,
1017 &read_num_local_vertices, read_vertex_lat));
1018 convert_to_rad(ncid, varid, read_vertex_lat, read_num_local_vertices);
1019 {
1020 int * buffer =
1021 xmalloc(
1022 MAX(3*read_num_local_cells, 2*read_num_local_edges) *
1023 sizeof(*buffer));
1024 {
1025 size_t tmp_start[2] = {0, read_local_start_cell};
1026 size_t tmp_count[2] = {3, read_num_local_cells};
1027 yac_nc_inq_varid(ncid, "vertex_of_cell", &varid);
1028 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, tmp_start, tmp_count, buffer));
1029 for (size_t i = 0; i < read_num_local_cells; ++i)
1030 for (int j = 0; j < 3; ++j)
1031 read_dist_vertex_of_cell[i * 3 + j] =
1032 buffer[i + j * read_num_local_cells];
1033 yac_nc_inq_varid(ncid, "edge_of_cell", &varid);
1034 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, tmp_start, tmp_count, buffer));
1035 for (size_t i = 0; i < read_num_local_cells; ++i)
1036 for (int j = 0; j < 3; ++j)
1037 read_dist_edge_of_cell[i * 3 + j] =
1038 buffer[i + j * read_num_local_cells];
1039 }
1040 {
1041 size_t tmp_start[2] = {0, read_local_start_edge};
1042 size_t tmp_count[2] = {2, read_num_local_edges};
1043 yac_nc_inq_varid(ncid, "edge_vertices", &varid);
1044 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, varid, tmp_start, tmp_count, buffer));
1045 for (size_t i = 0; i < read_num_local_edges; ++i)
1046 for (int j = 0; j < 2; ++j)
1047 read_dist_edge_vertices[i * 2 + j] =
1048 buffer[i + j * read_num_local_edges];
1049 }
1050 free(buffer);
1051
1052 // adjust for c indices
1053 for (size_t i = 0; i < read_num_local_cells * 3; ++i)
1054 if (read_dist_vertex_of_cell[i] > 0) read_dist_vertex_of_cell[i]--;
1055 for (size_t i = 0; i < read_num_local_cells * 3; ++i)
1056 if (read_dist_edge_of_cell[i] > 0) read_dist_edge_of_cell[i]--;
1057 for (size_t i = 0; i < read_num_local_edges * 2; ++i)
1058 if (read_dist_edge_vertices[i] > 0) read_dist_edge_vertices[i]--;
1059 }
1060
1061 YAC_HANDLE_ERROR(nc_close(ncid));
1062 } else {
1063 read_vertex_lon = xmalloc(1 * sizeof(*read_vertex_lon));
1064 read_vertex_lat = xmalloc(1 * sizeof(*read_vertex_lat));
1065 read_dist_vertex_of_cell = xmalloc(1 * sizeof(*read_dist_vertex_of_cell));
1066 read_dist_edge_of_cell = xmalloc(1 * sizeof(*read_dist_edge_of_cell));
1067 read_dist_edge_vertices = xmalloc(1 * sizeof(*read_dist_edge_vertices));
1068 }
1069
1070 free(io_ranks);
1071
1072 {
1073 int tmp;
1074 if (comm_rank == 0) tmp = (int)ncells;
1075 MPI_Bcast(&tmp, 1, MPI_INT, 0, comm);
1076 ncells = (size_t)tmp;
1077 if (comm_rank == 0) tmp = (int)nvertices;
1078 MPI_Bcast(&tmp, 1, MPI_INT, 0, comm);
1079 nvertices = (size_t)tmp;
1080 if (comm_rank == 0) tmp = (int)nedges;
1081 MPI_Bcast(&tmp, 1, MPI_INT, 0, comm);
1082 nedges = (size_t)tmp;
1083 }
1084
1085 // determine local range for cell and vertex data
1086 size_t local_start_cell =
1087 ((unsigned long)ncells * (unsigned long)comm_rank) /
1088 (unsigned long)comm_size;
1089 size_t num_local_cells =
1090 ((unsigned long)ncells * ((unsigned long)comm_rank+1)) /
1091 (unsigned long)comm_size - (unsigned long)local_start_cell;
1092 size_t local_start_vertex =
1093 ((unsigned long)nvertices * (unsigned long)comm_rank) /
1094 (unsigned long)comm_size;
1095 size_t num_local_vertices =
1096 ((unsigned long)nvertices * ((unsigned long)comm_rank+1)) /
1097 (unsigned long)comm_size - (unsigned long)local_start_vertex;
1098 size_t local_start_edge =
1099 ((unsigned long)nedges * (unsigned long)comm_rank) /
1100 (unsigned long)comm_size;
1101 size_t num_local_edges =
1102 ((unsigned long)nedges * ((unsigned long)comm_rank+1)) /
1103 (unsigned long)comm_size - (unsigned long)local_start_edge;
1104
1105 // redistribute basic cell data (from io decomposition)
1106 int * dist_vertex_of_cell =
1107 xmalloc(num_local_cells * 3 * sizeof(*dist_vertex_of_cell));
1108 int * dist_edge_of_cell =
1109 xmalloc(num_local_cells * 3 * sizeof(*dist_edge_of_cell));
1110 {
1111 int * send_count = xcalloc(comm_size, sizeof(*send_count));
1112 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
1113
1114 for (unsigned i = 0; i < read_num_local_cells; ++i)
1115 send_count[
1117 read_local_start_cell + i, ncells, comm_size)] += 3;
1118
1119 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
1120
1121 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
1122 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
1123 int send_accum = 0, recv_accum = 0;
1124 for (int i = 0; i < comm_size; ++i) {
1125 send_displ[i] = send_accum;
1126 recv_displ[i] = recv_accum;
1127 send_accum += send_count[i];
1128 recv_accum += recv_count[i];
1129 }
1130
1131 MPI_Alltoallv(read_dist_vertex_of_cell, send_count, send_displ, MPI_INT,
1132 dist_vertex_of_cell, recv_count, recv_displ, MPI_INT, comm);
1133 MPI_Alltoallv(read_dist_edge_of_cell, send_count, send_displ, MPI_INT,
1134 dist_edge_of_cell, recv_count, recv_displ, MPI_INT, comm);
1135
1136 free(recv_displ);
1137 free(send_displ);
1138 free(recv_count);
1139 free(send_count);
1140 free(read_dist_vertex_of_cell);
1141 free(read_dist_edge_of_cell);
1142 }
1143
1144 // redistribute basic vertex data (from io decomposition)
1145 double * vertex_lon = xmalloc(num_local_vertices * sizeof(*vertex_lon));
1146 double * vertex_lat = xmalloc(num_local_vertices * sizeof(*vertex_lat));
1147 {
1148 int * send_count = xcalloc(comm_size, sizeof(*send_count));
1149 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
1150
1151 for (unsigned i = 0; i < read_num_local_vertices; ++i)
1152 send_count[
1154 read_local_start_vertex + i, nvertices, comm_size)]++;
1155
1156 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
1157
1158 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
1159 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
1160 int send_accum = 0, recv_accum = 0;
1161 for (int i = 0; i < comm_size; ++i) {
1162 send_displ[i] = send_accum;
1163 recv_displ[i] = recv_accum;
1164 send_accum += send_count[i];
1165 recv_accum += recv_count[i];
1166 }
1167
1168 MPI_Alltoallv(read_vertex_lon, send_count, send_displ, MPI_DOUBLE,
1169 vertex_lon, recv_count, recv_displ, MPI_DOUBLE, comm);
1170 MPI_Alltoallv(read_vertex_lat, send_count, send_displ, MPI_DOUBLE,
1171 vertex_lat, recv_count, recv_displ, MPI_DOUBLE, comm);
1172
1173 free(recv_displ);
1174 free(send_displ);
1175 free(recv_count);
1176 free(send_count);
1177 free(read_vertex_lon);
1178 free(read_vertex_lat);
1179 }
1180
1181 // redistribute basic edge data (from io decomposition)
1182 int * dist_edge_vertices =
1183 xmalloc(num_local_edges * 2 * sizeof(*dist_edge_vertices));
1184 {
1185 int * send_count = xcalloc(comm_size, sizeof(*send_count));
1186 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
1187
1188 for (unsigned i = 0; i < read_num_local_edges; ++i)
1189 send_count[
1191 read_local_start_edge + i, nedges, comm_size)] += 2;
1192
1193 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
1194
1195 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
1196 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
1197 int send_accum = 0, recv_accum = 0;
1198 for (int i = 0; i < comm_size; ++i) {
1199 send_displ[i] = send_accum;
1200 recv_displ[i] = recv_accum;
1201 send_accum += send_count[i];
1202 recv_accum += recv_count[i];
1203 }
1204
1205 MPI_Alltoallv(read_dist_edge_vertices, send_count, send_displ, MPI_INT,
1206 dist_edge_vertices, recv_count, recv_displ, MPI_INT, comm);
1207
1208 free(recv_displ);
1209 free(send_displ);
1210 free(recv_count);
1211 free(send_count);
1212 free(read_dist_edge_vertices);
1213 }
1214
1215 // determine required vertices for core cells
1216 // in additional compute num_cells_per_vertex, vertex_to_cell,
1217 // and cell_to_vertex
1218 size_t num_core_vertices;
1219 yac_int * core_vertices;
1221 size_t * vertex_to_cell;
1222 size_t * cell_to_vertex;
1223 {
1224 size_t N = num_local_cells * 3;
1225 core_vertices = xmalloc(N * sizeof(*core_vertices));
1227 vertex_to_cell = xmalloc(N * sizeof(*vertex_to_cell));
1228 cell_to_vertex = xmalloc(N * sizeof(*cell_to_vertex));
1229 for (size_t i = 0; i < N; ++i)
1230 core_vertices[i] = (yac_int)dist_vertex_of_cell[i];
1231 size_t * permutation = vertex_to_cell;
1232 for (size_t i = 0; i < N; ++i) permutation[i] = i;
1233 yac_quicksort_index_yac_int_size_t(core_vertices, N, permutation);
1234 // remove duplicated core vertices and count number of cells per vertex
1235 yac_int prev_vertex_id = XT_INT_MAX;
1236 num_core_vertices = 0;
1237 for (size_t i = 0; i < N; ++i) {
1238 yac_int curr_vertex_id = core_vertices[i];
1239 if (prev_vertex_id == curr_vertex_id) {
1240 num_cells_per_vertex[num_core_vertices-1]++;
1241 } else {
1242 num_cells_per_vertex[num_core_vertices] = 1;
1243 core_vertices[num_core_vertices] = (prev_vertex_id = curr_vertex_id);
1244 ++num_core_vertices;
1245 }
1246 cell_to_vertex[permutation[i]] = num_core_vertices-1;
1247 permutation[i] /= 3;
1248 }
1249 core_vertices =
1250 xrealloc(core_vertices, num_core_vertices * sizeof(*core_vertices));
1253 num_core_vertices * sizeof(*num_cells_per_vertex));
1254 free(dist_vertex_of_cell);
1255 }
1256
1257 // determine required edges for core cells
1258 // in additional compute edge_to_cell and cell_to_edge
1259 size_t num_core_edges;
1260 yac_int * core_edges;
1261 size_t * cell_to_edge;
1262 {
1263 size_t N = num_local_cells * 3;
1264 core_edges = xmalloc(N * sizeof(*core_edges));
1265 size_t * permutation = xmalloc(N * sizeof(*permutation));
1266 cell_to_edge = xmalloc(N * sizeof(*cell_to_edge));
1267 for (size_t i = 0; i < N; ++i)
1268 core_edges[i] = (yac_int)dist_edge_of_cell[i];
1269 for (size_t i = 0; i < N; ++i) permutation[i] = i;
1270 yac_quicksort_index_yac_int_size_t(core_edges, N, permutation);
1271 // remove duplicated core edges and count number of cells per edge
1272 yac_int prev_edge_id = XT_INT_MAX;
1273 num_core_edges = 0;
1274 for (size_t i = 0; i < N; ++i) {
1275 yac_int curr_edge_id = core_edges[i];
1276 if (prev_edge_id != curr_edge_id)
1277 core_edges[num_core_edges++] = (prev_edge_id = curr_edge_id);
1278 cell_to_edge[permutation[i]] = num_core_edges-1;
1279 permutation[i] /= 3;
1280 }
1281 free(permutation);
1282 core_edges =
1283 xrealloc(core_edges, num_core_edges * sizeof(*core_edges));
1284 free(dist_edge_of_cell);
1285 }
1286
1287 // generate vertex coordinate data
1289 xmalloc(num_core_vertices * sizeof(*vertex_coordinates));
1290 {
1291 double * local_vertex_lon =
1292 xmalloc(num_core_vertices * sizeof(*local_vertex_lon));
1293 double * local_vertex_lat =
1294 xmalloc(num_core_vertices * sizeof(*local_vertex_lat));
1295 int * send_count = xcalloc(comm_size, sizeof(*send_count));
1296 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
1297
1298 for (size_t i = 0; i < num_core_vertices; ++i)
1299 send_count[((unsigned long)(core_vertices[i]) *
1300 (unsigned long)comm_size + (unsigned long)comm_size - 1) /
1301 (unsigned long)nvertices]++;
1302
1303 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
1304
1305 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
1306 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
1307 int send_accum = 0, recv_accum = 0;
1308 for (int i = 0; i < comm_size; ++i) {
1309 send_displ[i] = send_accum;
1310 recv_displ[i] = recv_accum;
1311 send_accum += send_count[i];
1312 recv_accum += recv_count[i];
1313 }
1314
1315 int num_all_local_vertices_remote = 0;
1316 for (int i = 0; i < comm_size; ++i)
1317 num_all_local_vertices_remote += recv_count[i];
1318
1319 yac_int * remote_vertex_buffer =
1320 xmalloc(num_all_local_vertices_remote * sizeof(*remote_vertex_buffer));
1321
1322 MPI_Alltoallv(
1323 core_vertices, send_count, send_displ, yac_int_dt,
1324 remote_vertex_buffer, recv_count, recv_displ, yac_int_dt, comm);
1325
1326 double * send_vertex_lon =
1327 xmalloc(num_all_local_vertices_remote * sizeof(*send_vertex_lon));
1328 double * send_vertex_lat =
1329 xmalloc(num_all_local_vertices_remote * sizeof(*send_vertex_lat));
1330
1331 for (int i = 0, l = 0; i < comm_size; ++i) {
1332 for (int j = 0; j < recv_count[i]; ++j, ++l) {
1333 size_t idx = (size_t)(remote_vertex_buffer[l]) - local_start_vertex;
1334 send_vertex_lon[l] = vertex_lon[idx];
1335 send_vertex_lat[l] = vertex_lat[idx];
1336 }
1337 }
1338
1339 free(remote_vertex_buffer);
1340 free(vertex_lon);
1341 free(vertex_lat);
1342
1343 MPI_Alltoallv(send_vertex_lon, recv_count, recv_displ, MPI_DOUBLE,
1344 local_vertex_lon, send_count, send_displ, MPI_DOUBLE, comm);
1345 MPI_Alltoallv(send_vertex_lat, recv_count, recv_displ, MPI_DOUBLE,
1346 local_vertex_lat, send_count, send_displ, MPI_DOUBLE, comm);
1347
1348 for (unsigned i = 0; i < num_core_vertices; ++i)
1349 LLtoXYZ(
1350 local_vertex_lon[i], local_vertex_lat[i], &(vertex_coordinates[i][0]));
1351
1352 free(send_vertex_lat);
1353 free(send_vertex_lon);
1354 free(recv_displ);
1355 free(send_displ);
1356 free(recv_count);
1357 free(send_count);
1358 free(local_vertex_lon);
1359 free(local_vertex_lat);
1360 }
1361
1362 // generate edge vertex data
1363 size_t * edge_to_vertex =
1364 xmalloc(2 * num_core_edges * sizeof(*edge_to_vertex));
1365 {
1366 int * local_edge_to_vertex =
1367 xmalloc(2 * num_core_edges * sizeof(*local_edge_to_vertex));
1368 int * send_count = xcalloc(comm_size, sizeof(*send_count));
1369 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
1370
1371 for (size_t i = 0; i < num_core_edges; ++i)
1372 send_count[((unsigned long)(core_edges[i]) *
1373 (unsigned long)comm_size + (unsigned long)comm_size - 1) /
1374 (unsigned long)nedges]++;
1375
1376 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
1377
1378 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
1379 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
1380 int send_accum = 0, recv_accum = 0;
1381 for (int i = 0; i < comm_size; ++i) {
1382 send_displ[i] = send_accum;
1383 recv_displ[i] = recv_accum;
1384 send_accum += send_count[i];
1385 recv_accum += recv_count[i];
1386 }
1387
1388 int num_all_local_edges_remote = 0;
1389 for (int i = 0; i < comm_size; ++i)
1390 num_all_local_edges_remote += recv_count[i];
1391
1392 yac_int * remote_edge_buffer =
1393 xmalloc(num_all_local_edges_remote * sizeof(*remote_edge_buffer));
1394
1395 MPI_Alltoallv(
1396 core_edges, send_count, send_displ, yac_int_dt,
1397 remote_edge_buffer, recv_count, recv_displ, yac_int_dt, comm);
1398
1399 int * send_edge_vertices =
1400 xmalloc(2 * num_all_local_edges_remote * sizeof(*send_edge_vertices));
1401
1402 for (int i = 0, l = 0; i < comm_size; ++i) {
1403 for (int j = 0; j < recv_count[i]; ++j, ++l) {
1404 size_t idx = (size_t)(remote_edge_buffer[l]) - local_start_edge;
1405 send_edge_vertices[2*l+0] = dist_edge_vertices[2*idx+0];
1406 send_edge_vertices[2*l+1] = dist_edge_vertices[2*idx+1];
1407
1408 }
1409 send_count[i] *= 2;
1410 recv_count[i] *= 2;
1411 send_displ[i] *= 2;
1412 recv_displ[i] *= 2;
1413 }
1414
1415 free(remote_edge_buffer);
1416 free(dist_edge_vertices);
1417
1418 MPI_Alltoallv(send_edge_vertices, recv_count, recv_displ, MPI_INT,
1419 local_edge_to_vertex, send_count, send_displ, MPI_INT, comm);
1420
1421 size_t * permutation = xmalloc(2 * num_core_edges * sizeof(*permutation));
1422 for (size_t i = 0; i < 2 * num_core_edges; ++i) permutation[i] = i;
1423
1425 local_edge_to_vertex, 2 * num_core_edges, permutation);
1426
1427 for (size_t i = 0, j = 0; i < 2 * num_core_edges; ++i) {
1428 yac_int curr_vertex = (yac_int)(local_edge_to_vertex[i]);
1429 while ((j < nvertices) && (core_vertices[j] < curr_vertex)) ++j;
1430 YAC_ASSERT(
1431 (j < nvertices) && (core_vertices[j] == curr_vertex),
1432 "ERROR(yac_read_icon_basic_grid_data_parallel): vertex id missmatch")
1433 edge_to_vertex[permutation[i]] = j;
1434 }
1435
1436 free(permutation);
1437 free(send_edge_vertices);
1438 free(recv_displ);
1439 free(send_displ);
1440 free(recv_count);
1441 free(send_count);
1442 free(local_edge_to_vertex);
1443 }
1444
1445 // generate cell ids for local partition
1446 yac_int * cell_ids = xmalloc(num_local_cells * sizeof(*cell_ids));
1447 for (size_t i = 0; i < num_local_cells; ++i)
1448 cell_ids[i] = (yac_int)(local_start_cell + i);
1449
1450 // generate num_vertices_per_cell (for icon grids this is always 3)
1451 int * num_vertices_per_cell =
1452 xmalloc(num_local_cells * sizeof(*num_vertices_per_cell));
1453 for (size_t i = 0; i < num_local_cells; ++i) num_vertices_per_cell[i] = 3;
1454
1455 // generate edge_type (for icon grids this is always YAC_GREAT_CIRCLE_EDGE)
1456 enum yac_edge_type * edge_type = xmalloc(num_core_edges * sizeof(*edge_type));
1457 for (size_t i = 0; i < num_core_edges; ++i) edge_type[i] = YAC_GREAT_CIRCLE_EDGE;
1458
1459 struct yac_basic_grid_data grid_data;
1461 grid_data.cell_ids = cell_ids;
1462 grid_data.vertex_ids = core_vertices;
1463 grid_data.edge_ids = core_edges;
1464 grid_data.num_cells = num_local_cells;
1465 grid_data.num_vertices = num_core_vertices;
1466 grid_data.num_edges = num_core_edges;
1467 grid_data.core_cell_mask = generate_simple_core_mask(num_local_cells);
1468 grid_data.core_vertex_mask = generate_simple_core_mask(num_core_vertices);
1469 grid_data.core_edge_mask = generate_simple_core_mask(num_core_edges);
1472 grid_data.cell_to_vertex = cell_to_vertex;
1474 grid_data.cell_to_edge = cell_to_edge;
1475 grid_data.cell_to_edge_offsets = grid_data.cell_to_vertex_offsets;
1476 grid_data.vertex_to_cell = vertex_to_cell;
1477 grid_data.vertex_to_cell_offsets = generate_offsets(num_core_vertices, num_cells_per_vertex);
1479 grid_data.edge_type = edge_type;
1480 grid_data.num_total_cells = num_local_cells;
1481 grid_data.num_total_vertices = num_core_vertices;
1482 grid_data.num_total_edges = num_core_edges;
1483
1484 return grid_data;
1485#endif
1486}
1487
1489 char const * filename, char const * gridname, MPI_Comm comm) {
1490
1491 return
1493 gridname,
1495}
1496
1498 char const * filename, char const * gridname, MPI_Fint comm) {
1499
1500 return
1502 filename, gridname, MPI_Comm_f2c(comm));
1503}
1504
1506 char const * filename) {
1507
1508 int nbr_vertices;
1509 int nbr_cells;
1510 int * num_vertices_per_cell = NULL;
1511 int * cell_to_vertex = NULL;
1512 int * cell_mask = NULL;
1513
1514 double * x_vertices = NULL;
1515 double * y_vertices = NULL;
1516 double * x_cells = NULL;
1517 double * y_cells = NULL;
1518
1519 yac_read_icon_grid_information(filename, &nbr_vertices, &nbr_cells,
1521 &x_vertices, &y_vertices,
1522 &x_cells, &y_cells,
1523 &cell_mask);
1524
1525 free(x_cells);
1526 free(y_cells);
1527 free(cell_mask);
1528
1529 struct yac_basic_grid_data grid =
1531 (size_t)nbr_vertices, (int)nbr_cells, num_vertices_per_cell,
1532 x_vertices, y_vertices, cell_to_vertex);
1534 free(x_vertices);
1535 free(y_vertices);
1536 free(cell_to_vertex);
1537
1538 return grid;
1539}
1540
1542 char const * filename, char const * gridname) {
1543
1544 return
1546 gridname, yac_read_icon_basic_grid_data(filename));
1547}
1548
1549/* ---------------------------------------------------------------- */
1550
1551#ifdef YAC_NETCDF_ENABLED
1552static int * get_icon_cell_mask ( int ncid, size_t nbr_cells ) {
1553
1554 // get variable id
1555 int mask_id;
1556 yac_nc_inq_varid (ncid, "cell_sea_land_mask", &mask_id);
1557
1558 // check number of dimension (has to be 1)
1559 int ndims;
1560 YAC_HANDLE_ERROR(nc_inq_varndims(ncid, mask_id, &ndims));
1561 YAC_ASSERT(
1562 ndims == 1,
1563 "ERROR(get_icon_cell_mask): mask array has more than one dimension")
1564
1565 // get id of dimension
1566 int dimid;
1567 YAC_HANDLE_ERROR(nc_inq_vardimid(ncid, mask_id, &dimid));
1568
1569 // check size of mask (has to be equal to nbr_cells)
1570 size_t dimlen;
1571 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &dimlen));
1572 YAC_ASSERT(
1573 dimlen == nbr_cells,
1574 "ERROR(get_icon_cell_mask): invalid size of mask array")
1575
1576 // check mask type (has to be NC_INT)
1577 nc_type mask_type;
1578 YAC_HANDLE_ERROR(nc_inq_vartype(ncid, mask_id, &mask_type));
1579 YAC_ASSERT(
1580 mask_type == NC_INT, "ERROR(get_icon_cell_mask): invalid mask type")
1581
1582 // get and return mask
1583 int * cell_mask = xmalloc(nbr_cells * sizeof(*cell_mask));
1584 YAC_HANDLE_ERROR(nc_get_var_int (ncid, mask_id, cell_mask));
1585 return cell_mask;
1586}
1587
1588/* ---------------------------------------------------------------- */
1589
1590static int * get_icon_connect(int ncid, size_t nbr_cells) {
1591
1592 // get variable id
1593 int conn_id;
1594 yac_nc_inq_varid(ncid, "vertex_of_cell", &conn_id);
1595
1596 // check number of dimension (has to be 1)
1597 int ndims;
1598 YAC_HANDLE_ERROR(nc_inq_varndims(ncid, conn_id, &ndims));
1599 YAC_ASSERT(
1600 ndims == 2,
1601 "ERROR(get_icon_connect): "
1602 "connectivity array has invalid number of dimensions")
1603
1604 // get ids of dimensions
1605 int dimids[2];
1606 YAC_HANDLE_ERROR(nc_inq_vardimid(ncid, conn_id, dimids));
1607
1608 // check size of dimensions
1609 size_t dimlen;
1610 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimids[0], &dimlen));
1611 YAC_ASSERT(
1612 dimlen == 3,
1613 "ERROR(get_icon_connect): invalid size of first dimension of "
1614 "connectivity array (has to be 3)")
1615 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimids[1], &dimlen));
1616 YAC_ASSERT(
1617 dimlen == nbr_cells,
1618 "ERROR(get_icon_connect): invalid size of second dimension of "
1619 "connectivity array (has to be nbr_cells)")
1620
1621 // get and return connectivity array
1622 int * vertex_of_cell = xmalloc(3 * nbr_cells * sizeof(*vertex_of_cell));
1623 YAC_HANDLE_ERROR(nc_get_var_int (ncid, conn_id, vertex_of_cell));
1624 return vertex_of_cell;
1625}
1626#endif
1627
1628void yac_delete_icon_grid_data( int ** cell_mask,
1629 int ** global_cell_id,
1630 int ** global_cell_id_rank,
1631 int ** num_vertices_per_cell,
1632 int ** global_corner_id,
1633 int ** global_corner_id_rank,
1634 int ** cell_to_vertex,
1635 double ** x_cells,
1636 double ** y_cells,
1637 double ** x_vertices,
1638 double ** y_vertices) {
1639
1640 free (*cell_mask);
1641 free (*global_cell_id);
1642 free (*global_cell_id_rank);
1643 free (*num_vertices_per_cell);
1644 free (*global_corner_id);
1645 free (*global_corner_id_rank);
1646 free (*cell_to_vertex);
1647 free (*x_cells);
1648 free (*y_cells);
1649 free (*x_vertices);
1650 free (*y_vertices);
1651}
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:45
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:71
#define YAC_RAD
Definition geometry.h:30
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition geometry.h:287
yac_edge_type
Definition grid_cell.h:12
@ YAC_GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:13
void yac_get_io_ranks(MPI_Comm comm, int *local_is_io_, int **io_ranks_, int *num_io_ranks_)
Definition io_utils.c:303
void yac_nc_inq_varid(int ncid, char const *name, int *varidp)
Definition io_utils.c:403
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:344
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:379
#define YAC_HANDLE_ERROR(exp)
Definition io_utils.h:30
#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
int yac_check_coord_units(int ncid, int varid)
Definition read_grid.c:45
void yac_read_coords(int ncid, char const *lon_name, char const *lat_name, double **lon, double **lat, size_t *len)
Definition read_grid.c:92
struct yac_basic_grid * yac_read_icon_basic_grid_parallel_f2c(char const *filename, char const *gridname, MPI_Fint comm)
static void convert_to_rad(int ncid, int varid, double *array, size_t count)
void yac_delete_icon_grid_data(int **cell_mask, int **global_cell_id, int **global_cell_id_rank, int **num_vertices_per_cell, int **global_corner_id, int **global_corner_id_rank, int **cell_to_vertex, double **x_cells, double **y_cells, double **x_vertices, double **y_vertices)
struct yac_basic_grid * yac_read_icon_basic_grid(char const *filename, char const *gridname)
void yac_read_part_icon_grid_information(const char *filename, int *nbr_vertices, int *nbr_cells, int **num_vertices_per_cell, int **cell_to_vertex, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **global_cell_id, int **cell_mask, int **cell_core_mask, int **global_corner_id, int **corner_core_mask, int rank, int size)
struct yac_basic_grid_data yac_read_icon_basic_grid_data_parallel(const char *filename, MPI_Comm comm)
static int * get_icon_cell_mask(int ncid, size_t nbr_cells)
void yac_read_icon_grid_information_parallel(const char *filename, MPI_Comm comm, int *nbr_vertices, int *nbr_cells, int **num_vertices_per_cell, int **cell_to_vertex, int **global_cell_ids, int **cell_owner, int **global_vertex_ids, int **vertex_owner, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **cell_msk)
void yac_read_icon_grid_information_parallel_f2c(const char *filename, MPI_Fint comm, int *nbr_vertices, int *nbr_cells, int **num_vertices_per_cell, int **cell_to_vertex, int **global_cell_ids, int **cell_owner, int **global_vertex_ids, int **vertex_owner, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **cell_msk)
static int partition_idx_from_element_idx(unsigned element_idx, unsigned num_elements, int num_partitions)
static size_t * generate_offsets(size_t N, int *counts)
static int * generate_simple_core_mask(size_t N)
void yac_read_icon_grid_information(const char *filename, int *nbr_vertices, int *nbr_cells, int **num_vertices_per_cell, int **cell_to_vertex, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **cell_mask)
struct yac_basic_grid * yac_read_icon_basic_grid_parallel(char const *filename, char const *gridname, MPI_Comm comm)
static int * get_icon_connect(int ncid, size_t nbr_cells)
struct yac_basic_grid_data yac_read_icon_basic_grid_data(char const *filename)
yac_coordinate_pointer vertex_coordinates
size_t * vertex_to_cell_offsets
yac_size_t_2_pointer edge_to_vertex
enum yac_edge_type * edge_type
size_t * cell_to_vertex_offsets
static void yac_remove_duplicates_int(int *array, size_t *n)
#define MAX(a, b)
void yac_quicksort_index_yac_int_size_t(yac_int *a, size_t n, size_t *idx)
void yac_quicksort_index_int_size_t(int *a, size_t n, size_t *idx)
void yac_quicksort_index(int *a, size_t n, int *idx)
#define die(msg)
Definition yac_assert.h:12
#define YAC_ASSERT(exp, msg)
Definition yac_assert.h:15
Xt_int yac_int
Definition yac_types.h:15
size_t(* yac_size_t_2_pointer)[2]
Definition yac_types.h:23
#define yac_int_dt
Definition yac_types.h:16
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19