YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
read_exodus_grid.c
Go to the documentation of this file.
1// Copyright (c) 2025 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#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#include <limits.h>
15
16#include <mpi.h>
17
18#include "read_exodus_grid.h"
19#include "utils_common.h"
20#include "io_utils.h"
21#include "geometry.h"
22#include "read_grid.h"
23#include "yac_mpi_internal.h"
24
25#ifdef YAC_NETCDF_ENABLED
26#include <netcdf.h>
27
28static size_t * generate_offsets(size_t N, int * counts) {
29
30 size_t * offsets = xmalloc(N * sizeof(*offsets));
31 for (size_t i = 0, accu = 0; i < N; ++i) {
32 offsets[i] = accu;
33 accu += (size_t)(counts[i]);
34 }
35 return offsets;
36}
37
38// taken from scales-ppm library
39// https://www.dkrz.de/redmine/projects/scales-ppm
40static inline int
41partition_idx_from_element_idx(size_t element_idx, size_t num_elements,
42 int num_partitions) {
43
44 return (int)((((unsigned long)element_idx) * ((unsigned long)num_partitions) +
45 (unsigned long)num_partitions - 1) /
46 ((unsigned long)num_elements));
47}
48
50 const char * filename, MPI_Comm comm, yac_coordinate_pointer * node_coords,
51 yac_int ** elem_ids, yac_int ** node_ids,
52 size_t * num_elem, size_t * num_nodes,
53 int ** num_nodes_per_elem, int ** num_elem_per_node,
54 size_t ** elem_to_node, size_t ** node_to_elem) {
55
56 int comm_rank, comm_size;
57
58 MPI_Comm_rank(comm, &comm_rank);
59 MPI_Comm_size(comm, &comm_size);
60
61 int local_is_io, * io_ranks, num_io_ranks;
62 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
63
64 size_t num_global_nodes, num_global_elem, num_nod_per_elem;
65
66 size_t read_local_start_elem = 0;
67 size_t read_num_local_elems = 0;
68 size_t read_local_start_node = 0;
69 size_t read_num_local_nodes = 0;
70
71 yac_coordinate_pointer read_node_coords = NULL;
72 int * read_dist_elem_to_node = NULL;
73
74 if (local_is_io) {
75
76 unsigned long io_proc_idx = ULONG_MAX;
77 for (int i = 0; (i < num_io_ranks) && (io_proc_idx == ULONG_MAX); ++i)
78 if (io_ranks[i] == comm_rank)
79 io_proc_idx = (unsigned long)i;
80
81 // open file
82 int ncid;
83 yac_nc_open(filename, NC_NOWRITE, &ncid);
84
85 // get number of cells and vertices
86 int dim_id;
87 size_t num_el_blk, num_el_in_blk1;
88 yac_nc_inq_dimid(ncid, "num_nodes", &dim_id);
89 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &num_global_nodes));
90 yac_nc_inq_dimid(ncid, "num_elem", &dim_id);
91 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &num_global_elem));
92 yac_nc_inq_dimid(ncid, "num_el_blk", &dim_id);
93 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &num_el_blk));
94 yac_nc_inq_dimid(ncid, "num_el_in_blk1", &dim_id);
95 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &num_el_in_blk1));
96 yac_nc_inq_dimid(ncid, "num_nod_per_el1", &dim_id);
97 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dim_id, &num_nod_per_elem));
98
100 num_el_blk == 1,
101 "reader currently only supports a single block of elements");
103 num_global_elem == num_el_in_blk1,
104 "total number of elements and number of elements in first block "
105 "of elements do not match");
106
107 // determine local range for element and node data
108 read_local_start_elem =
109 ((unsigned long)num_global_elem * io_proc_idx) / (unsigned long)num_io_ranks;
110 read_num_local_elems =
111 ((unsigned long)num_global_elem * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
112 (unsigned long)read_local_start_elem;
113 read_local_start_node =
114 ((unsigned long)num_global_nodes * io_proc_idx) / (unsigned long)num_io_ranks;
115 read_num_local_nodes =
116 ((unsigned long)num_global_nodes * (io_proc_idx+1)) / (unsigned long)num_io_ranks -
117 (unsigned long)read_local_start_node;
118
119 // read basic grid data (each process its individual part)
120 double * read_node_coord_x =
121 xmalloc(read_num_local_nodes * sizeof(*read_node_coord_x));
122 double * read_node_coord_y =
123 xmalloc(read_num_local_nodes * sizeof(*read_node_coord_y));
124 double * read_node_coord_z =
125 xmalloc(read_num_local_nodes * sizeof(*read_node_coord_z));;
126 int varid;
127 yac_nc_inq_varid(ncid, "coord", &varid);
129 nc_get_vara_double(
130 ncid, varid, (size_t[]){0, read_local_start_node},
131 (size_t[]){1,read_num_local_nodes}, read_node_coord_x));
133 nc_get_vara_double(
134 ncid, varid, (size_t[]){1, read_local_start_node},
135 (size_t[]){1,read_num_local_nodes}, read_node_coord_y));
137 nc_get_vara_double(
138 ncid, varid, (size_t[]){2, read_local_start_node},
139 (size_t[]){1,read_num_local_nodes}, read_node_coord_z));
140 read_node_coords =
141 xmalloc(read_num_local_nodes * sizeof(*read_node_coords));
142 for (size_t i = 0; i < read_num_local_nodes; ++i) {
143 read_node_coords[i][0] = read_node_coord_x[i];
144 read_node_coords[i][1] = read_node_coord_y[i];
145 read_node_coords[i][2] = read_node_coord_z[i];
146 }
147 free(read_node_coord_z);
148 free(read_node_coord_y);
149 free(read_node_coord_x);
150
151 read_dist_elem_to_node =
152 xmalloc(
153 read_num_local_elems * num_nod_per_elem *
154 sizeof(*read_dist_elem_to_node));
155 yac_nc_inq_varid(ncid, "connect1", &varid);
157 nc_get_vara_int(
158 ncid, varid, (size_t[]){read_local_start_elem, 0},
159 (size_t[]){read_num_local_elems, num_nod_per_elem},
160 read_dist_elem_to_node));
161 for (size_t i = 0; i < read_num_local_elems * num_nod_per_elem; ++i)
162 read_dist_elem_to_node[i]--;
163
164 YAC_HANDLE_ERROR(nc_close(ncid));
165
166 } else {
167 read_node_coords = xmalloc(1 * sizeof(*read_node_coords));
168 read_dist_elem_to_node = xmalloc(1 * sizeof(*read_dist_elem_to_node));
169 }
170
171 free(io_ranks);
172
173 {
174 size_t tmp;
175 if (comm_rank == 0) tmp = num_global_nodes;
176 MPI_Bcast(&tmp, 1, YAC_MPI_SIZE_T, 0, comm);
177 num_global_nodes = tmp;
178 if (comm_rank == 0) tmp = num_global_elem;
179 MPI_Bcast(&tmp, 1, YAC_MPI_SIZE_T, 0, comm);
180 num_global_elem = tmp;
181 if (comm_rank == 0) tmp = num_nod_per_elem;
182 MPI_Bcast(&tmp, 1, YAC_MPI_SIZE_T, 0, comm);
183 num_nod_per_elem = tmp;
184 }
185
186 // determine local range for element and node data
187 size_t local_start_elem =
188 ((unsigned long)num_global_elem * (unsigned long)comm_rank) /
189 (unsigned long)comm_size;
190 size_t num_local_elems =
191 ((unsigned long)num_global_elem * ((unsigned long)comm_rank+1)) /
192 (unsigned long)comm_size - (unsigned long)local_start_elem;
193 size_t local_start_node =
194 ((unsigned long)num_global_nodes * (unsigned long)comm_rank) /
195 (unsigned long)comm_size;
196 size_t num_local_nodes =
197 ((unsigned long)num_global_nodes * ((unsigned long)comm_rank+1)) /
198 (unsigned long)comm_size - (unsigned long)local_start_node;
199
200 // redistribute basic element data (from io decomposition)
201 int * dist_elem_to_node =
202 xmalloc(num_local_elems * num_nod_per_elem * sizeof(*dist_elem_to_node));
203 {
204 int * send_count = xcalloc(comm_size, sizeof(*send_count));
205 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
206
207 for (size_t i = 0; i < read_num_local_elems; ++i)
208 send_count[
210 read_local_start_elem + i, num_global_elem, comm_size)] +=
211 num_nod_per_elem;
212
213 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
214
215 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
216 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
217 int send_accum = 0, recv_accum = 0;
218 for (int i = 0; i < comm_size; ++i) {
219 send_displ[i] = send_accum;
220 recv_displ[i] = recv_accum;
221 send_accum += send_count[i];
222 recv_accum += recv_count[i];
223 }
224
225 MPI_Alltoallv(read_dist_elem_to_node, send_count, send_displ, MPI_INT,
226 dist_elem_to_node, recv_count, recv_displ, MPI_INT, comm);
227
228 free(recv_displ);
229 free(send_displ);
230 free(recv_count);
231 free(send_count);
232 free(read_dist_elem_to_node);
233 }
234
235 // redistribute basic node data (from io decomposition)
236 yac_coordinate_pointer dist_node_coords =
237 xmalloc(num_local_nodes * sizeof(*dist_node_coords));
238 {
239 int * send_count = xcalloc(comm_size, sizeof(*send_count));
240 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
241
242 for (size_t i = 0; i < read_num_local_nodes; ++i)
243 send_count[
245 read_local_start_node + i, num_global_nodes, comm_size)] += 3;
246
247 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
248
249 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
250 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
251 int send_accum = 0, recv_accum = 0;
252 for (int i = 0; i < comm_size; ++i) {
253 send_displ[i] = send_accum;
254 recv_displ[i] = recv_accum;
255 send_accum += send_count[i];
256 recv_accum += recv_count[i];
257 }
258
259 MPI_Alltoallv(read_node_coords, send_count, send_displ, MPI_DOUBLE,
260 dist_node_coords, recv_count, recv_displ, MPI_DOUBLE, comm);
261
262 free(recv_displ);
263 free(send_displ);
264 free(recv_count);
265 free(send_count);
266 free(read_node_coords);
267 }
268
269 // determine required nodes for core elements
270 // in additional compute elem_to_node, node_to_elem, and num_elem_per_node
271 size_t num_core_nodes;
272 {
273 size_t N = num_local_elems * num_nod_per_elem;
274 *node_ids = xmalloc(N * sizeof(**node_ids));
275 *num_elem_per_node = xmalloc(N * sizeof(**num_elem_per_node));
276 *elem_to_node = xmalloc(N * sizeof(**elem_to_node));
277 *node_to_elem = xmalloc(N * sizeof(**node_to_elem));
278 for (size_t i = 0; i < N; ++i)
279 (*node_ids)[i] = (yac_int)dist_elem_to_node[i];
280 size_t * permutation = *node_to_elem;
281 for (size_t i = 0; i < N; ++i) permutation[i] = i;
282 yac_quicksort_index_yac_int_size_t(*node_ids, N, permutation);
283 // remove duplicated core nodes and count number of elements per node
284 yac_int prev_node_id = YAC_INT_MAX;
285 num_core_nodes = 0;
286 for (size_t i = 0; i < N; ++i) {
287 yac_int curr_node_id = (*node_ids)[i];
288 if (prev_node_id == curr_node_id) {
289 (*num_elem_per_node)[num_core_nodes-1]++;
290 } else {
291 (*num_elem_per_node)[num_core_nodes] = 1;
292 (*node_ids)[num_core_nodes] = (prev_node_id = curr_node_id);
293 ++num_core_nodes;
294 }
295 (*elem_to_node)[permutation[i]] = num_core_nodes-1;
296 permutation[i] /= num_nod_per_elem;
297 }
298 *node_ids =
299 xrealloc(*node_ids, num_core_nodes * sizeof(**node_ids));
300 *num_elem_per_node =
301 xrealloc(*num_elem_per_node,
302 num_core_nodes * sizeof(**num_elem_per_node));
303 free(dist_elem_to_node);
304 }
305
306 // get node coordinate data
307 {
308 *node_coords = xmalloc(num_core_nodes * sizeof(**node_coords));
309 int * send_count = xcalloc(comm_size, sizeof(*send_count));
310 int * recv_count = xcalloc(comm_size, sizeof(*recv_count));
311
312 for (size_t i = 0; i < num_core_nodes; ++i)
313 send_count[
315 (*node_ids)[i], num_global_nodes, comm_size)]++;
316
317 MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
318
319 int * send_displ = xmalloc(comm_size * sizeof(*send_displ));
320 int * recv_displ = xmalloc(comm_size * sizeof(*recv_displ));
321 int send_accum = 0, recv_accum = 0;
322 for (int i = 0; i < comm_size; ++i) {
323 send_displ[i] = send_accum;
324 recv_displ[i] = recv_accum;
325 send_accum += send_count[i];
326 recv_accum += recv_count[i];
327 }
328
329 int num_all_local_nodes_remote = 0;
330 for (int i = 0; i < comm_size; ++i)
331 num_all_local_nodes_remote += recv_count[i];
332
333 yac_int * remote_node_buffer =
334 xmalloc(num_all_local_nodes_remote * sizeof(*remote_node_buffer));
335
336 MPI_Alltoallv(
337 *node_ids, send_count, send_displ, yac_int_dt,
338 remote_node_buffer, recv_count, recv_displ, yac_int_dt, comm);
339
340 yac_coordinate_pointer send_node_coords =
341 xmalloc(num_all_local_nodes_remote * sizeof(*send_node_coords));
342
343 for (int i = 0, l = 0; i < comm_size; ++i) {
344 for (int j = 0; j < recv_count[i]; ++j, ++l) {
345 size_t idx = (size_t)(remote_node_buffer[l]) - local_start_node;
346 send_node_coords[l][0] = dist_node_coords[idx][0];
347 send_node_coords[l][1] = dist_node_coords[idx][1];
348 send_node_coords[l][2] = dist_node_coords[idx][2];
349 }
350 send_count[i] *= 3;
351 recv_count[i] *= 3;
352 send_displ[i] *= 3;
353 recv_displ[i] *= 3;
354 }
355
356 free(remote_node_buffer);
357 free(dist_node_coords);
358
359 MPI_Alltoallv(send_node_coords, recv_count, recv_displ, MPI_DOUBLE,
360 *node_coords, send_count, send_displ, MPI_DOUBLE, comm);
361
362 free(send_node_coords);
363 free(recv_displ);
364 free(send_displ);
365 free(recv_count);
366 free(send_count);
367 }
368
369 // generate elem ids for local partition
370 *elem_ids = xmalloc(num_local_elems * sizeof(**elem_ids));
371 for (size_t i = 0; i < num_local_elems; ++i)
372 (*elem_ids)[i] = (yac_int)(local_start_elem + i);
373
374 // generate num_nodes_per_elem
375 *num_nodes_per_elem =
376 xmalloc(num_local_elems * sizeof(**num_nodes_per_elem));
377 for (size_t i = 0; i < num_local_elems; ++i)
378 (*num_nodes_per_elem)[i] = num_nod_per_elem;
379
380 *num_elem = num_local_elems;
381 *num_nodes = num_core_nodes;
382}
383
384struct temp_edge {
385 size_t node[2];
387};
388
389static int compare_temp_edges(void const * a, void const * b) {
390
391 struct temp_edge const * edge_a = (struct temp_edge const *)a;
392 struct temp_edge const * edge_b = (struct temp_edge const *)b;
393
394 if (edge_a->node[0] != edge_b->node[0])
395 return (edge_a->node[0] > edge_b->node[0])?1:-1;
396 return (edge_a->node[1] > edge_b->node[1]) -
397 (edge_a->node[1] < edge_b->node[1]);
398}
399
400static int check_pole(double * vertex) {
401
402 return fabs(1.0 - fabs(vertex[2])) < 1e-8;
403}
404
405static int check_lon_edge(double * vertex_a_, double * vertex_b_) {
406
407 double vertex_a[3] = {vertex_a_[0], vertex_a_[1], 0.0};
408 double vertex_b[3] = {vertex_b_[0], vertex_b_[1], 0.0};
409
410 normalise_vector(vertex_a);
411 normalise_vector(vertex_b);
412
413 return get_vector_angle(vertex_a, vertex_b) < 1e-6;
414}
415
416static int check_lat_edge(double * vertex_a, double * vertex_b) {
417
418 return fabs(acos(vertex_a[2]) - acos(vertex_b[2])) < 1e-6;
419}
420
422 const char * filename, int use_ll_edges, MPI_Comm comm) {
423
424 yac_coordinate_pointer node_coords;
425 yac_int * elem_ids;
426 yac_int * node_ids;
427 size_t num_elem;
428 size_t num_nodes;
429 int * num_nodes_per_elem;
430 int * num_elem_per_node;
431 size_t * elem_to_node;
432 size_t * node_to_elem;
433
435 filename, comm, &node_coords, &elem_ids, &node_ids, &num_elem, &num_nodes,
436 &num_nodes_per_elem, &num_elem_per_node, &elem_to_node, &node_to_elem);
437
438 size_t num_edges;
439 size_t * elem_to_edge;
440 yac_size_t_2_pointer edge_to_node;
442
443 { // compute edge data
444
445 // compute the maximum number of edge
446 size_t max_num_edges = 0;
447 for (size_t i = 0; i < num_elem; ++i)
448 max_num_edges += num_nodes_per_elem[i];
449
450 // generate temporary array containing edge information
451 struct temp_edge * temp_edges =
452 xmalloc(max_num_edges * sizeof(*temp_edges));
453 for (size_t i = 0, offset = 0, k = 0; i < num_elem; ++i) {
454 size_t * curr_elem_to_node = elem_to_node + offset;
455 size_t curr_num_edges = num_nodes_per_elem[i];
456 offset += curr_num_edges;
457 for (size_t j = 0; j < curr_num_edges; ++j, ++k) {
458 int order =
459 curr_elem_to_node[j] > curr_elem_to_node[(j+1)%curr_num_edges];
460 temp_edges[k].node[order] = curr_elem_to_node[j];
461 temp_edges[k].node[order^1] = curr_elem_to_node[(j+1)%curr_num_edges];
462 temp_edges[k].elem_to_edge_idx = k;
463 }
464 }
465 qsort(temp_edges, max_num_edges,
466 sizeof(*temp_edges), compare_temp_edges);
467
468 // generate elem_to_edge and edge_to_node; count total number of edges
469 elem_to_edge = xmalloc(max_num_edges * sizeof(*elem_to_edge));
470 num_edges = 0;
471 edge_to_node = (yac_size_t_2_pointer)temp_edges;
472 for (size_t i = 0, prev_indices[2] = {SIZE_MAX, SIZE_MAX};
473 i < max_num_edges; ++i) {
474
475 size_t curr_elem_to_edge_idx = temp_edges[i].elem_to_edge_idx;
476 if ((prev_indices[0] != temp_edges[i].node[0]) ||
477 (prev_indices[1] != temp_edges[i].node[1])) {
478
479 prev_indices[0] = temp_edges[i].node[0];
480 prev_indices[1] = temp_edges[i].node[1];
481 edge_to_node[num_edges][0] = prev_indices[0];
482 edge_to_node[num_edges][1] = prev_indices[1];
483 ++num_edges;
484 }
485
486 elem_to_edge[curr_elem_to_edge_idx] = num_edges - 1;
487 }
488 edge_to_node =
489 xrealloc(edge_to_node, num_edges * sizeof(*edge_to_node));
490
491 edge_type = xmalloc(num_edges * sizeof(*edge_type));
492 if (use_ll_edges) {
493 for (size_t i = 0; i < num_edges; ++i) {
494 double * edge_vertex_a = node_coords[edge_to_node[i][0]];
495 double * edge_vertex_b = node_coords[edge_to_node[i][1]];
496 int vertex_a_is_pole = check_pole(edge_vertex_a);
497 int vertex_b_is_pole = check_pole(edge_vertex_b);
498 int is_lon_edge =
499 (vertex_a_is_pole ^ vertex_b_is_pole) ||
500 (!vertex_a_is_pole && !vertex_b_is_pole &&
501 check_lon_edge(edge_vertex_a, edge_vertex_b));
502 int is_lat_edge =
503 (vertex_a_is_pole && vertex_b_is_pole) ||
504 check_lat_edge(edge_vertex_a, edge_vertex_b);
506 is_lon_edge || is_lat_edge,
507 "\"use_ll_edges == true\" but edge is neither lon nor lat "
508 "((%lf,%lf,%lf),(%lf,%lf,%lf))",
509 edge_vertex_a[0], edge_vertex_a[1], edge_vertex_a[2],
510 edge_vertex_b[0], edge_vertex_b[1], edge_vertex_b[2]);
511 edge_type[i] = (is_lon_edge)?YAC_LON_CIRCLE_EDGE:YAC_LAT_CIRCLE_EDGE;
512 }
513 } else {
514 for (size_t i = 0; i < num_edges; ++i)
515 edge_type[i] = YAC_GREAT_CIRCLE_EDGE;
516 }
517 }
518
520 grid_data.vertex_coordinates = node_coords;
521 grid_data.cell_ids = elem_ids;
522 grid_data.vertex_ids = node_ids;
523 grid_data.edge_ids = NULL;
524 grid_data.num_cells = num_elem;
525 grid_data.num_vertices = num_nodes;
526 grid_data.num_edges = num_edges;
527 grid_data.core_cell_mask = NULL;
528 grid_data.core_vertex_mask = NULL;
529 grid_data.core_edge_mask = NULL;
530 grid_data.num_vertices_per_cell = num_nodes_per_elem;
531 grid_data.num_cells_per_vertex = num_elem_per_node;
532 grid_data.cell_to_vertex = elem_to_node;
533 grid_data.cell_to_vertex_offsets = generate_offsets(num_elem, num_nodes_per_elem);
534 grid_data.cell_to_edge = elem_to_edge;
535 grid_data.cell_to_edge_offsets = grid_data.cell_to_vertex_offsets;
536 grid_data.vertex_to_cell = node_to_elem;
537 grid_data.vertex_to_cell_offsets = generate_offsets(num_nodes, num_elem_per_node);
538 grid_data.edge_to_vertex = edge_to_node;
539 grid_data.edge_type = edge_type;
540 grid_data.num_total_cells = num_elem;
541 grid_data.num_total_vertices = num_nodes;
542 grid_data.num_total_edges = num_edges;
543
544 return grid_data;
545}
546
548 char const * filename, char const * gridname, int use_ll_edges,
549 MPI_Comm comm) {
550
551 return
553 gridname,
554 yac_read_exodus_basic_grid_data_parallel(filename, use_ll_edges, comm));
555}
556
557#else
558
560 const char * filename, MPI_Comm comm, yac_coordinate_pointer * node_coords,
561 yac_int ** elem_ids, yac_int ** node_ids,
562 size_t * num_elem, size_t * num_nodes,
563 int ** num_nodes_per_elem, int ** num_elem_per_node,
564 size_t ** elem_to_node, size_t ** node_to_elem) {
565
566 UNUSED(filename);
567 UNUSED(comm);
568 UNUSED(node_coords);
569 UNUSED(elem_ids);
570 UNUSED(node_ids);
571 UNUSED(num_elem);
572 UNUSED(num_nodes);
573 UNUSED(num_nodes_per_elem);
574 UNUSED(num_elem_per_node);
575 UNUSED(elem_to_node);
576 UNUSED(node_to_elem);
577 die(
578 "ERROR(yac_read_exodus_grid_information_parallel): "
579 "YAC is built without the NetCDF support");
580}
581
583 const char * filename, int use_ll_edges, MPI_Comm comm) {
584
585 UNUSED(filename);
586 UNUSED(use_ll_edges);
587 UNUSED(comm);
588 die(
589 "ERROR(yac_read_exodus_basic_grid_data_parallel): "
590 "YAC is built without the NetCDF support");
591
592 return
594 (size_t[]){0,0}, (int[]){0,0}, NULL, NULL);
595}
596
598 char const * filename, char const * gridname, int use_ll_edges,
599 MPI_Comm comm) {
600
601 UNUSED(filename);
602 UNUSED(gridname);
603 UNUSED(use_ll_edges);
604 UNUSED(comm);
605 die(
606 "ERROR(yac_read_exodus_basic_grid_parallel): "
607 "YAC is built without the NetCDF support");
608
609 return NULL;
610}
611
612#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
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
#define UNUSED(x)
Definition core.h:72
static void normalise_vector(double v[])
Definition geometry.h:754
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:472
yac_edge_type
Definition grid_cell.h:12
@ YAC_GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:13
@ YAC_LAT_CIRCLE_EDGE
latitude circle
Definition grid_cell.h:14
@ YAC_LON_CIRCLE_EDGE
longitude circle
Definition grid_cell.h:15
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
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:344
#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
static int partition_idx_from_element_idx(size_t element_idx, size_t num_elements, int num_partitions)
void yac_read_exodus_grid_information_parallel(const char *filename, MPI_Comm comm, yac_coordinate_pointer *node_coords, yac_int **elem_ids, yac_int **node_ids, size_t *num_elem, size_t *num_nodes, int **num_nodes_per_elem, int **num_elem_per_node, size_t **elem_to_node, size_t **node_to_elem)
static int check_lon_edge(double *vertex_a_, double *vertex_b_)
static size_t * generate_offsets(size_t N, int *counts)
static int check_lat_edge(double *vertex_a, double *vertex_b)
static int check_pole(double *vertex)
struct yac_basic_grid * yac_read_exodus_basic_grid_parallel(char const *filename, char const *gridname, int use_ll_edges, MPI_Comm comm)
static int compare_temp_edges(void const *a, void const *b)
struct yac_basic_grid_data yac_read_exodus_basic_grid_data_parallel(const char *filename, int use_ll_edges, MPI_Comm comm)
size_t vertex[2]
size_t node[2]
size_t elem_to_edge_idx
enum yac_edge_type * edge_type
#define N
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
void yac_quicksort_index_yac_int_size_t(yac_int *a, size_t n, size_t *idx)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define die(msg)
Definition yac_assert.h:14
#define YAC_MPI_SIZE_T
YAC_INT yac_int
Definition yac_types.h:15
size_t(* yac_size_t_2_pointer)[2]
Definition yac_types.h:25
#define yac_int_dt
Definition yac_types.h:18
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21