YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_dist_grid_pair_parallel.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <mpi.h>
7#include <yaxt.h>
8#include <netcdf.h>
9#include <string.h>
10
11#include "tests.h"
12#include "test_common.h"
13#include "geometry.h"
14#include "read_icon_grid.h"
16#include "yac_mpi.h"
17#include "dist_grid_utils.h"
18#include "io_utils.h"
19
25static void utest_get_basic_grid_data(
26 char * filename, size_t * num_cells, size_t * num_vertices,
27 size_t * num_edges);
28
29static void utest_check_indices(
30 const_yac_int_pointer ids, size_t * indices,
31 size_t count, size_t global_count);
32
33static void utest_check_global_ids(
34 yac_int const * ids, size_t count,
35 int * mask, int global_count,
36 int * core_mask, MPI_Comm comm);
37
38static void utest_check_unmasked_global_ids(
39 yac_int const * ids, size_t count,
40 int * mask, int global_count,
41 int * global_core_mask, MPI_Comm comm);
42
43static void utest_check_dist_owner(
44 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
45 enum yac_location location, size_t global_size, int * core_mask,
46 int with_cell_ids, MPI_Comm comm);
47
48int main(int argc, char** argv) {
49
50 MPI_Init(NULL, NULL);
51
52 xt_initialize(MPI_COMM_WORLD);
53
54 set_even_io_rank_list(MPI_COMM_WORLD);
55
56 int comm_rank, comm_size;
57 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
58 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
59
60 {
61 if (argc != 2) {
62 PUT_ERR("ERROR: missing grid file directory");
63 xt_finalize();
64 MPI_Finalize();
65 return TEST_EXIT_CODE;
66 }
67
68 char * filenames[2];
69 char * grid_filenames[] =
70 {"icon_grid_0030_R02B03_G.nc", "icon_grid_0043_R02B04_G.nc"};
71 for (int i = 0; i < 2; ++i)
72 filenames[i] =
73 strcat(
74 strcpy(
75 malloc(strlen(argv[1]) + strlen(grid_filenames[i]) + 2), argv[1]),
76 grid_filenames[i]);
77
79 char const * grid_names[2] = {"grid_1", "grid2"};
80
81 for (int i = 0; i < 2; ++i)
82 grid_data[i] =
83 yac_read_icon_basic_grid_data_parallel(filenames[i], MPI_COMM_WORLD);
84
85 // generate edge coordinates
86 yac_coordinate_pointer edge_coordinates[2];
87 for (int i = 0; i < 2; ++i) {
88
89 edge_coordinates[i] =
90 xmalloc(grid_data[i].num_edges * sizeof(**edge_coordinates));
91 for (size_t j = 0; j < grid_data[i].num_edges; ++j) {
92
93 for (size_t k = 0; k < 3; ++k)
94 edge_coordinates[i][j][k] =
96 grid_data[i].edge_to_vertex[j][0]][k] +
98 grid_data[i].edge_to_vertex[j][1]][k];
99 normalise_vector(edge_coordinates[i][j]);
100 }
101 }
102
103 struct yac_basic_grid * grids[2] =
106
107 struct yac_interp_field edge_field[2];
108 for (int i = 0; i < 2; ++i) {
109 edge_field[i].location = YAC_LOC_EDGE;
110 edge_field[i].coordinates_idx =
112 grids[i], YAC_LOC_EDGE, edge_coordinates[i], grid_data[i].num_edges);
113 edge_field[i].masks_idx = SIZE_MAX;
114 }
115
116 yac_coordinate_pointer search_coordinates[2];
117 size_t num_search_coords[2];
118 for (int i = 0; i < 2; ++i) {
119 search_coordinates[i] = edge_coordinates[i];
120 num_search_coords[i] = grid_data[i].num_edges / 32;
121 for (size_t j = 0; j < num_search_coords[i]; ++j)
122 for (int k = 0; k < 3; ++k)
123 search_coordinates[i][j][k] =
124 search_coordinates[i][32 * j][k];
125 search_coordinates[i] =
126 realloc(
127 search_coordinates[i],
128 num_search_coords[i] * sizeof(*search_coordinates[i]));
129 }
130
131 struct {
132 yac_int * global_ids;
133 int * core_mask;
134 } global_ids[2][3];
135
136 for (int i = 0; i < 2; ++i) {
137 global_ids[i][0].global_ids = grid_data[i].cell_ids;
138 global_ids[i][0].core_mask = grid_data[i].core_cell_mask;
139 global_ids[i][1].global_ids = grid_data[i].vertex_ids;
140 global_ids[i][1].core_mask = grid_data[i].core_vertex_mask;
141 global_ids[i][2].global_ids = grid_data[i].edge_ids;
142 global_ids[i][2].core_mask = grid_data[i].core_edge_mask;
143 }
144
145 for (int k = 0; k < 8; ++k) {
146
147 for (int i = 0; i < 2; ++i) {
148 struct yac_basic_grid_data * curr_basic_grid_data =
150 if (k & (1 << 0)) {
151 curr_basic_grid_data->cell_ids = NULL;
152 curr_basic_grid_data->core_cell_mask = NULL;
153 } else {
154 curr_basic_grid_data->cell_ids = global_ids[i][0].global_ids;
155 curr_basic_grid_data->core_cell_mask = global_ids[i][0].core_mask;
156 }
157 if (k & (1 << 1)) {
158 curr_basic_grid_data->vertex_ids = NULL;
159 curr_basic_grid_data->core_vertex_mask = NULL;
160 } else {
161 curr_basic_grid_data->vertex_ids = global_ids[i][1].global_ids;
162 curr_basic_grid_data->core_vertex_mask = global_ids[i][1].core_mask;
163 }
164 if (k & (1 << 2)) {
165 curr_basic_grid_data->edge_ids = NULL;
166 curr_basic_grid_data->core_edge_mask = NULL;
167 } else {
168 curr_basic_grid_data->edge_ids = global_ids[i][2].global_ids;
169 curr_basic_grid_data->core_edge_mask = global_ids[i][2].core_mask;
170 }
171 }
172
173 struct yac_dist_grid_pair * grid_pair =
174 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
175
176 for (int i = 0; i < 2; ++i) {
177
178 // test yac_dist_grid_pair_get_dist_grid
179 struct yac_dist_grid * dist_grid =
181
182 enum yac_location locations[] =
184 size_t counts[3];
185
186 utest_get_basic_grid_data(filenames[i], &counts[0], &counts[1], &counts[2]);
187
188 const struct yac_const_basic_grid_data * dist_grid_data =
190
192 {dist_grid_data->ids[YAC_LOC_CELL],
193 dist_grid_data->ids[YAC_LOC_CORNER],
194 dist_grid_data->ids[YAC_LOC_EDGE]};
195
196 for (size_t j = 0; j < 3; ++j) {
197
198 // test yac_dist_grid_get_local_count
199 uint64_t local_count =
200 (uint64_t)yac_dist_grid_get_local_count(dist_grid, locations[j]);
201
202 uint64_t global_count;
203 MPI_Allreduce(
204 &local_count, &global_count, 1, MPI_UINT64_T, MPI_SUM,
205 MPI_COMM_WORLD);
206 if ((uint64_t)(counts[j]) != global_count)
207 PUT_ERR("error in yac_dist_grid_get_local_count\n");
208
209 // test yac_dist_grid_get_local_unmasked_points
210 size_t * indices, count;
212 dist_grid, (struct yac_interp_field){.location = locations[j],
213 .coordinates_idx = SIZE_MAX,
214 .masks_idx = SIZE_MAX},
215 &indices, &count);
216
217 if (count != local_count)
218 PUT_ERR("error in yac_dist_grid_get_local_unmasked_points\n");
219
220 utest_check_indices(ids[j], indices, count, counts[j]);
221
222 free(indices);
223 }
224
225 // test yac_dist_grid_pair_do_nnn_search
226 size_t * result_ids =
227 malloc(1 * num_search_coords[i^1] * sizeof(*result_ids));
229 grid_pair, grid_names[i], search_coordinates[i^1],
230 num_search_coords[i^1], result_ids, 1, edge_field[i], M_PI);
231 free(result_ids);
232 }
233
234 yac_dist_grid_pair_delete(grid_pair);
235
236 for (int i = 0; i < 2; ++i) {
237 struct yac_basic_grid_data * curr_basic_grid_data =
239 if (k & (1 << 0)) {
240 free(curr_basic_grid_data->cell_ids);
241 free(curr_basic_grid_data->core_cell_mask);
242 curr_basic_grid_data->cell_ids = NULL;
243 curr_basic_grid_data->core_cell_mask = NULL;
244 }
245 if (k & (1 << 1)) {
246 free(curr_basic_grid_data->vertex_ids);
247 free(curr_basic_grid_data->core_vertex_mask);
248 curr_basic_grid_data->vertex_ids = NULL;
249 curr_basic_grid_data->core_vertex_mask = NULL;
250 }
251 if (k & (1 << 2)) {
252 free(curr_basic_grid_data->edge_ids);
253 free(curr_basic_grid_data->core_edge_mask);
254 curr_basic_grid_data->edge_ids = NULL;
255 curr_basic_grid_data->core_edge_mask = NULL;
256 }
257 }
258 }
259
260 for (int i = 0; i < 2; ++i) {
262 for (int j = 0; j < 3; ++j) {
263 free(global_ids[i][j].global_ids);
264 free(global_ids[i][j].core_mask);
265 }
266 free(filenames[i]);
267 free(search_coordinates[i]);
268 }
269 }
270
271 if (comm_size >= 4) { // test with artificial grids
272
273 // we only need 4 processes
274 int do_test = comm_rank < 4;
275 MPI_Comm comm;
276 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
277
278 if (do_test) {
279
280 int comm_rank, comm_size;
281 MPI_Comm_rank(comm, &comm_rank);
282 MPI_Comm_size(comm, &comm_size);
283
284 int is_tgt = comm_rank >= 2;
285
286 double coordinates_x[2][5] = {{0.0,1.0,2.0,3.0,4.0}, {0.5,1.5,2.5,3.5,-1.0}};
287 double coordinates_y[2][4] = {{0.0,1.0,2.0,3.0}, {0.5,1.5,2.5,-1.0}};
288 size_t num_cells[2][2] = {{4,3},{3,2}};
289 size_t local_start[4][2] = {{0,0},{2,0},{0,0},{2,0}};
290 size_t local_count[4][2] = {{2,3},{2,3},{2,2},{1,2}};
291 int core_cell_mask[2][12] = {{0,0,0,0,
292 0,1,1,0,
293 0,0,0,0},
294 {0,0,0,
295 0,1,0}};
296 int core_vertex_mask[2][20] = {{0,0,0,0,0,
297 0,1,1,1,0,
298 0,1,1,1,0,
299 0,0,0,0,0},
300 {0,0,0,0,
301 0,1,1,0,
302 0,1,1,0}};
303 int core_edge_mask[2][31] = {{0,0,0,0,0,0,0,0,0,
304 0,0,1,1,1,1,0,1,0,
305 0,0,1,0,1,0,0,0,0,
306 0,0,0,0},
307 {0,0,0,0,0,0,0,
308 0,0,1,1,0,1,0,
309 0,1,0}};
310 int with_halo = 0;
311 for (int i = 0; i < 2; ++i){
312 for (int j = 0; j < 5; ++j) coordinates_x[i][j] *= YAC_RAD;
313 for (int j = 0; j < 4; ++j) coordinates_y[i][j] *= YAC_RAD;
314 }
315
318 coordinates_x[is_tgt], coordinates_y[is_tgt], num_cells[is_tgt],
319 local_start[comm_rank], local_count[comm_rank], with_halo);
320 for (size_t i = 0; i < grid_data.num_cells; ++i)
321 grid_data.core_cell_mask[i] =
322 core_cell_mask[is_tgt][grid_data.cell_ids[i]];
323 for (size_t i = 0; i < grid_data.num_vertices; ++i)
324 grid_data.core_vertex_mask[i] =
325 core_vertex_mask[is_tgt][grid_data.vertex_ids[i]];
326 for (size_t i = 0; i < grid_data.num_edges; ++i)
327 grid_data.core_edge_mask[i] =
328 core_edge_mask[is_tgt][grid_data.edge_ids[i]];
329 char const * grid_names[2] = {"src_grid", "tgt_grid"};
330 struct yac_basic_grid * grids[2] =
333
334 struct yac_dist_grid_pair * grid_pair =
335 yac_dist_grid_pair_new(grids[is_tgt], grids[is_tgt^1], comm);
336
337 // check dist owner information
338 {
339 size_t num_points[2][3] = {{12,20,31}, {6,12,17}};
340 enum yac_location locations[3] =
342 int * core_masks[2][3] =
343 {{core_cell_mask[0], core_vertex_mask[0], core_edge_mask[0]},
344 {core_cell_mask[1], core_vertex_mask[1], core_edge_mask[1]}};
345 for (int i = 0; i < 2; ++i)
346 for (int j = 0; j < 3; ++j)
347 utest_check_dist_owner(
348 grid_pair, grid_names[i], locations[j], num_points[i][j],
349 core_masks[i][j], 1, comm);
350 }
351
352 // check basic grid data of local part of the grid
353 {
354 int ref_num_cells[2] = {12, 6};
355 int ref_num_vertices[2] = {20, 12};
356 int ref_num_edges[2] = {31, 17};
357 int ref_cell_to_vertex[2][12][4] =
358 {{{0,1,6,5},{1,2,7,6},{2,3,8,7},{3,4,9,8},
359 {5,6,11,10},{6,7,12,11},{7,8,13,12},{8,9,14,13},
360 {10,11,16,15},{11,12,17,16},{12,13,18,17},{13,14,19,18}},
361 {{0,1,5,4},{1,2,6,5},{2,3,7,6},
362 {4,5,9,8},{5,6,10,9},{6,7,11,10}}};
363 int ref_cell_to_edge[2][12][4] =
364 {{{0,3,9,1},{2,5,11,3},{4,7,13,5},{6,8,15,7},
365 {9,12,18,10},{11,14,20,12},{13,16,22,14},{15,17,24,16},
366 {18,21,27,19},{20,23,28,21},{22,25,29,23},{24,26,30,25}},
367 {{0,3,7,1},{2,5,9,3},{4,6,11,5},
368 {7,10,14,8},{9,12,15,10},{11,13,16,12}}};
369 enum yac_edge_type ref_edge_type[2][31] =
383 int * core_masks[2][3] =
384 {{core_cell_mask[0], core_vertex_mask[0], core_edge_mask[0]},
385 {core_cell_mask[1], core_vertex_mask[1], core_edge_mask[1]}};
386
387 int cell_mask[12];
388 int vertex_mask[20];
389 int edge_mask[31];
390
391 for (int i = 0; i < 2; ++i) {
392
396
397 utest_check_global_ids(
399 cell_mask, ref_num_cells[i], core_masks[i][YAC_LOC_CELL], comm);
400 utest_check_global_ids(
402 vertex_mask, ref_num_vertices[i], core_masks[i][YAC_LOC_CORNER], comm);
403 utest_check_global_ids(
405 edge_mask, ref_num_edges[i], core_masks[i][YAC_LOC_EDGE], comm);
406
407 for (size_t j = 0; j < grid_data->count[YAC_LOC_CELL]; ++j) {
408
409 int curr_cell_id = (int)(grid_data->ids[YAC_LOC_CELL][j]);
410
411 if (grid_data->num_vertices_per_cell[j] != 4)
412 PUT_ERR("error in num_vertices_per_cell");
413
414 for (int k = 0; k < 4; ++k) {
415 if (ref_cell_to_vertex[i][curr_cell_id][k] !=
418 grid_data->cell_to_vertex_offsets[j]+k]])
419 PUT_ERR("error in cell_to_vertex");
420
421 if (ref_cell_to_edge[i][curr_cell_id][k] !=
423 grid_data->cell_to_edge[
424 grid_data->cell_to_edge_offsets[j]+k]])
425 PUT_ERR("error in cell_to_edge");
426 }
427 }
428
429 for (size_t j = 0; j < grid_data->count[YAC_LOC_EDGE]; ++j)
430 if (ref_edge_type[i][grid_data->ids[YAC_LOC_EDGE][j]] !=
431 grid_data->edge_type[j])
432 PUT_ERR("error in edge_type");
433
434 // check yac_dist_grid_get_local_unmasked_points
435 {
436 size_t * local_vertex_indices, local_vertex_count;
439 (struct yac_interp_field){.location = YAC_LOC_CORNER,
440 .coordinates_idx = SIZE_MAX,
441 .masks_idx = SIZE_MAX},
442 &local_vertex_indices, &local_vertex_count);
443
444 yac_int global_vertex_indices[20];
445
446 for (size_t j = 0; j < local_vertex_count; ++j)
447 global_vertex_indices[j] =
448 grid_data->ids[YAC_LOC_CORNER][local_vertex_indices[j]];
449
450 utest_check_unmasked_global_ids(
451 global_vertex_indices, local_vertex_count,
452 vertex_mask, ref_num_vertices[i], core_vertex_mask[i],
453 comm);
454
455 free(local_vertex_indices);
456 }
457
458 // check yac_dist_grid_global_to_local
459 {
460 yac_int global_edge_ids[ref_num_edges[i]];
461 size_t local_edge_ids[ref_num_edges[i]];
462 size_t edge_count = 0;
463 for (int j = 0; j < ref_num_edges[i]; ++j)
464 if (core_edge_mask[i][j])
465 global_edge_ids[edge_count++] = j;
466
469 YAC_LOC_EDGE, global_edge_ids, edge_count, local_edge_ids);
470
474
475 for (size_t j = 0; j < edge_count; ++j) {
476
477 if (grid_data->ids[YAC_LOC_EDGE][local_edge_ids[j]] !=
478 global_edge_ids[j])
479 PUT_ERR("ERROR in yac_dist_grid_global_to_local");
480
481 if (ref_edge_type[i][global_edge_ids[j]] !=
482 grid_data->edge_type[local_edge_ids[j]])
483 PUT_ERR("ERROR in yac_dist_grid_global_to_local");
484 }
485 }
486
487 // check yac_dist_grid_pair_get_corner_cells
488 {
489 size_t * local_vertex_indices, local_vertex_count;
492 (struct yac_interp_field){.location = YAC_LOC_CORNER,
493 .coordinates_idx = SIZE_MAX,
494 .masks_idx = SIZE_MAX},
495 &local_vertex_indices, &local_vertex_count);
496
497 size_t * vertex_to_cell;
498 size_t num_cells_per_vertex[20];
500 grid_pair, grid_names[i], local_vertex_indices,
501 local_vertex_count, &vertex_to_cell, num_cells_per_vertex);
502
503 yac_int const * global_corner_ids =
506 grid_pair, grid_names[i]))->ids[YAC_LOC_CORNER];
507 yac_int const * global_cell_ids =
510 grid_pair, grid_names[i]))->ids[YAC_LOC_CELL];
511
512 yac_int ref_corner_cells[2][20][4] =
513 {{{-1}, {-1}, {-1}, {-1}, {-1},
514 {-1}, {5}, {5,6}, {6}, {-1},
515 {-1}, {5}, {5,6}, {6}, {-1},
516 {-1}, {-1}, {-1}, {-1}, {-1}},
517 {{-1}, {-1}, {-1}, {-1},
518 {-1}, {4}, {4}, {-1},
519 {-1}, {4}, {4}, {-1}}};
520 size_t ref_num_cells_per_corner[2][20] =
521 {{0,0,0,0,0, 0,1,2,1,0, 0,1,2,1,0, 0,0,0,0,0},
522 {0,0,0,0, 0,1,1,0, 0,1,1,0}};
523
524 for (size_t j = 0, l = 0; j < local_vertex_count; ++j) {
525 if (ref_num_cells_per_corner[i][
526 global_corner_ids[local_vertex_indices[j]]] !=
527 num_cells_per_vertex[j])
528 PUT_ERR("ERROR in yac_dist_grid_pair_get_corner_cells");
529
530 for (size_t k = 0; k < num_cells_per_vertex[j]; ++k, ++l)
531 if (ref_corner_cells[i][
532 global_corner_ids[
533 local_vertex_indices[j]]][k] !=
534 global_cell_ids[vertex_to_cell[l]])
535 PUT_ERR("ERROR in yac_dist_grid_pair_get_corner_cells");
536 }
537
538 free(local_vertex_indices);
539 free(vertex_to_cell);
540 }
541 }
542 }
543
544 yac_dist_grid_pair_delete(grid_pair);
547 }
548
549 MPI_Comm_free(&comm);
550
551 } else {
552 PUT_ERR("insufficient number of processes");
553 }
554
555 if (comm_size >= 3) { // test with degenerated artificial grids
556
557 // we only need 3 processes
558 int do_test = comm_rank < 3;
559 MPI_Comm comm;
560 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
561
562 if (do_test) {
563
564 int comm_rank, comm_size;
565 MPI_Comm_rank(comm, &comm_rank);
566 MPI_Comm_size(comm, &comm_size);
567
568 int is_tgt = comm_rank == 2;
569
570 for (int with_cell_ids = 0; with_cell_ids < 2; ++with_cell_ids) {
571
573 if (is_tgt) {
574 size_t nbr_vertices[2] = {5, 2};
575 int cyclic[2] = {0,0};
576 double lon_vertices[] = {-2.0,-1.0,0.0,1.0,2.0};
577 double lat_vertices[] = {-0.5,0.5};
578 grid_data =
580 nbr_vertices, cyclic, lon_vertices, lat_vertices);
581 } else {
582 size_t nbr_vertices[2] = {7,8};
583 size_t nbr_cells[2] = {4,4};
584 int num_vertices_per_cell[2][4] = {{5,3,3,0}, {3,6,3,0}};
585 double x_vertices[2][8] = {{-1.5,-0.5,0.5,-2.0,0.0,-0.75,0.5},
586 {-0.5,0.5,1.5,0.0,2.0,-0.75,0.5,1.5}};
587 double y_vertices[2][8] = {{-0.5,-0.5,-0.5,0.0,0.0,0.5,0.5},
588 {-0.5,-0.5,-0.5,0.0,0.0,0.5,0.5,0.5}};
589 int cell_to_vertex[2][12] = {{0,1,4,5,3, 1,2,4, 4,6,5},
590 {0,1,3, 1,2,4,7,6,3, 3,6,5}};
591 static yac_int cell_ids[2][4] = {{0,1,2,4}, {1,3,2,4}};
592 static yac_int vertex_ids[2][8] = {{0,1,2,4,5,7,8}, {1,2,3,4,6,7,8,9}};
593 static yac_int edge_ids[2][10] = {{0,1,2,3,5,7,8,9,11}, {2,3,4,5,6,8,9,10,11,12}};
594 static int core_cell_mask[2][4] = {{1,0,0,1},{0,1,0,1}};
595 static int core_vertex_mask[2][8] = {{1,1,0,1,1,1,0},{0,1,1,1,1,0,1,1}};
596 static int core_edge_mask[2][10] = {{1,1,0,1,0,1,1,0,0}, {0,0,1,1,1,0,1,1,0,1}};
597 grid_data =
599 nbr_vertices[comm_rank], nbr_cells[comm_rank],
600 num_vertices_per_cell[comm_rank],
601 x_vertices[comm_rank], y_vertices[comm_rank],
602 cell_to_vertex[comm_rank]);
603
604 grid_data.cell_ids =
605 (with_cell_ids)?(TO_POINTER(cell_ids[comm_rank])):NULL;
606 grid_data.vertex_ids = TO_POINTER(vertex_ids[comm_rank]);
607 grid_data.edge_ids = TO_POINTER(edge_ids[comm_rank]);
608 grid_data.core_cell_mask = TO_POINTER(core_cell_mask[comm_rank]);
609 grid_data.core_vertex_mask = TO_POINTER(core_vertex_mask[comm_rank]);
610 grid_data.core_edge_mask = TO_POINTER(core_edge_mask[comm_rank]);
611 }
612
613 char const * grid_names[2] = {"src_grid", "tgt_grid"};
614 struct yac_basic_grid * grids[2] =
617
618 struct yac_dist_grid_pair * grid_pair =
619 yac_dist_grid_pair_new(grids[is_tgt], grids[is_tgt^1], comm);
620
621 // check dist owner information
622 {
623 size_t num_points[2][3] = {{5,10,13}, {4,10,13}};
624 enum yac_location locations[3] =
626 int core_masks[2][3][13] =
627 {{{1,0,0,1,1}, {1,1,1,1,1,1,1,1,1,1}, {1,1,0,1,1,1,1,1,1,1,1,0,1}},
628 {{1,1,1,1},
629 {1,1,1,1,1,1,1,1,1,1},
630 {1,1,1,1,1,1,1,1,1,1,1,1,1}}};
631 for (int i = 0; i < 2; ++i)
632 for (int j = 0; j < 3; ++j)
633 utest_check_dist_owner(
634 grid_pair, grid_names[i], locations[j], num_points[i][j],
635 core_masks[i][j], with_cell_ids, comm);
636 }
637
638 yac_dist_grid_pair_delete(grid_pair);
641
642 } // with_cell_ids
643 }
644
645 MPI_Comm_free(&comm);
646
647 } else {
648 PUT_ERR("insufficient number of processes");
649 }
650
651 // test on a single process
652 {
653
654 // we only need 1 processes
655 int do_test = comm_rank < 1;
656 MPI_Comm comm;
657 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
658
659 if (do_test) {
660
661 int comm_rank, comm_size;
662 MPI_Comm_rank(comm, &comm_rank);
663 MPI_Comm_size(comm, &comm_size);
664
665 double coordinates_x[2][5] = {{0.0,1.0,2.0,3.0,4.0}, {0.5,1.5,2.5,3.5,-1.0}};
666 double coordinates_y[2][4] = {{0.0,1.0,2.0,3.0}, {0.5,1.5,2.5,-1.0}};
667 size_t num_cells[2][2] = {{4,3},{3,2}};
668 size_t local_start[2][2] = {{0,0},{0,0}};
669 size_t local_count[2][2] = {{4,3},{3,2}};
670 int with_halo = 0;
671 for (int i = 0; i < 2; ++i){
672 for (int j = 0; j < 5; ++j) coordinates_x[i][j] *= YAC_RAD;
673 for (int j = 0; j < 4; ++j) coordinates_y[i][j] *= YAC_RAD;
674 }
675
679 local_start[0], local_count[0], with_halo),
682 local_start[1], local_count[1], with_halo)};
683 char const * grid_names[2] = {"src_grid", "tgt_grid"};
684 struct yac_basic_grid * grids[2] =
687
688
689 struct yac_dist_grid_pair * grid_pair =
691
692 // check basic grid data of local part of the grid
693 {
694 int ref_num_cells[2] = {12, 6};
695 int ref_num_vertices[2] = {20, 12};
696 int ref_num_edges[2] = {31, 17};
697 int ref_cell_to_vertex[2][12][4] =
698 {{{0,1,6,5},{1,2,7,6},{2,3,8,7},{3,4,9,8},
699 {5,6,11,10},{6,7,12,11},{7,8,13,12},{8,9,14,13},
700 {10,11,16,15},{11,12,17,16},{12,13,18,17},{13,14,19,18}},
701 {{0,1,5,4},{1,2,6,5},{2,3,7,6},
702 {4,5,9,8},{5,6,10,9},{6,7,11,10}}};
703 int ref_cell_to_edge[2][12][4] =
704 {{{0,3,9,1},{2,5,11,3},{4,7,13,5},{6,8,15,7},
705 {9,12,18,10},{11,14,20,12},{13,16,22,14},{15,17,24,16},
706 {18,21,27,19},{20,23,28,21},{22,25,29,23},{24,26,30,25}},
707 {{0,3,7,1},{2,5,9,3},{4,6,11,5},
708 {7,10,14,8},{9,12,15,10},{11,13,16,12}}};
709 enum yac_edge_type ref_edge_type[2][31] =
723
724 int cell_mask[12];
725 int vertex_mask[20];
726 int edge_mask[31];
727
728 for (int i = 0; i < 2; ++i) {
729
733
734 utest_check_global_ids(
736 cell_mask, ref_num_cells[i], NULL, comm);
737 utest_check_global_ids(
739 vertex_mask, ref_num_vertices[i], NULL, comm);
740 utest_check_global_ids(
742 edge_mask, ref_num_edges[i], NULL, comm);
743
744 for (size_t j = 0; j < grid_data->count[YAC_LOC_CELL]; ++j) {
745
746 int curr_cell_id = (int)(grid_data->ids[YAC_LOC_CELL][j]);
747
748 if (grid_data->num_vertices_per_cell[j] != 4)
749 PUT_ERR("error in num_vertices_per_cell");
750
751 for (int k = 0; k < 4; ++k) {
752 if (ref_cell_to_vertex[i][curr_cell_id][k] !=
755 grid_data->cell_to_vertex_offsets[j]+k]])
756 PUT_ERR("error in cell_to_vertex");
757
758 if (ref_cell_to_edge[i][curr_cell_id][k] !=
760 grid_data->cell_to_edge[
761 grid_data->cell_to_edge_offsets[j]+k]])
762 PUT_ERR("error in cell_to_edge");
763 }
764 }
765
766 for (size_t j = 0; j < grid_data->count[YAC_LOC_EDGE]; ++j)
767 if (ref_edge_type[i][grid_data->ids[YAC_LOC_EDGE][j]] !=
768 grid_data->edge_type[j])
769 PUT_ERR("error in edge_type");
770 }
771 }
772
773 yac_dist_grid_pair_delete(grid_pair);
776 }
777
778 MPI_Comm_free(&comm);
779 }
780
781 // test on a single process
782 // (with hanging edge and vertex)
783 {
784
785 // we only need 1 processes
786 int do_test = comm_rank < 1;
787 MPI_Comm comm;
788 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
789
790 if (do_test) {
791
792 int comm_rank, comm_size;
793 MPI_Comm_rank(comm, &comm_rank);
794 MPI_Comm_size(comm, &comm_size);
795
796 double x_vertices[] = {0,1,2,3,0,1,2,3};
797 double y_vertices[] = {0,0,0,0,1,1,1,1};
798 int cell_to_vertex[][4] = {{0,1,5,4},{1,2,6,5},{2,3,7,6}};
799 int num_vertices_per_cell[] = {4,4,4};
800 size_t nbr_vertices = sizeof(x_vertices)/sizeof(x_vertices[0]);
801 size_t nbr_cells = sizeof(cell_to_vertex)/sizeof(cell_to_vertex[0]);
802
803 yac_int cell_ids[] = {0,1,2};
804 yac_int vertex_ids[] = {0,1,2,3,4,5,6,7};
805 yac_int edge_ids[] = {0,1,2,3,4,5,6,7,8,9};
806 int core_cell_mask[] = {0,1,0};
807 int core_vertex_mask[] = {0,1,1,1,0,1,1,1};
808 int core_edge_mask[] = {0,0,1,1,0,1,0,0,1,1};
809
811 char const * grid_names[2] = {"src_grid", "tgt_grid"};
812 struct yac_basic_grid * grids[2];
813
814 for (int i = 0; i < 2; ++i) {
815 grid_data[i] =
817 nbr_vertices, nbr_cells, num_vertices_per_cell,
818 x_vertices, y_vertices, (int*)cell_to_vertex);
819 grid_data[i].cell_ids = TO_POINTER(cell_ids);
820 grid_data[i].vertex_ids = TO_POINTER(vertex_ids);
821 grid_data[i].edge_ids = TO_POINTER(edge_ids);
822 grid_data[i].core_cell_mask = TO_POINTER(core_cell_mask);
823 grid_data[i].core_vertex_mask = TO_POINTER(core_vertex_mask);
824 grid_data[i].core_edge_mask = TO_POINTER(core_edge_mask);
826 }
827
828 struct yac_dist_grid_pair * grid_pair =
830
831 {
832 enum yac_location locations[3] =
834 size_t ref_local_count[] = {1, 6, 5};
835
836 for (int grid_idx = 0; grid_idx < 2; ++grid_idx) {
837
838 struct yac_dist_grid * dist_grid =
840
841 for (int i = 0; i < 3; ++i) {
842
843 if (ref_local_count[i] !=
845 PUT_ERR("ERROR in yac_dist_grid_get_local_count");
846 }
847 }
848 }
849
850 yac_dist_grid_pair_delete(grid_pair);
853 }
854
855 MPI_Comm_free(&comm);
856 }
857
858 // test on a single process
859 // (with duplicated cell)
860 {
861
862 // we only need 1 processes
863 int do_test = comm_rank < 1;
864 MPI_Comm comm;
865 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
866
867 if (do_test) {
868
869 int comm_rank, comm_size;
870 MPI_Comm_rank(comm, &comm_rank);
871 MPI_Comm_size(comm, &comm_size);
872
873 double x_vertices[] = {-1.0,0.0,1.0,-0.5,0.5,0.0};
874 double y_vertices[] = {0.0,0.0,0.0,1.0,1.0,2.0};
875 int cell_to_vertex[][3] = {{0,1,3},{1,2,4},{1,4,3},{3,4,5},{1,4,3}};
876 int num_vertices_per_cell[] = {3,3,3,3,3};
877 size_t nbr_vertices = sizeof(x_vertices)/sizeof(x_vertices[0]);
878 size_t nbr_cells = sizeof(cell_to_vertex)/sizeof(cell_to_vertex[0]);
879
880 yac_int cell_ids[] = {0,1,2,3,4};
881 int core_cell_mask[] = {1,1,1,1,0};
882
884 char const * grid_names[2] = {"src_grid", "tgt_grid"};
885 struct yac_basic_grid * grids[2];
886
887 for (int i = 0; i < 2; ++i) {
888 grid_data[i] =
890 nbr_vertices, nbr_cells, num_vertices_per_cell,
891 x_vertices, y_vertices, (int*)cell_to_vertex);
892 grid_data[i].cell_ids = TO_POINTER(cell_ids);
893 grid_data[i].core_cell_mask = TO_POINTER(core_cell_mask);
895 }
896
897 struct yac_dist_grid_pair * grid_pair =
899
900 yac_dist_grid_pair_delete(grid_pair);
903 }
904
905 MPI_Comm_free(&comm);
906 }
907
908 { // generation of edge_to_cell with regular grid containing a pole
909 MPI_Comm comm;
910 MPI_Comm_dup(MPI_COMM_WORLD, &comm);
911
912 double coordinates_x[] = {0.0, 0.1, 0.2, 0.3};
913 double coordinates_y[] = {-M_PI_2, 0.1-M_PI_2, 0.2-M_PI_2, 0.3-M_PI_2};
914 size_t num_vertices[] = {4,4};
915 int cyclic[] = {0,0};
916
917 int comm_rank, comm_size;
918 MPI_Comm_rank(comm, &comm_rank);
919 MPI_Comm_size(comm, &comm_size);
920
921 int is_tgt = comm_rank == 0;
922
926
927 char const * grid_names[2] = {"src_grid", "tgt_grid"};
928 struct yac_basic_grid * grids[2] =
931
932
933 struct yac_dist_grid_pair * grid_pair =
934 yac_dist_grid_pair_new(grids[is_tgt], grids[is_tgt^1], comm);
935
936 // testing yac_dist_grid_generate_edge_to_cell
937 // should complete successfully without crashing)
938 for (int i = 0; i < 2; ++i) {
939 yac_size_t_2_pointer edge_to_cell =
941 free(edge_to_cell);
942 }
943
944 yac_dist_grid_pair_delete(grid_pair);
947
948 MPI_Comm_free(&comm);
949 }
950
951 xt_finalize();
952
953 MPI_Finalize();
954
955 return TEST_EXIT_CODE;
956}
957
958static void utest_get_basic_grid_data(
959 char * filename, size_t * num_cells, size_t * num_vertices,
960 size_t * num_edges) {
961
962 int ncid;
963
964 yac_nc_open(filename, NC_NOWRITE, &ncid);
965
966 int dimid;
967 yac_nc_inq_dimid(ncid, "cell", &dimid);
968 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_cells));
969 yac_nc_inq_dimid(ncid, "vertex", &dimid);
970 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_vertices));
971 yac_nc_inq_dimid(ncid, "edge", &dimid);
972 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_edges));
973
974 YAC_HANDLE_ERROR(nc_close(ncid));
975}
976
977static void utest_check_indices(
978 const_yac_int_pointer ids, size_t * indices,
979 size_t count, size_t global_count) {
980
981 int comm_rank, comm_size;
982 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
983 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
984
985 size_t local_start =
986 (global_count * (size_t)comm_rank + (size_t)comm_size - 1) /
987 (size_t)comm_size;
988 size_t next_local_start =
989 (global_count * (size_t)(comm_rank + 1) + (size_t)comm_size - 1) /
990 (size_t)comm_size;
991 size_t local_size = next_local_start - local_start;
992
993 Xt_int * src_global_ids = xmalloc(count * sizeof(*src_global_ids));
994 for (size_t i = 0; i < count; ++i)
995 src_global_ids[i] = (Xt_int)(ids[indices[i]]);
996
997 struct Xt_stripe dst_stripe =
998 {.start = (Xt_int)local_start, .stride = 1, .nstrides = (int)local_size};
999
1000 Xt_idxlist src_idxlist = xt_idxvec_new(src_global_ids, (int)count);
1001 Xt_idxlist dst_idxlist = xt_idxstripes_new(&dst_stripe, 1);
1002 Xt_xmap xmap = xt_xmap_dist_dir_new(src_idxlist, dst_idxlist, MPI_COMM_WORLD);
1003 Xt_redist redist = xt_redist_p2p_new(xmap, Xt_int_dt);
1004
1005 Xt_int * collected_ids = xmalloc(local_size * sizeof(*collected_ids));
1006
1007 xt_redist_s_exchange1(redist, src_global_ids, collected_ids);
1008
1009 for (size_t i = 0; i < local_size; ++i)
1010 if (collected_ids[i] != (Xt_int)(i + local_start)) PUT_ERR("missing id");
1011
1012 free(collected_ids);
1013 xt_redist_delete(redist);
1014 xt_xmap_delete(xmap);
1015 xt_idxlist_delete(dst_idxlist);
1016 xt_idxlist_delete(src_idxlist);
1017 free(src_global_ids);
1018}
1019
1020static void utest_check_global_ids(yac_int const * ids, size_t count,
1021 int * mask, int global_count,
1022 int * core_mask, MPI_Comm comm) {
1023
1024 for (int i = 0; i < global_count; ++i) mask[i] = 0;
1025
1026 for (size_t i = 0; i < count; ++i) mask[ids[i]] = 1;
1027
1028 MPI_Allreduce(MPI_IN_PLACE, mask, global_count, MPI_INT, MPI_MAX, comm);
1029
1030 for (int i = 0; i < global_count; ++i) {
1031 if (((core_mask == NULL) || core_mask[i]) || core_mask == NULL) {
1032 if(!mask[i]) PUT_ERR("missing id");
1033 } else {
1034 if(mask[i]) PUT_ERR("masked id available");
1035 }
1036 }
1037}
1038
1039static void utest_check_unmasked_global_ids(yac_int const * ids, size_t count,
1040 int * mask, int global_count,
1041 int * global_core_mask, MPI_Comm comm) {
1042
1043 for (int i = 0; i < global_count; ++i) mask[i] = 0;
1044
1045 for (size_t i = 0; i < count; ++i) mask[ids[i]] = 1;
1046
1047 MPI_Allreduce(MPI_IN_PLACE, mask, global_count, MPI_INT, MPI_SUM, comm);
1048
1049 for (int i = 0; i < global_count; ++i) {
1050 if (mask[i] > 1) PUT_ERR("multiple owners");
1051 if (mask[i] != global_core_mask[i])
1052 PUT_ERR("masked data is owned by a process");
1053 }
1054}
1055
1056static void utest_check_dist_owner(
1057 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
1058 enum yac_location location, size_t global_size, int * core_mask,
1059 int with_cell_ids, MPI_Comm comm) {
1060
1063 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name));
1064
1065 size_t local_size = grid_data->count[location];
1066 yac_int const * local_ids = grid_data->ids[location];
1067
1068 size_t points[local_size];
1069 for (size_t i = 0; i < local_size; ++i) points[i] = i;
1070
1071 // request dist owners for all points in the local part of the dist grid
1072 int local_ranks[local_size];
1074 grid_pair, grid_name, points, local_size, location, local_ranks);
1075
1076 // combine the result from all processes
1077 int global_ranks[global_size];
1078 for (size_t i = 0; i < global_size; ++i) global_ranks[i] = INT_MAX;
1079 for (size_t i = 0; i < local_size; ++i)
1080 global_ranks[local_ids[i]] = local_ranks[i];
1081 MPI_Allreduce(
1082 MPI_IN_PLACE, global_ranks, (int)global_size, MPI_INT, MPI_MIN, comm);
1083
1084 // every unmasked point should be available on at least one process
1085 if (core_mask) {
1086 if (with_cell_ids) {
1087 for (size_t i = 0; i < global_size; ++i)
1088 if (((global_ranks[i] == INT_MAX) && core_mask[i]) ||
1089 ((global_ranks[i] != INT_MAX) && !core_mask[i]))
1090 PUT_ERR("ERROR in yac_dist_grid_pair_determine_dist_owner");
1091 } else {
1092 size_t num_unmasked = 0;
1093 size_t num_owners = 0;
1094 for (size_t i = 0; i < global_size; ++i) {
1095 if (core_mask[i]) ++num_unmasked;
1096 if (global_ranks[i] != INT_MAX) ++num_owners;
1097 }
1098 if (num_unmasked != num_owners)
1099 PUT_ERR("ERROR in yac_dist_grid_pair_determine_dist_owner");
1100 }
1101 } else {
1102 for (size_t i = 0; i < global_size; ++i)
1103 if (global_ranks[i] == INT_MAX)
1104 PUT_ERR("ERROR in yac_dist_grid_pair_determine_dist_owner");
1105 }
1106
1107 // for any point the dist owner should be the same on all ranks
1108 for (size_t i = 0; i < local_size; ++i)
1109 if (global_ranks[local_ids[i]] != local_ranks[i])
1110 PUT_ERR("ERROR in yac_dist_grid_pair_determine_dist_owner");
1111
1112 int comm_rank;
1113 MPI_Comm_rank(comm, &comm_rank);
1114
1115 // all points should be available on the dist owners
1116 for (size_t i = 0; i < global_size; ++i) {
1117 if (global_ranks[i] == comm_rank) {
1118 int found = 0;
1119 for(size_t j = 0; (j < local_size) && !found; ++j)
1120 if (local_ids[j] == (yac_int)i) found = 1;
1121 if (!found)
1122 PUT_ERR("ERROR in yac_dist_grid_pair_determine_dist_owner");
1123 }
1124 }
1125}
char const * grid_names[]
unsigned grid_idx[3]
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:50
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:137
size_t yac_basic_grid_add_coordinates(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
Definition basic_grid.c:232
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:63
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:70
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition grid_reg2d.c:65
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d_deg(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
Definition grid_reg2d.c:74
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2313
void yac_dist_grid_pair_determine_dist_owner(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *points, size_t count, enum yac_location location, int *ranks)
Definition dist_grid.c:6137
size_t yac_dist_grid_get_local_count(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2154
void yac_dist_grid_pair_do_nnn_search(struct yac_dist_grid_pair *grid_pair, char const *grid_name, yac_coordinate_pointer search_coords, size_t count, size_t *local_ids, size_t n, struct yac_interp_field field, double max_search_distance)
Definition dist_grid.c:4123
yac_size_t_2_pointer yac_dist_grid_generate_edge_to_cell(struct yac_dist_grid_pair *grid_pair, char const *grid_name)
Definition dist_grid.c:6282
struct yac_dist_grid * yac_dist_grid_pair_get_dist_grid(struct yac_dist_grid_pair *grid_pair, char const *grid_name)
Definition dist_grid.c:2134
struct yac_dist_grid_pair * yac_dist_grid_pair_new(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
Definition dist_grid.c:2061
void yac_dist_grid_get_local_unmasked_points(struct yac_dist_grid *dist_grid, struct yac_interp_field field, size_t **indices, size_t *num_indices)
Definition dist_grid.c:2205
struct yac_const_basic_grid_data * yac_dist_grid_get_basic_grid_data(struct yac_dist_grid *dist_grid)
Definition dist_grid.c:2146
void yac_dist_grid_global_to_local(struct yac_dist_grid *dist_grid, enum yac_location location, yac_int *global_ids, size_t count, size_t *local_ids)
Definition dist_grid.c:5264
void yac_dist_grid_pair_get_corner_cells(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *vertices, size_t count, size_t **vertex_to_cell, size_t *num_cells_per_vertex)
Definition dist_grid.c:5799
yac_int const * const_yac_int_pointer
struct yac_basic_grid_data yac_generate_basic_grid_data_reg2d(double const *global_coords_x, double const *global_coords_y, size_t const num_global_cells_[2], size_t const local_start[2], size_t const local_count[2], int with_halo)
#define YAC_RAD
static void normalise_vector(double v[])
Definition geometry.h:635
yac_edge_type
Definition grid_cell.h:12
@ YAC_LAT_CIRCLE_EDGE
latitude circle
Definition grid_cell.h:14
@ YAC_LON_CIRCLE_EDGE
longitude circle
Definition grid_cell.h:15
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:350
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:385
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct yac_basic_grid_data yac_read_icon_basic_grid_data_parallel(const char *filename, MPI_Comm comm)
yac_coordinate_pointer vertex_coordinates
yac_size_t_2_pointer edge_to_vertex
const const_int_pointer num_vertices_per_cell
const const_yac_int_pointer ids[3]
MPI_Comm comm
Definition dist_grid.c:116
int * num_vertices_per_cell
Definition dist_grid.c:90
enum yac_location location
Definition basic_grid.h:16
static enum yac_location locations[]
void set_even_io_rank_list(MPI_Comm comm)
#define TO_POINTER(a)
Definition test_common.h:14
int * cell_to_vertex
int * cell_mask
double coordinates_x[]
size_t num_cells[2]
double coordinates_y[]
unsigned cyclic[2]
static int mask[16]
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10
int const * location
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
static struct user_input_data_points ** points
Definition yac.c:158
static size_t num_points
Definition yac.c:159
struct yac_basic_grid ** grids
Definition yac.c:152
YAC_INT yac_int
Definition yac_types.h:15
size_t(* yac_size_t_2_pointer)[2]
Definition yac_types.h:23
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19