YetAnotherCoupler 3.1.1
Loading...
Searching...
No Matches
dist_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// Get the definition of the 'restrict' keyword.
7#include "config.h"
8#endif
9
10#include <stdlib.h>
11#include <string.h>
12#include <assert.h>
13#include <float.h>
14#include <yaxt.h>
15
16#include "basic_grid.h"
17#include "dist_grid_internal.h"
18#include "geometry.h"
19#include "yac_mpi_internal.h"
20#include "utils_core.h"
21#include "sphere_part.h"
22#include "proc_sphere_part.h"
23#include "ensure_array_size.h"
24#include "interp_grid.h"
25#include "field_data_set.h"
26
31
36
41
42// reorder_idx has to be first
49
50// reorder_idx has to be first
58
59struct id_pos {
61 uint64_t orig_pos;
62};
63
71
77
86
87// warning: when changing this, ensure that struct yac_const_basic_grid_data is
88// changed accordingly
109
118
123
125 struct {
126 size_t local_id;
129 size_t neigh_idx;
130};
131
132// looks up positions of ids in an array of sorted ids
133static void id2idx(
134 yac_int * ids, size_t * idx, size_t num_ids,
135 yac_int * ref_sorted_ids, size_t num_sorted_ids) {
136
137 size_t * reorder = xmalloc(num_ids * sizeof(*reorder));
138 for (size_t i = 0; i < num_ids; ++i) reorder[i] = i;
139
140 yac_quicksort_index_yac_int_size_t(ids, num_ids, reorder);
141
142 for (size_t i = 0, j = 0; i < num_ids; ++i) {
143
144 yac_int curr_id = ids[i];
145 while ((j < num_sorted_ids) && (ref_sorted_ids[j] < curr_id)) ++j;
147 (j < num_sorted_ids) && (ref_sorted_ids[j] == curr_id),
148 "ERROR(id2idx): id not found")
149 idx[reorder[i]] = j;
150 }
151
152 free(reorder);
153}
154
155// returns the index of the cell vertex with the lowest global id
157 struct yac_dist_grid * dist_grid, size_t cell_idx) {
158
159 int num_vertices = dist_grid->num_vertices_per_cell[cell_idx];
160 if (num_vertices == 0) return SIZE_MAX;
161 yac_int * grid_vertex_ids = dist_grid->ids[YAC_LOC_CORNER];
162 size_t * vertices =
163 dist_grid->cell_to_vertex + dist_grid->cell_to_vertex_offsets[cell_idx];
164 // get the cell corner with the smallest global id
165 size_t min_idx = vertices[0];
166 yac_int min_global_id = grid_vertex_ids[min_idx];
167 for (int j = 1; j < num_vertices; ++j) {
168 size_t curr_vertex = vertices[j];
169 yac_int curr_global_id = grid_vertex_ids[curr_vertex];
170 if (min_global_id > curr_global_id) {
171 min_global_id = curr_global_id;
172 min_idx = curr_vertex;
173 }
174 }
175 return min_idx;
176}
177
178// generate cell core mask (true for all cells belonging to the local part of
179// the distributed directory and the have a valid original owner)
181 struct yac_dist_grid * dist_grid, int is_root, int * vertex_owner_mask) {
182
183 size_t num_cells = dist_grid->count[YAC_LOC_CELL];
184 int * core_cell_mask = xmalloc(num_cells * sizeof(*core_cell_mask));
185
186 //-------------------------
187 // determine cell core mask
188 //-------------------------
189 for (size_t i = 0; i < num_cells; ++i) {
190 size_t ref_vertex = get_cell_reference_vertex(dist_grid, i);
191 core_cell_mask[i] =
192 (dist_grid->owners[YAC_LOC_CELL][i].count > 0) &&
193 ((ref_vertex != SIZE_MAX)?(vertex_owner_mask[ref_vertex]):is_root);
194 }
195 return core_cell_mask;
196}
197
198// returns the index of the edge vertex with the lowest global id
199static inline size_t get_edge_reference_vertex(
200 struct yac_dist_grid * dist_grid, size_t edge_idx) {
201
202 yac_int * vertex_ids = dist_grid->ids[YAC_LOC_CORNER];
203 size_t * edge_vertices = &(dist_grid->edge_to_vertex[edge_idx][0]);
204 // get the edge corner with the smallest global id
205 return edge_vertices[
206 (vertex_ids[edge_vertices[0]] > vertex_ids[edge_vertices[1]])?1:0];
207}
208
209// generate edge core mask (true for all edge belonging to the local part of
210// the distributed directory and the have a valid original owner)
212 struct yac_dist_grid * dist_grid, int * vertex_owner_mask) {
213
214 size_t num_edges = dist_grid->count[YAC_LOC_EDGE];
215 int * core_edge_mask = xmalloc(num_edges * sizeof(*core_edge_mask));
216
217 //-------------------------
218 // determine edge core mask
219 //-------------------------
220 for (size_t i = 0; i < num_edges; ++i)
221 core_edge_mask[i] =
222 (dist_grid->owners[YAC_LOC_EDGE][i].count > 0) &&
223 vertex_owner_mask[get_edge_reference_vertex(dist_grid, i)];
224 return core_edge_mask;
225}
226
227// generate core masks for cells, vertices and edges
229 struct yac_dist_grid * dist_grid,
230 struct proc_sphere_part_node * proc_sphere_part, int comm_rank) {
231
232 // determine distributed owner for vertices in the local part of the
233 // distributed grid
234 int * vertex_owner_mask =
235 xmalloc(dist_grid->count[YAC_LOC_CORNER] * sizeof(*vertex_owner_mask));
237 proc_sphere_part, dist_grid->vertex_coordinates,
238 dist_grid->count[YAC_LOC_CORNER], vertex_owner_mask);
239 for (size_t i = 0; i < dist_grid->count[YAC_LOC_CORNER]; ++i)
240 vertex_owner_mask[i] = vertex_owner_mask[i] == comm_rank;
241
242 // generate core mask for cells
243 dist_grid->core_mask[YAC_LOC_CELL] =
244 determine_cell_core_mask(dist_grid, comm_rank == 0, vertex_owner_mask);
245
246 // generate core mask for edges
247 dist_grid->core_mask[YAC_LOC_EDGE] =
248 determine_edge_core_mask(dist_grid, vertex_owner_mask);
249
250 // generate vertex core mask (true for vertices belonging to the local
251 // process and have an original owner)
252 for (size_t i = 0; i < dist_grid->count[YAC_LOC_CORNER]; ++i)
253 vertex_owner_mask[i] =
254 vertex_owner_mask[i] && (dist_grid->owners[YAC_LOC_CORNER][i].count > 0);
255 dist_grid->core_mask[YAC_LOC_CORNER] = vertex_owner_mask;
256}
257
258static MPI_Datatype yac_get_single_remote_point_mpi_datatype(MPI_Comm comm) {
259
260 struct single_remote_point dummy;
261 MPI_Datatype single_id_owner_dt;
262 int array_of_blocklengths[] = {1, 1, 1};
263 const MPI_Aint array_of_displacements[] =
264 {(MPI_Aint)(intptr_t)(const void *)&(dummy.global_id) -
265 (MPI_Aint)(intptr_t)(const void *)&dummy,
266 (MPI_Aint)(intptr_t)(const void *)&(dummy.data.rank) -
267 (MPI_Aint)(intptr_t)(const void *)&dummy,
268 (MPI_Aint)(intptr_t)(const void *)&(dummy.data.orig_pos) -
269 (MPI_Aint)(intptr_t)(const void *)&dummy};
270 const MPI_Datatype array_of_types[] =
271 {yac_int_dt, MPI_INT, MPI_UINT64_T};
273 MPI_Type_create_struct(3, array_of_blocklengths, array_of_displacements,
274 array_of_types, &single_id_owner_dt), comm);
275 return yac_create_resized(single_id_owner_dt, sizeof(dummy), comm);
276}
277
279 int n, MPI_Comm comm) {
280
281 MPI_Datatype dt_single_remote_point_ =
283 MPI_Datatype dt_single_remote_point__ =
285 dt_single_remote_point_, sizeof(struct single_remote_point_reorder), comm);
286 MPI_Datatype dt_single_remote_point;
288 MPI_Type_contiguous(
289 n, dt_single_remote_point__, &dt_single_remote_point), comm);
290 yac_mpi_call(MPI_Type_free(&dt_single_remote_point__), comm);
291 yac_mpi_call(MPI_Type_commit(&dt_single_remote_point), comm);
292 return dt_single_remote_point;
293}
294
296 const void * a, const void * b) {
297
298 return (((const struct single_remote_point *)a)->global_id >
299 ((const struct single_remote_point *)b)->global_id) -
300 (((const struct single_remote_point *)a)->global_id <
301 ((const struct single_remote_point *)b)->global_id);
302}
303
304static MPI_Datatype yac_get_id_pos_mpi_datatype(MPI_Comm comm) {
305
306 struct id_pos dummy;
307 MPI_Datatype id_pos_dt;
308 int array_of_blocklengths[] = {1,1};
309 const MPI_Aint array_of_displacements[] =
310 {(MPI_Aint)(intptr_t)(const void *)&(dummy.global_id) -
311 (MPI_Aint)(intptr_t)(const void *)&dummy,
312 (MPI_Aint)(intptr_t)(const void *)&(dummy.orig_pos) -
313 (MPI_Aint)(intptr_t)(const void *)&dummy};
314 const MPI_Datatype array_of_types[] = {yac_int_dt, MPI_UINT64_T};
316 MPI_Type_create_struct(
317 2, array_of_blocklengths, array_of_displacements,
318 array_of_types, &id_pos_dt), comm);
319 return yac_create_resized(id_pos_dt, sizeof(dummy), comm);
320}
321
322MPI_Datatype yac_get_remote_point_info_mpi_datatype(MPI_Comm comm) {
323
324 struct remote_point_info dummy;
325 MPI_Datatype remote_point_info_dt;
326 int array_of_blocklengths[] = {1, 1};
327 const MPI_Aint array_of_displacements[] =
328 {(MPI_Aint)(intptr_t)(const void *)&(dummy.rank) -
329 (MPI_Aint)(intptr_t)(const void *)&dummy,
330 (MPI_Aint)(intptr_t)(const void *)&(dummy.orig_pos) -
331 (MPI_Aint)(intptr_t)(const void *)&dummy};
332 const MPI_Datatype array_of_types[] =
333 {MPI_INT, MPI_UINT64_T};
335 MPI_Type_create_struct(2, array_of_blocklengths, array_of_displacements,
336 array_of_types, &remote_point_info_dt), comm);
337 return yac_create_resized(remote_point_info_dt, sizeof(dummy), comm);
338}
339
341 struct remote_point_infos point_infos) {
342
343 int count = point_infos.count;
344 if (count > 1) {
345 struct remote_point_info * temp = xmalloc((size_t)count * sizeof(*temp));
346 memcpy(temp, point_infos.data.multi, (size_t)count * sizeof(*temp));
347 point_infos.data.multi = temp;
348 }
349 return point_infos;
350}
351
353 yac_int * sorted_ids, size_t * reorder_idx, size_t count,
354 struct remote_points * points) {
355
356 struct remote_point_infos * point_infos = xmalloc(count * sizeof(*point_infos));
357
358 size_t id_owner_count = points->count;
359 struct remote_point * points_ = points->data;
360
361 for (size_t i = 0, j = 0; i < count; ++i) {
362
363 yac_int curr_id = sorted_ids[i];
364
365 while ((j < id_owner_count) && (points_[j].global_id < curr_id)) ++j;
366
367 if ((j >= id_owner_count) || (points_[j].global_id != curr_id))
368 point_infos[reorder_idx[i]].count = -1;
369 else
370 point_infos[reorder_idx[i]] = copy_remote_point_infos(points_[j].data);
371 }
372
373 return point_infos;
374}
375
377 yac_int * requested_ids, struct remote_point_infos ** results,
378 size_t * reorder_buffer, size_t request_count,
379 struct remote_points * local_remote_data) {
380
381 struct remote_point * local_remote_points = local_remote_data->data;
382 size_t local_count = local_remote_data->count;
383 static struct remote_point_infos dummy_data =
384 {.count = 0, .data.single = {.rank = INT_MAX, .orig_pos = UINT64_MAX}};
385
386 for (size_t j = 0; j < request_count; ++j) reorder_buffer[j] = j;
387
388 // sort ids for easier owner lookup
390 requested_ids, request_count, reorder_buffer);
391
392 for (size_t i = 0, j = 0; i < request_count; ++i) {
393 yac_int curr_id = requested_ids[i];
394 while ((j < local_count) && (curr_id > local_remote_points[j].global_id))
395 ++j;
396 results[reorder_buffer[i]] =
397 ((j < local_count) && (curr_id == local_remote_points[j].global_id))?
398 &(local_remote_points[j].data):&dummy_data;
399 }
400}
401
403 struct remote_point_infos const * infos, MPI_Datatype point_info_dt,
404 MPI_Comm comm) {
405
406 int pack_size_count,
407 pack_size_data;
408
409 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &pack_size_count), comm);
411 MPI_Pack_size(infos->count, point_info_dt, comm, &pack_size_data), comm);
412
413 return pack_size_count + pack_size_data;
414}
415
417 struct remote_point_infos ** infos, size_t count, int * pack_sizes,
418 MPI_Datatype point_info_dt, MPI_Comm comm) {
419
420 int pack_size_count;
421
422 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &pack_size_count), comm);
423
424 for (size_t i = 0; i < count; ++i) {
426 MPI_Pack_size(
427 infos[i]->count, point_info_dt, comm, pack_sizes + i), comm);
428 pack_sizes[i] += pack_size_count;
429 }
430}
431
433 struct remote_point_infos ** infos, int * pack_sizes, size_t count,
434 void * buffer, MPI_Datatype point_info_dt, MPI_Comm comm) {
435
436 for (size_t i = 0; i < count; ++i) {
437
438 int curr_count = infos[i]->count;
439 struct remote_point_info * curr_point_infos =
440 (curr_count == 1)?
441 (&(infos[i]->data.single)):(infos[i]->data.multi);
442
443 int position = 0;
444 int buffer_size = pack_sizes[i];
446 MPI_Pack(&curr_count, 1, MPI_INT, buffer,
447 buffer_size, &position, comm), comm);
449 MPI_Pack(curr_point_infos, curr_count, point_info_dt, buffer,
450 buffer_size, &position, comm), comm);
451 buffer = (void*)(((unsigned char*)buffer) + buffer_size);
452 }
453}
454
456 void * buffer, int buffer_size, int * position,
457 struct remote_point_infos * infos, MPI_Datatype point_info_dt, MPI_Comm comm) {
458
459 int count;
461 MPI_Unpack(buffer, buffer_size, position, &count, 1, MPI_INT, comm), comm);
462
463 infos->count = count;
464
465 if (count > 0) {
466 struct remote_point_info * point_infos;
467 if (count == 1)
468 point_infos = &(infos->data.single);
469 else
470 point_infos =
471 (infos->data.multi = xmalloc((size_t)count * sizeof(*point_infos)));
472
474 MPI_Unpack(buffer, buffer_size, position, point_infos, count,
475 point_info_dt, comm), comm);
476 } else {
477 infos->data.single.rank = INT_MAX;
478 infos->data.single.orig_pos = UINT64_MAX;
479 }
480}
481
483 void * buffer, int buffer_size, int * position,
484 struct remote_point_info * info_buffer, size_t * info_buffer_position,
485 struct remote_point_infos * infos, MPI_Datatype point_info_dt, MPI_Comm comm) {
486
487 int count;
489 MPI_Unpack(buffer, buffer_size, position, &count, 1, MPI_INT, comm), comm);
490
491 infos->count = count;
492
493 struct remote_point_info * point_infos;
494 if (count == 1)
495 point_infos = &(infos->data.single);
496 else {
497 point_infos =
498 (infos->data.multi = info_buffer + *info_buffer_position);
499 *info_buffer_position += count;
500 }
501
503 MPI_Unpack(buffer, buffer_size, position, point_infos, count,
504 point_info_dt, comm), comm);
505}
506
508 struct remote_point * point, MPI_Datatype point_info_dt, MPI_Comm comm) {
509
510 int pack_size_id,
511 pack_size_remote_point_infos;
512
513 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &pack_size_id), comm);
514 pack_size_remote_point_infos =
515 yac_remote_point_infos_get_pack_size(&(point->data), point_info_dt, comm);
516
517 return pack_size_id + pack_size_remote_point_infos;
518}
519
521 struct remote_point_infos const * infos, void * buffer, int buffer_size,
522 int * position, MPI_Datatype point_info_dt, MPI_Comm comm) {
523
524 int count = infos->count;
525
526 struct remote_point_info const * info =
527 (count == 1)?(&(infos->data.single)):(infos->data.multi);
528
530 MPI_Pack(&count, 1, MPI_INT, buffer, buffer_size, position, comm), comm);
532 MPI_Pack(info, count, point_info_dt, buffer, buffer_size, position, comm),
533 comm);
534}
535
537 struct remote_point * point, void * buffer, int buffer_size, int * position,
538 MPI_Datatype point_info_dt, MPI_Comm comm) {
539
541 MPI_Pack(&(point->global_id), 1, yac_int_dt, buffer,
542 buffer_size, position, comm), comm);
543
545 &(point->data), buffer, buffer_size, position, point_info_dt, comm);
546}
547
549 void * buffer, int buffer_size, int * position, struct remote_point * point,
550 MPI_Datatype point_info_dt, MPI_Comm comm) {
551
553 MPI_Unpack(
554 buffer, buffer_size, position, &(point->global_id), 1, yac_int_dt, comm),
555 comm);
557 buffer, buffer_size, position, &(point->data), point_info_dt, comm);
558}
559
561 void * buffer, int buffer_size, int * position,
562 struct remote_point_info * info_buffer, size_t * info_buffer_position,
563 struct remote_point * point, MPI_Datatype point_info_dt, MPI_Comm comm) {
564
566 MPI_Unpack(
567 buffer, buffer_size, position, &(point->global_id), 1, yac_int_dt, comm),
568 comm);
570 buffer, buffer_size, position, info_buffer, info_buffer_position,
571 &(point->data), point_info_dt, comm);
572}
573
575 struct remote_points * points, MPI_Datatype point_info_dt, MPI_Comm comm) {
576
577 size_t count = points->count;
578 struct remote_point * points_data = points->data;
579
580 int count_pack_size,
581 remote_points_pack_size;
582
583 yac_mpi_call(MPI_Pack_size(2, MPI_UINT64_T, comm, &count_pack_size), comm);
584 remote_points_pack_size = 0;
585 for (size_t i = 0; i < count; ++i)
586 remote_points_pack_size +=
587 yac_remote_point_get_pack_size(points_data + i, point_info_dt, comm);
588
589 return count_pack_size + remote_points_pack_size;
590}
591
593 struct remote_points * points, void * buffer, int buffer_size, int * position,
594 MPI_Datatype point_info_dt, MPI_Comm comm) {
595
596 size_t count = points->count;
597 struct remote_point * point_data = points->data;
598 uint64_t counts[2] = {(uint64_t)count, 0};
599 for (size_t i = 0; i < count; ++i)
600 if (point_data[i].data.count > 1)
601 counts[1] += (uint64_t)(point_data[i].data.count);
602
604 MPI_Pack(counts, 2, MPI_UINT64_T, buffer,
605 buffer_size, position, comm), comm);
606 for (size_t i = 0; i < count; ++i)
608 point_data + i, buffer, buffer_size, position, point_info_dt, comm);
609}
610
612 void * buffer, int buffer_size, int * position,
613 struct remote_points ** points, MPI_Datatype point_info_dt, MPI_Comm comm) {
614
615 uint64_t counts[2];
616
618 MPI_Unpack(
619 buffer, buffer_size, position, counts, 2, MPI_UINT64_T, comm), comm);
620
621 *points = xmalloc(((size_t)counts[1]) * sizeof(struct remote_point_infos) +
622 sizeof(**points));
623
624 size_t count = ((*points)->count = (size_t)(counts[0]));
625 struct remote_point * point_data =
626 ((*points)->data = xmalloc(count * sizeof(*((*points)->data))));
627 struct remote_point_info * remote_point_info_buffer =
628 &((*points)->buffer[0]);
629
630 for (size_t i = 0, offset = 0; i < count; ++i) {
631
633 buffer, buffer_size, position, remote_point_info_buffer, &offset,
634 point_data + i, point_info_dt, comm);
635 }
636}
637
639 struct yac_dist_grid * dist_grid,
640 struct proc_sphere_part_node * proc_sphere_part,
641 struct remote_points ** dist_owner) {
642
643 MPI_Comm comm = dist_grid->comm;
644
645 int comm_size;
646 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
647
648 for (int location = 0; location < 3; ++location)
649 dist_grid->owners[location] =
651 dist_grid->sorted_ids[location],
652 dist_grid->sorted_reorder_idx[location],
653 dist_grid->count[location], dist_owner[location]);
654
655 size_t num_missing_vertices = 0;
656 size_t num_missing_edges = 0;
657
658 for (size_t i = 0; i < dist_grid->count[YAC_LOC_CELL]; ++i)
660 dist_grid->owners[YAC_LOC_CELL][i].count != -1,
661 "ERROR(generate_dist_grid_remote_point_infos):"
662 "no owner information for a cell available")
663 for (size_t i = 0; i < dist_grid->count[YAC_LOC_CORNER]; ++i)
664 if (dist_grid->owners[YAC_LOC_CORNER][i].count == -1)
665 ++num_missing_vertices;
666 for (size_t i = 0; i < dist_grid->count[YAC_LOC_EDGE]; ++i)
667 if (dist_grid->owners[YAC_LOC_EDGE][i].count == -1) ++num_missing_edges;
668
669 size_t total_num_missing = num_missing_vertices + num_missing_edges;
670 int * ranks_buffer = xmalloc(total_num_missing * sizeof(*ranks_buffer));
671 int * vertex_ranks = ranks_buffer;
672 int * edge_ranks = ranks_buffer + num_missing_vertices;
673 size_t * size_t_buffer =
674 xmalloc((3 * total_num_missing +
675 4 * (size_t)comm_size) * sizeof(*size_t_buffer));
676 size_t * vertex_reorder = size_t_buffer;
677 size_t * edge_reorder = size_t_buffer + num_missing_vertices;
678 size_t * coord_indices = size_t_buffer + total_num_missing;
679 size_t * ranks_idxs = coord_indices;
680 size_t * cve_reorder = size_t_buffer + 2 * total_num_missing;
681 size_t * total_sendcounts = size_t_buffer + 3 * total_num_missing + 0 * comm_size;
682 size_t * total_recvcounts = size_t_buffer + 3 * total_num_missing + 1 * comm_size;
683 size_t * total_sdispls = size_t_buffer + 3 * total_num_missing + 2 * comm_size;
684 size_t * total_rdispls = size_t_buffer + 3 * total_num_missing + 3 * comm_size;
685
686 size_t offset = 0;
687 for (size_t i = 0, j = 0; i < dist_grid->count[YAC_LOC_CORNER]; ++i) {
688 if (dist_grid->owners[YAC_LOC_CORNER][i].count == -1) {
689
690 vertex_reorder[j] = i;
691 ++j;
692 coord_indices[offset] = i;
693 cve_reorder[offset] = offset;
694 ++offset;
695 }
696 }
697 for (size_t i = 0, j = 0; i < dist_grid->count[YAC_LOC_EDGE]; ++i) {
698 if (dist_grid->owners[YAC_LOC_EDGE][i].count == -1) {
699 // compute middle point of edge
700 size_t * vertex_idxes = &(dist_grid->edge_to_vertex[i][0]);
701 yac_int vertex_ids[2] = {dist_grid->ids[YAC_LOC_CORNER][vertex_idxes[0]],
702 dist_grid->ids[YAC_LOC_CORNER][vertex_idxes[1]]};
703 edge_reorder[j] = i;
704 ++j;
705 coord_indices[offset] =
706 vertex_idxes[(vertex_ids[0] > vertex_ids[1])?1:0];
707 cve_reorder[offset] = offset;
708 ++offset;
709 }
710 }
711
713 coord_indices, total_num_missing, cve_reorder);
714
715 size_t num_unique_idxs = 0;
716 for (size_t i = 0, prev_idx = SIZE_MAX; i < total_num_missing; ++i) {
717 size_t curr_idx = coord_indices[i];
718 if (curr_idx != prev_idx) {
719 prev_idx = curr_idx;
720 ++num_unique_idxs;
721 }
722 }
723
724 yac_coordinate_pointer search_coords =
725 xmalloc(num_unique_idxs * sizeof(*search_coords));
726 int * search_ranks = xmalloc(num_unique_idxs * sizeof(*search_ranks));
727
728 for (size_t i = 0, j = 0, prev_idx = SIZE_MAX; i < total_num_missing; ++i) {
729 size_t curr_idx = coord_indices[i];
730 if (curr_idx != prev_idx) {
731 memcpy(search_coords[j], dist_grid->vertex_coordinates[curr_idx],
732 3 * sizeof(double));
733 prev_idx = curr_idx;
734 ++j;
735 }
736 ranks_idxs[i] = j-1;
737 }
738
740 proc_sphere_part, search_coords, num_unique_idxs, search_ranks);
741 free(search_coords);
742
744 cve_reorder, total_num_missing, ranks_idxs);
745
746 offset = 0;
747 for (size_t i = 0; i < num_missing_vertices; ++i, ++offset)
748 vertex_ranks[i] = search_ranks[ranks_idxs[offset]];
749 for (size_t i = 0; i < num_missing_edges; ++i, ++offset)
750 edge_ranks[i] = search_ranks[ranks_idxs[offset]];
751 free(search_ranks);
752
754 vertex_ranks, num_missing_vertices, vertex_reorder);
756 edge_ranks, num_missing_edges, edge_reorder);
757
758 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
760 2, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
761
762 for (size_t i = 0; i < num_missing_vertices; ++i)
763 sendcounts[2 * vertex_ranks[i] + 0]++;
764 for (size_t i = 0; i < num_missing_edges; ++i)
765 sendcounts[2 * edge_ranks[i] + 1]++;
766
768 2, sendcounts, recvcounts, sdispls, rdispls, comm);
769
770 size_t num_requested_ids[2] = {0,0};
771 size_t saccu = 0, raccu = 0;
772 for (int i = 0; i < comm_size; ++i) {
773 total_sdispls[i] = saccu;
774 total_rdispls[i] = raccu;
775 total_sendcounts[i] = 0;
776 total_recvcounts[i] = 0;
777 for (int j = 0; j < 2; ++j) {
778 total_sendcounts[i] += sendcounts[2 * i + j];
779 total_recvcounts[i] += recvcounts[2 * i + j];
780 num_requested_ids[j] += recvcounts[2 * i + j];
781 }
782 saccu += total_sendcounts[i];
783 raccu += total_recvcounts[i];
784 }
785 size_t request_count = total_recvcounts[comm_size - 1] +
786 total_rdispls[comm_size - 1];
787
788 yac_int * exchange_id_buffer =
789 xmalloc(
790 (total_num_missing + 2 * request_count) * sizeof(*exchange_id_buffer));
791 yac_int * id_send_buffer = exchange_id_buffer + request_count;
792 yac_int * id_recv_buffer = exchange_id_buffer + request_count + total_num_missing;
793
794 // pack the ids for which the local process is missing the owner information
795 for (size_t i = 0; i < num_missing_vertices; ++i) {
796 size_t pos = sdispls[2 * vertex_ranks[i] + 0 + 1]++;
797 id_send_buffer[pos] = dist_grid->ids[YAC_LOC_CORNER][vertex_reorder[i]];
798 }
799 for (size_t i = 0; i < num_missing_edges; ++i) {
800 size_t pos = sdispls[2 * edge_ranks[i] + 1 + 1]++;
801 id_send_buffer[pos] = dist_grid->ids[YAC_LOC_EDGE][edge_reorder[i]];
802 }
803
804 // exchange the ids for which the local process is missing the owner information
805 yac_alltoallv_yac_int_p2p(
806 id_send_buffer, total_sendcounts, total_sdispls,
807 id_recv_buffer, total_recvcounts, total_rdispls, comm);
808
809 yac_int * requested_ids[2] =
810 {exchange_id_buffer, exchange_id_buffer + num_requested_ids[0]};
811
812 // unpack data
813 {
814 size_t ids_offset[2] = {0, 0}, offset = 0;
815 for (int i = 0; i < comm_size; ++i) {
816 for (int j = 0; j < 2; ++j) {
817 size_t curr_count = recvcounts[2 * i + j];
818 memcpy(requested_ids[j] + ids_offset[j], id_recv_buffer + offset,
819 curr_count * sizeof(*(requested_ids[0])));
820 ids_offset[j] += curr_count;
821 offset += curr_count;
822 }
823 }
824 }
825
826 struct remote_point_infos ** remote_point_infos_buffer =
827 xmalloc(request_count * sizeof(*remote_point_infos_buffer));
828 struct remote_point_infos ** found_points[2] =
829 {remote_point_infos_buffer,
830 remote_point_infos_buffer + num_requested_ids[0]};
831 struct remote_points * local_remote_points[2] =
832 {dist_owner[YAC_LOC_CORNER], dist_owner[YAC_LOC_EDGE]};
833
834 size_t max_num_requested_ids = MAX(num_requested_ids[0], num_requested_ids[1]);
835 size_t * reorder_buffer = xmalloc(max_num_requested_ids * sizeof(*reorder_buffer));
836 // lookup owners for requested ids
837 for (int i = 0; i < 2; ++i)
839 requested_ids[i], found_points[i], reorder_buffer, num_requested_ids[i],
840 local_remote_points[i]);
841 free(reorder_buffer);
842 free(exchange_id_buffer);
843
844 int * pack_size_buffer =
845 xmalloc((total_num_missing + request_count) * sizeof(*pack_size_buffer));
846 int * send_pack_sizes = pack_size_buffer;
847 int * recv_pack_sizes = pack_size_buffer + request_count;
848 MPI_Datatype point_info_dt = yac_get_remote_point_info_mpi_datatype(comm);
849
850 {
851 size_t offset = 0, offsets[2] = {0, 0};
852 for (int i = 0; i < comm_size; ++i) {
853 for (int j = 0; j < 2; ++j) {
854 size_t curr_count = (size_t)(recvcounts[2 * i + j]);
855 // get pack sizes
857 found_points[j] + offsets[j], curr_count,
858 send_pack_sizes + offset, point_info_dt, comm);
859 offsets[j] += curr_count;
860 offset += curr_count;
861 }
862 }
863 }
864
865 // exchange pack sizes
866 yac_alltoallv_int_p2p(
867 send_pack_sizes, total_recvcounts, total_rdispls,
868 recv_pack_sizes, total_sendcounts, total_sdispls, comm);
869
870 size_t send_buffer_size = 0, recv_buffer_size = 0;
871 for (size_t i = 0; i < request_count; ++i)
872 send_buffer_size += (size_t)(send_pack_sizes[i]);
873 for (size_t i = 0; i < total_num_missing; ++i)
874 recv_buffer_size += (size_t)(recv_pack_sizes[i]);
875
876 void * result_buffer = xmalloc(send_buffer_size + recv_buffer_size);
877 void * send_result_buffer = result_buffer;
878 void * recv_result_buffer = (unsigned char *)result_buffer + send_buffer_size;
879
880 // pack data
881 {
882 size_t send_buffer_size = 0, offset = 0, offsets[2] = {0,0};
883 for (int i = 0; i < comm_size; ++i) {
884 for (int j = 0; j < 2; ++j) {
885 size_t curr_count = recvcounts[2 * i + j];
886 // get pack sizes
888 found_points[j] + offsets[j],
889 send_pack_sizes + offset, curr_count,
890 (void*)((unsigned char*)send_result_buffer + send_buffer_size),
891 point_info_dt, comm);
892 for (size_t k = 0; k < curr_count; ++k)
893 send_buffer_size += send_pack_sizes[offset + k];
894 offsets[j] += curr_count;
895 offset += curr_count;
896 }
897 }
898 }
899
900 {
901 size_t send_offset = 0, recv_offset = 0;
902 size_t saccu = 0, raccu = 0;
903 for (int i = 0; i < comm_size; ++i) {
904 total_sdispls[i] = saccu;
905 total_rdispls[i] = raccu;
906 size_t curr_sendcount = 0, curr_recvcount = 0;
907 for (int k = 0; k < 2; ++k) {
908 for (size_t j = 0; j < recvcounts[2 * i + k]; ++j, ++send_offset)
909 curr_sendcount += (size_t)(send_pack_sizes[send_offset]);
910 for (size_t j = 0; j < sendcounts[2 * i + k]; ++j, ++recv_offset)
911 curr_recvcount += (size_t)(recv_pack_sizes[recv_offset]);
912 }
913 total_sendcounts[i] = curr_sendcount;
914 total_recvcounts[i] = curr_recvcount;
915 saccu += curr_sendcount;
916 raccu += curr_recvcount;
917 }
918 }
919
920 // exchange results
921 yac_alltoallv_packed_p2p(
922 send_result_buffer, total_sendcounts, total_sdispls,
923 recv_result_buffer, total_recvcounts, total_rdispls, comm);
924
925 // unpack results
926 {
927 size_t counts[2] = {0, 0}, count = 0, offset = 0;
929 {dist_grid->owners[YAC_LOC_CORNER], dist_grid->owners[YAC_LOC_EDGE]};
930 size_t * reorder[2] = {vertex_reorder, edge_reorder};
931 for (int i = 0; i < comm_size; ++i) {
932 for (int j = 0; j < 2; ++j) {
933 size_t curr_count = sendcounts[2 * i + j];
934 for (size_t k = 0; k < curr_count; ++k, ++counts[j], ++count) {
935 int curr_buffer_size = recv_pack_sizes[sdispls[2 * i + j] + k];
936 int position = 0;
938 (void*)((unsigned char*)recv_result_buffer + offset),
939 curr_buffer_size, &position,
940 remote_points[j] + reorder[j][counts[j]], point_info_dt, comm);
941 offset += (size_t)(curr_buffer_size);
942 }
943 }
944 }
945 }
946
947 yac_mpi_call(MPI_Type_free(&point_info_dt), comm);
948
949 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
950 free(result_buffer);
951 free(pack_size_buffer);
952 free(remote_point_infos_buffer);
953 free(size_t_buffer);
954 free(ranks_buffer);
955}
956
957static int compare_remote_point(const void * a, const void * b) {
958
959 return ((const struct remote_point*)a)->global_id -
960 ((const struct remote_point*)b)->global_id;
961}
962
963// inserts an element into an array and increases the corresponding size
964static void insert_global_id(yac_int * ids, size_t n, yac_int id) {
965
966 size_t i;
967 for (i = 0; i < n; ++i) if (ids[i] >= id) break;
968 // copy new id into array and move bigger elements one position up
969 if (n != i) memmove(ids + i + 1, ids + i, (n - i) * sizeof(*ids));
970 ids[i] = id;
971}
972
973// inserts an element into an array and increases the corresponding size
974// if the element already exists in the array nothing is done
975static void insert_rank(int * ranks, int * count, int rank) {
976
977 int i;
978 int n = *count;
979
980 for (i = 0; i < n; ++i) if (ranks[i] >= rank) break;
981
982 // if the rank is already in the array
983 if (i != n) {
984 if (ranks[i] == rank) return;
985 else memmove(ranks + i + 1, ranks + i, ((size_t)(n - i)) * sizeof(*ranks));
986 }
987 ranks[i] = rank;
988 *count = n + 1;
989}
990
992 const void * a, const void * b) {
993
994 int count_a = ((struct n_ids_reorder const *)a)->count;
995 int count_b = ((struct n_ids_reorder const *)b)->count;
996 yac_int * a_ids = ((struct n_ids_reorder const *)a)->ids;
997 yac_int * b_ids = ((struct n_ids_reorder const *)b)->ids;
998 int ret = count_a - count_b;
999 for (int i = 0; !ret && (i < count_a); ++i)
1000 ret = (a_ids[i] > b_ids[i]) - (a_ids[i] < b_ids[i]);
1001 return ret;
1002}
1003
1005 const void * a, const void * b) {
1006
1007 return (((struct n_ids_reorder const *)a)->reorder_idx >
1008 ((struct n_ids_reorder const *)b)->reorder_idx) -
1009 (((struct n_ids_reorder const *)a)->reorder_idx <
1010 ((struct n_ids_reorder const *)b)->reorder_idx);
1011}
1012
1013// determines for all cells, in the grid data provided by the user, to
1014// which processes they belong according to the decomposition of the
1015// distributed grid
1017 struct proc_sphere_part_node * proc_sphere_part,
1018 struct yac_basic_grid_data * grid, MPI_Comm comm, int ** dist_cell_ranks,
1019 int * dist_cell_rank_counts, size_t * dist_cell_rank_offsets) {
1020
1021 int comm_size;
1022 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1023
1024 size_t num_cells = grid->num_cells;
1025 int * ranks_buffer = xmalloc((size_t)comm_size * sizeof(*ranks_buffer));
1026 size_t dist_cell_ranks_array_size = num_cells;
1027 int * dist_cell_ranks_ = xmalloc(num_cells * sizeof(*dist_cell_ranks_));
1028 size_t offset = 0;
1029
1030 // determine maximum number of vertices per cell
1031 int max_num_vertices_per_cell = 0;
1032 for (size_t i = 0; i < num_cells; ++i)
1033 if (grid->num_vertices_per_cell[i] > max_num_vertices_per_cell)
1034 max_num_vertices_per_cell = grid->num_vertices_per_cell[i];
1035
1036 struct grid_cell cell;
1037 cell.coordinates_xyz =
1038 xmalloc(
1039 (size_t)max_num_vertices_per_cell * sizeof(*(cell.coordinates_xyz)));
1040 cell.edge_type =
1041 xmalloc((size_t)max_num_vertices_per_cell * sizeof(*(cell.edge_type)));
1042
1043 size_t * cell_to_vertex = grid->cell_to_vertex;
1044 size_t * cell_to_vertex_offsets = grid->cell_to_vertex_offsets;
1045 size_t * cell_to_edge = grid->cell_to_edge;
1046 size_t * cell_to_edge_offsets = grid->cell_to_edge_offsets;
1047 yac_coordinate_pointer vertex_coordinates = grid->vertex_coordinates;
1048 enum yac_edge_type * edge_type = grid->edge_type;
1049 int * num_vertices_per_cell = grid->num_vertices_per_cell;
1050
1051 // generate a bounding circle for each cell and use it to determine
1052 // ranks of the processes that require this cell
1053 for (size_t i = 0; i < num_cells; ++i) {
1054
1055 // get bounding circle for current cell
1056 cell.num_corners = num_vertices_per_cell[i];
1057 size_t * curr_cell_to_vertex =
1058 cell_to_vertex + cell_to_vertex_offsets[i];
1059 size_t * curr_cell_to_edge =
1060 cell_to_edge + cell_to_edge_offsets[i];
1061 for (int j = 0; j < num_vertices_per_cell[i]; ++j) {
1062 yac_coordinate_pointer curr_vertex_coords =
1063 vertex_coordinates + curr_cell_to_vertex[j];
1064 for (int k = 0; k < 3; ++k)
1065 cell.coordinates_xyz[j][k] = (*curr_vertex_coords)[k];
1066 cell.edge_type[j] = edge_type[curr_cell_to_edge[j]];
1067 }
1068 int rank_count;
1069 if (cell.num_corners > 0) {
1070
1071 struct bounding_circle bnd_circle;
1072 yac_get_cell_bounding_circle(cell, &bnd_circle);
1073
1075 proc_sphere_part, bnd_circle, ranks_buffer, &rank_count);
1076 } else {
1077 ranks_buffer[0] = 0;
1078 rank_count = 1;
1079 }
1080
1081 ENSURE_ARRAY_SIZE(dist_cell_ranks_, dist_cell_ranks_array_size,
1082 offset + (size_t)rank_count);
1083 memcpy(dist_cell_ranks_ + offset, ranks_buffer,
1084 (size_t)rank_count * sizeof(*ranks_buffer));
1085 dist_cell_rank_counts[i] = rank_count;
1086 dist_cell_rank_offsets[i] = offset;
1087 offset += (size_t)rank_count;
1088 }
1089
1090 dist_cell_rank_offsets[num_cells] = offset;
1091
1092 free(cell.edge_type);
1093 free(cell.coordinates_xyz);
1094 free(ranks_buffer);
1095
1096 *dist_cell_ranks = dist_cell_ranks_;
1097}
1098
1099static MPI_Datatype yac_get_id_reorder_coord_coord_mpi_datatype(MPI_Comm comm) {
1100
1101 struct id_reorder_coord dummy;
1102 MPI_Datatype coord_dt;
1103 int array_of_blocklengths[] = {3};
1104 const MPI_Aint array_of_displacements[] =
1105 {(MPI_Aint)(intptr_t)(const void *)&(dummy.coord) -
1106 (MPI_Aint)(intptr_t)(const void *)&dummy};
1107 const MPI_Datatype array_of_types[] = {MPI_DOUBLE};
1109 MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements,
1110 array_of_types, &coord_dt), comm);
1111 return yac_create_resized(coord_dt, sizeof(dummy), comm);
1112}
1113
1114static MPI_Datatype yac_get_id_reorder_coord_id_mpi_datatype(MPI_Comm comm) {
1115
1116 struct id_reorder_coord dummy;
1117 MPI_Datatype global_id_dt;
1118 int array_of_blocklengths[] = {1};
1119 const MPI_Aint array_of_displacements[] =
1120 {(MPI_Aint)(intptr_t)(const void *)&(dummy.global_id) -
1121 (MPI_Aint)(intptr_t)(const void *)&dummy};
1122 const MPI_Datatype array_of_types[] = {yac_int_dt};
1124 MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements,
1125 array_of_types, &global_id_dt), comm);
1126 return yac_create_resized(global_id_dt, sizeof(dummy), comm);
1127}
1128
1130 const void * a, const void * b) {
1131
1132 return compare_coords(((const struct id_reorder_coord *)a)->coord,
1133 ((const struct id_reorder_coord *)b)->coord);
1134}
1135
1137 const void * a, const void * b) {
1138
1139 return (((const struct id_reorder_coord *)a)->reorder_idx >
1140 ((const struct id_reorder_coord *)b)->reorder_idx) -
1141 (((const struct id_reorder_coord *)a)->reorder_idx <
1142 ((const struct id_reorder_coord *)b)->reorder_idx);
1143}
1144
1145// generates global vertex ids if they are not provied by the user
1146// and returns the distributed owners for each vertex in the provided
1147// grid data
1149 struct proc_sphere_part_node * proc_sphere_part,
1150 struct yac_basic_grid_data * grid, MPI_Comm comm) {
1151
1152 int * vertex_ranks = xmalloc(grid->num_vertices * sizeof(*vertex_ranks));
1153
1154 // determine the dist grid ranks for all vertices
1156 proc_sphere_part, grid->vertex_coordinates, grid->num_vertices,
1157 vertex_ranks);
1158
1159 // check whether only of subset of the processes have defined
1160 // their global ids, which is not supported
1161 int ids_available_local =
1162 (grid->num_vertices > 0) && (grid->vertex_ids != NULL);
1163 int ids_available_global;
1164 yac_mpi_call(MPI_Allreduce(&ids_available_local, &ids_available_global, 1,
1165 MPI_INT, MPI_MAX, comm), comm);
1166
1167 // if there are vertices defined locally for the current grid
1168 if (grid->num_vertices != 0) {
1169 YAC_ASSERT(
1170 ids_available_local || !ids_available_global,
1171 "ERROR(generate_vertex_ids): inconsistent global ids")
1172
1173 // generate core mask if not available
1174 if (grid->core_vertex_mask == NULL) {
1175 int * core_mask =
1176 (grid->core_vertex_mask =
1177 xmalloc(grid->num_vertices * sizeof(*core_mask)));
1178 for (size_t j = 0; j < grid->num_vertices; ++j) core_mask[j] = 1;
1179 }
1180 }
1181
1182 // if we do not need to generate the global ids
1183 if (ids_available_global) return vertex_ranks;
1184
1185 int comm_size;
1186 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1187
1188 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1190 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
1191
1192 for (size_t i = 0; i < grid->num_vertices; ++i)
1193 sendcounts[vertex_ranks[i]]++;
1194
1196 1, sendcounts, recvcounts, sdispls, rdispls, comm);
1197
1198 size_t orig_vertex_count = grid->num_vertices;
1199 size_t dist_vertex_count =
1200 recvcounts[comm_size - 1] + rdispls[comm_size - 1];
1201
1202 struct id_reorder_coord * id_reorder_coord_buffer =
1203 xmalloc((orig_vertex_count + dist_vertex_count) *
1204 sizeof(*id_reorder_coord_buffer));
1205 struct id_reorder_coord *
1206 id_reorder_coord_send_buffer = id_reorder_coord_buffer;
1207 struct id_reorder_coord *
1208 id_reorder_coord_recv_buffer = id_reorder_coord_buffer + orig_vertex_count;
1209
1210 // pack send buffer
1211 for (size_t i = 0; i < orig_vertex_count; ++i) {
1212 size_t pos = sdispls[vertex_ranks[i] + 1]++;
1213 id_reorder_coord_send_buffer[pos].reorder_idx = i;
1214 for (int j = 0; j < 3; ++j)
1215 id_reorder_coord_send_buffer[pos].coord[j] =
1216 grid->vertex_coordinates[i][j];
1217 }
1218
1219 MPI_Datatype id_reorder_coord_coord_dt =
1221
1222 // exchange data
1224 id_reorder_coord_send_buffer, sendcounts, sdispls,
1225 id_reorder_coord_recv_buffer, recvcounts, rdispls,
1226 sizeof(*id_reorder_coord_send_buffer), id_reorder_coord_coord_dt, comm);
1227
1228 yac_mpi_call(MPI_Type_free(&id_reorder_coord_coord_dt), comm);
1229
1230 for (size_t i = 0; i < dist_vertex_count; ++i)
1231 id_reorder_coord_recv_buffer[i].reorder_idx = i;
1232
1233 // sort received vertices based on coordinates
1234 qsort(id_reorder_coord_recv_buffer, dist_vertex_count,
1235 sizeof(*id_reorder_coord_recv_buffer), compare_id_reorder_coord_coord);
1236
1237 size_t unique_count = dist_vertex_count > 0;
1238 struct id_reorder_coord * prev = id_reorder_coord_recv_buffer;
1239
1240 // determine number of unique coordinates
1241 for (size_t i = 0; i < dist_vertex_count; ++i) {
1242 struct id_reorder_coord * curr = id_reorder_coord_recv_buffer + i;
1243 if (compare_id_reorder_coord_coord(prev, curr)) {
1244 ++unique_count;
1245 prev = curr;
1246 }
1247 curr->global_id = (yac_int)unique_count - 1;
1248 }
1249
1250 YAC_ASSERT(
1251 unique_count <= (size_t)XT_INT_MAX,
1252 "ERROR(generate_vertex_ids): global_id out of bounds")
1253
1254 yac_int yac_int_unique_count = (yac_int)unique_count;
1255 yac_int id_offset;
1256
1257 // determine exclusive scan of sum of numbers of unique
1258 // coordinates on all ranks
1259 yac_mpi_call(MPI_Exscan(&yac_int_unique_count, &id_offset, 1, yac_int_dt,
1260 MPI_SUM, comm), comm);
1261 int comm_rank;
1262 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1263 if (comm_rank == 0) id_offset = 0;
1264
1265 YAC_ASSERT(
1266 ((size_t)id_offset + unique_count) <= (size_t)XT_INT_MAX,
1267 "ERROR(generate_vertex_ids): global_id out of bounds")
1268
1269 // adjust global ids
1270 for (size_t i = 0; i < dist_vertex_count; ++i)
1271 id_reorder_coord_recv_buffer[i].global_id += id_offset;
1272
1273 // return received vertices into original order
1274 qsort(id_reorder_coord_recv_buffer, dist_vertex_count,
1275 sizeof(*id_reorder_coord_recv_buffer),
1277
1278 MPI_Datatype id_reorder_coord_id_dt =
1280
1281 // return generated global ids data
1283 id_reorder_coord_recv_buffer, recvcounts, rdispls,
1284 id_reorder_coord_send_buffer, sendcounts, sdispls,
1285 sizeof(*id_reorder_coord_send_buffer), id_reorder_coord_id_dt, comm);
1286
1287 yac_mpi_call(MPI_Type_free(&id_reorder_coord_id_dt), comm);
1288
1289 yac_int * vertex_ids =
1290 ((grid->vertex_ids =
1291 (grid->num_vertices > 0)?
1292 xmalloc(grid->num_vertices * sizeof(*(grid->vertex_ids))):NULL));
1293
1294 for (size_t i = 0; i < grid->num_vertices; ++i)
1295 vertex_ids[id_reorder_coord_send_buffer[i].reorder_idx] =
1296 id_reorder_coord_send_buffer[i].global_id;
1297
1298 free(id_reorder_coord_buffer);
1299 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1300
1301 return vertex_ranks;
1302}
1303
1304// generates global cell/edge ids if they are not provied by the user
1306 struct proc_sphere_part_node * proc_sphere_part,
1307 struct yac_basic_grid_data * grid, int * vertex_ranks, MPI_Comm comm) {
1308
1309 int comm_rank, comm_size;
1310 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1311 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1312
1313 // check whether only of subset of the processes have defined
1314 // their global ids, which is not supported
1315 int ids_available_local[2], ids_available_global[2];
1316 ids_available_local[0] = (grid->num_cells > 0) && (grid->cell_ids != NULL);
1317 ids_available_local[1] = (grid->num_edges > 0) && (grid->edge_ids != NULL);
1318 yac_mpi_call(MPI_Allreduce(ids_available_local, ids_available_global, 2,
1319 MPI_INT, MPI_MAX, comm), comm);
1320
1321 if (grid->num_cells > 0) {
1322 YAC_ASSERT(
1323 ids_available_local[0] == ids_available_global[0],
1324 "ERROR(generate_ce_ids): inconsistent global ids")
1325 // generate core mask if not available
1326 if (grid->core_cell_mask == NULL) {
1327 int * core_cell_mask =
1328 (grid->core_cell_mask =
1329 xmalloc(grid->num_cells * sizeof(*core_cell_mask)));
1330 for (size_t j = 0; j < grid->num_cells; ++j) core_cell_mask[j] = 1;
1331 }
1332 }
1333 if (grid->num_edges > 0) {
1334 YAC_ASSERT(
1335 ids_available_local[1] == ids_available_global[1],
1336 "ERROR(generate_ce_ids): inconsistent global ids")
1337 // generate core mask if not available
1338 if (grid->core_edge_mask == NULL) {
1339 int * core_edge_mask =
1340 (grid->core_edge_mask =
1341 xmalloc(grid->num_edges * sizeof(*core_edge_mask)));
1342 for (size_t j = 0; j < grid->num_edges; ++j) core_edge_mask[j] = 1;
1343 }
1344 }
1345
1346 // if no ids need to be generated
1347 if (ids_available_global[0] && ids_available_global[1]) return;
1348
1349 int * rank_buffer =
1350 xmalloc(
1351 (((ids_available_global[0])?0:(grid->num_cells)) +
1352 ((ids_available_global[1])?0:(grid->num_edges))) * sizeof(*rank_buffer));
1353 int * cell_ranks = rank_buffer;
1354 int * edge_ranks =
1355 rank_buffer + ((ids_available_global[0])?0:(grid->num_cells));
1356
1357 size_t * size_t_buffer =
1358 xmalloc((8 * (size_t)comm_size + 1) * sizeof(*size_t_buffer));
1359 size_t * sendcounts = size_t_buffer + 0 * comm_size;
1360 size_t * recvcounts = size_t_buffer + 2 * comm_size;
1361 size_t * total_sendcounts = size_t_buffer + 4 * comm_size;
1362 size_t * total_recvcounts = size_t_buffer + 5 * comm_size;
1363 size_t * total_sdispls = size_t_buffer + 6 * comm_size;
1364 size_t * total_rdispls = size_t_buffer + 7 * comm_size + 1;
1365 memset(sendcounts, 0, 2 * (size_t)comm_size * sizeof(*sendcounts));
1366
1367 yac_int * cell_to_vertex_ids = NULL;
1368 int max_num_vertices_per_cell = 0;
1369
1370 if (!ids_available_global[0]) {
1371
1372 { // compute the global maximum number of vertices per cell
1373 for (size_t i = 0; i < grid->num_cells; ++i)
1374 if (grid->num_vertices_per_cell[i] > max_num_vertices_per_cell)
1375 max_num_vertices_per_cell = grid->num_vertices_per_cell[i];
1376 yac_mpi_call(MPI_Allreduce(MPI_IN_PLACE, &max_num_vertices_per_cell, 1,
1377 MPI_INT, MPI_MAX, comm), comm);
1378 }
1379
1380 cell_to_vertex_ids =
1381 xmalloc(grid->num_cells * max_num_vertices_per_cell *
1382 sizeof(*cell_to_vertex_ids));
1383
1384 for (size_t i = 0; i < grid->num_cells; ++i) {
1385
1386 size_t curr_num_vertices = grid->num_vertices_per_cell[i];
1387 yac_int * curr_cell_to_vertex_ids =
1388 cell_to_vertex_ids + i * max_num_vertices_per_cell;
1389
1390 int cell_rank;
1391 if (curr_num_vertices > 0) {
1392 size_t * curr_cell_vertices =
1393 grid->cell_to_vertex + grid->cell_to_vertex_offsets[i];
1394 size_t min_vertex = curr_cell_vertices[0];
1395 curr_cell_to_vertex_ids[0] = grid->vertex_ids[min_vertex];
1396 for (size_t j = 1; j < curr_num_vertices; ++j) {
1397 size_t curr_vertex_idx = curr_cell_vertices[j];
1398 yac_int curr_vertex_id = grid->vertex_ids[curr_vertex_idx];
1399 insert_global_id(curr_cell_to_vertex_ids, j, curr_vertex_id);
1400 if (curr_cell_to_vertex_ids[0] == curr_vertex_id)
1401 min_vertex = curr_vertex_idx;
1402 }
1403 cell_rank = vertex_ranks[min_vertex];
1404 } else {
1405 cell_rank = 0;
1406 }
1407 for (size_t j = curr_num_vertices; j < max_num_vertices_per_cell; ++j)
1408 curr_cell_to_vertex_ids[j] = XT_INT_MAX;
1409
1410 sendcounts[2 * ((cell_ranks[i] = cell_rank)) + 0]++;
1411 }
1412 }
1413
1414 yac_int * edge_to_vertex_ids = NULL;
1415
1416 if (!ids_available_global[1]) {
1417
1418 edge_to_vertex_ids =
1419 xmalloc(2 * grid->num_edges * sizeof(*edge_to_vertex_ids));
1420
1421 for (size_t i = 0; i < grid->num_edges; ++i) {
1422
1423 size_t * curr_edge_to_vertex = &(grid->edge_to_vertex[i][0]);
1424 yac_int * curr_edge_vertex_ids = edge_to_vertex_ids + 2 * i;
1425 curr_edge_vertex_ids[0] = grid->vertex_ids[curr_edge_to_vertex[0]];
1426 curr_edge_vertex_ids[1] = grid->vertex_ids[curr_edge_to_vertex[1]];
1427
1428 if (curr_edge_vertex_ids[0] > curr_edge_vertex_ids[1]) {
1429 yac_int temp = curr_edge_vertex_ids[0];
1430 curr_edge_vertex_ids[0] = curr_edge_vertex_ids[1];
1431 curr_edge_vertex_ids[1] = temp;
1432 sendcounts[
1433 2 * ((edge_ranks[i] = vertex_ranks[curr_edge_to_vertex[1]])) + 1]++;
1434 } else {
1435 sendcounts[
1436 2 * ((edge_ranks[i] = vertex_ranks[curr_edge_to_vertex[0]])) + 1]++;
1437 }
1438 }
1439 }
1440
1441 // exchange the number of cells and edges
1442 yac_mpi_call(MPI_Alltoall(sendcounts, 2, YAC_MPI_SIZE_T,
1443 recvcounts, 2, YAC_MPI_SIZE_T, comm), comm);
1444
1445 total_sdispls[0] = 0;
1446 size_t recv_counts[2] = {0,0};
1447 size_t saccu = 0, raccu = 0;
1448 for (int i = 0; i < comm_size; ++i) {
1449 total_sdispls[i+1] = saccu;
1450 total_rdispls[i] = raccu;
1451 recv_counts[0] += recvcounts[2 * i + 0];
1452 recv_counts[1] += recvcounts[2 * i + 1];
1453 total_sendcounts[i] = sendcounts[2 * i + 0] *
1454 (size_t)max_num_vertices_per_cell +
1455 sendcounts[2 * i + 1] * 2;
1456 total_recvcounts[i] = recvcounts[2 * i + 0] *
1457 (size_t)max_num_vertices_per_cell +
1458 recvcounts[2 * i + 1] * 2;
1459 saccu += total_sendcounts[i];
1460 raccu += total_recvcounts[i];
1461 }
1462 size_t local_data_count = total_sendcounts[comm_size - 1] +
1463 total_sdispls[comm_size];
1464 size_t recv_count = total_recvcounts[comm_size - 1] +
1465 total_rdispls[comm_size - 1];
1466
1467 yac_int * yac_int_buffer =
1468 xmalloc((local_data_count + recv_count) * sizeof(*yac_int_buffer));
1469 yac_int * send_buffer = yac_int_buffer;
1470 yac_int * recv_buffer = yac_int_buffer + local_data_count;
1471
1472 // pack send buffer
1473 if (!ids_available_global[0])
1474 for (size_t i = 0; i < grid->num_cells; ++i)
1475 for (int j = 0; j < max_num_vertices_per_cell; ++j)
1476 send_buffer[total_sdispls[cell_ranks[i] + 1]++] =
1477 cell_to_vertex_ids[i * max_num_vertices_per_cell + j];
1478 if (!ids_available_global[1])
1479 for (size_t i = 0; i < grid->num_edges; ++i)
1480 for (int j = 0; j < 2; ++j)
1481 send_buffer[total_sdispls[edge_ranks[i] + 1]++] =
1482 edge_to_vertex_ids[2 * i + j];
1483
1484 free(edge_to_vertex_ids);
1485 free(cell_to_vertex_ids);
1486
1487 // exchange data
1488 yac_alltoallv_yac_int_p2p(
1489 send_buffer, total_sendcounts, total_sdispls,
1490 recv_buffer, total_recvcounts, total_rdispls, comm);
1491
1492 struct n_ids_reorder * n_ids_reorder_buffer =
1493 xmalloc((recv_counts[0] + recv_counts[1]) * sizeof(*n_ids_reorder_buffer));
1494 struct n_ids_reorder * n_ids_reorder[2] =
1495 {n_ids_reorder_buffer, n_ids_reorder_buffer + recv_counts[0]};
1496
1497 size_t offset = 0;
1498 int index_counts[2] = {max_num_vertices_per_cell, 2};
1499 size_t reorder_idx = 0;
1500 recv_counts[0] = 0;
1501 recv_counts[1] = 0;
1502 for (int i = 0; i < comm_size; ++i) {
1503 for (int j = 0; j < 2; ++j) {
1504 size_t curr_count = recvcounts[2 * i + j];
1505 for (size_t k = 0; k < curr_count; ++k, ++reorder_idx, ++recv_counts[j]) {
1506 n_ids_reorder[j][recv_counts[j]].count = index_counts[j];
1507 n_ids_reorder[j][recv_counts[j]].ids = recv_buffer + offset;
1508 n_ids_reorder[j][recv_counts[j]].reorder_idx = reorder_idx;
1509 offset += index_counts[j];
1510 }
1511 }
1512 }
1513
1514 for (int i = 0; i < 2; ++i) {
1515
1516 if (ids_available_global[i]) continue;
1517
1518 qsort(n_ids_reorder[i], recv_counts[i], sizeof(*(n_ids_reorder[i])),
1520
1521 size_t unique_count = recv_counts[i] > 0;
1522 struct n_ids_reorder * prev = n_ids_reorder[i];
1523 struct n_ids_reorder * curr = n_ids_reorder[i];
1524
1525 for (size_t j = 0; j < recv_counts[i]; ++j, ++curr) {
1526 if (compare_n_ids_reorder_ids(prev, curr)) {
1527 ++unique_count;
1528 prev = curr;
1529 }
1530 curr->global_id = (yac_int)(unique_count - 1);
1531 }
1532
1533 YAC_ASSERT(
1534 unique_count <= (size_t)XT_INT_MAX,
1535 "ERROR(generate_global_ce_ids): global_id out of bounds")
1536
1537 yac_int yac_int_unique_count = (yac_int)unique_count;
1538 yac_int id_offset;
1539
1540 // determine exclusive scan of sum of numbers of unique ids on all ranks
1541 yac_mpi_call(MPI_Exscan(&yac_int_unique_count, &id_offset, 1, yac_int_dt,
1542 MPI_SUM, comm), comm);
1543 if (comm_rank == 0) id_offset = 0;
1544
1545 YAC_ASSERT(
1546 ((size_t)id_offset + unique_count) <= (size_t)XT_INT_MAX,
1547 "ERROR(generate_global_ce_ids): global_id out of bounds")
1548
1549 // adjust global ids
1550 for (size_t j = 0; j < recv_counts[i]; ++j)
1551 n_ids_reorder[i][j].global_id += id_offset;
1552 }
1553 free(yac_int_buffer);
1554
1555 qsort(n_ids_reorder_buffer, recv_counts[0] + recv_counts[1],
1556 sizeof(*n_ids_reorder_buffer), compare_n_ids_reorder_reorder);
1557
1558 yac_int * global_ids_buffer =
1559 xmalloc((recv_counts[0] + recv_counts[1] +
1560 ((ids_available_global[0])?0:(grid->num_cells)) +
1561 ((ids_available_global[1])?0:(grid->num_edges))) *
1562 sizeof(*global_ids_buffer));
1563 yac_int * send_global_ids = global_ids_buffer;
1564 yac_int * recv_global_ids =
1565 global_ids_buffer + recv_counts[0] + recv_counts[1];
1566
1567 for (size_t i = 0; i < recv_counts[0] + recv_counts[1]; ++i)
1568 send_global_ids[i] = n_ids_reorder_buffer[i].global_id;
1569 free(n_ids_reorder_buffer);
1570
1571 // generate count and displs data
1572 saccu = 0, raccu = 0;
1573 for (int i = 0; i < comm_size; ++i) {
1574 total_sdispls[i] = saccu;
1575 total_rdispls[i] = raccu;
1576 saccu +=
1577 ((total_sendcounts[i] = recvcounts[2 * i + 0] + recvcounts[2 * i + 1]));
1578 raccu +=
1579 ((total_recvcounts[i] = sendcounts[2 * i + 0] + sendcounts[2 * i + 1]));
1580 }
1581
1582 // exchange generated global ids data
1583 yac_alltoallv_yac_int_p2p(
1584 send_global_ids, total_sendcounts, total_sdispls,
1585 recv_global_ids, total_recvcounts, total_rdispls, comm);
1586
1587 if ((!ids_available_global[0]) && (grid->num_cells > 0))
1588 grid->cell_ids = xmalloc(grid->num_cells * sizeof(*grid->cell_ids));
1589 if ((!ids_available_global[1]) && (grid->num_edges > 0))
1590 grid->edge_ids = xmalloc(grid->num_edges * sizeof(grid->edge_ids));
1591
1592 // unpack generated global ids
1593 if (!ids_available_global[0])
1594 for (size_t i = 0; i < grid->num_cells; ++i)
1595 grid->cell_ids[i] = recv_global_ids[total_rdispls[cell_ranks[i]]++];
1596 if (!ids_available_global[1])
1597 for (size_t i = 0; i < grid->num_edges; ++i)
1598 grid->edge_ids[i] = recv_global_ids[total_rdispls[edge_ranks[i]]++];
1599
1600 free(rank_buffer);
1601 free(size_t_buffer);
1602 free(global_ids_buffer);
1603}
1604
1605// generates global cell/vertex/edge ids if they are not provided by the user
1607 struct proc_sphere_part_node * proc_sphere_part,
1608 struct yac_basic_grid_data * grid, MPI_Comm comm) {
1609
1610 // generate global ids for all vertices (if non-existent)
1611 int * vertex_ranks = generate_vertex_ids(proc_sphere_part, grid, comm);
1612
1613 // generate global ids for all cell and edge (if non-existent)
1614 generate_ce_ids(proc_sphere_part, grid, vertex_ranks, comm);
1615
1616 free(vertex_ranks);
1617}
1618
1619// generate edge to cell mapping
1621 const_size_t_pointer cell_to_edge, const_int_pointer num_edges_per_cell,
1622 int * core_cell_mask, size_t num_cells, size_t num_edges) {
1623
1624 if (num_cells == 0) return NULL;
1625
1626 yac_size_t_2_pointer edge_to_cell = xmalloc(num_edges * sizeof(*edge_to_cell));
1627
1628 for (size_t i = 0; i < num_edges; ++i) {
1629 edge_to_cell[i][0] = SIZE_MAX;
1630 edge_to_cell[i][1] = SIZE_MAX;
1631 }
1632
1633 for (size_t i = 0, offset = 0; i < num_cells; ++i) {
1634
1635 size_t curr_num_edges = num_edges_per_cell[i];
1636 const_size_t_pointer curr_cell_to_edge = cell_to_edge + offset;
1637 offset += curr_num_edges;
1638
1639 if ((core_cell_mask == NULL) || core_cell_mask[i]) {
1640
1641 for (size_t j = 0; j < curr_num_edges; ++j) {
1642
1643 size_t curr_edge = curr_cell_to_edge[j];
1644 size_t * curr_edge_to_cell = edge_to_cell[curr_edge];
1645 curr_edge_to_cell += *curr_edge_to_cell != SIZE_MAX;
1647 *curr_edge_to_cell == SIZE_MAX,
1648 "ERROR(generate_edge_to_cell): "
1649 "more than two cells point to a single edge "
1650 "(does the grid contain degenrated cells (less than 3 corners) "
1651 "or duplicated cells; "
1652 "these can be masked out using the core mask)\n"
1653 "(num_cells: %zu cell_idx: %zu: num_cell_edge %zu)",
1654 num_cells, i, curr_num_edges)
1655 *curr_edge_to_cell = i;
1656 }
1657 }
1658 }
1659
1660 return edge_to_cell;
1661}
1662
1664 void * grid, size_t vertex_idx, size_t ** cells, int * num_cells) {
1665
1666 *cells =
1667 ((struct yac_basic_grid_data *)grid)->vertex_to_cell +
1668 ((struct yac_basic_grid_data *)grid)->vertex_to_cell_offsets[vertex_idx];
1669 *num_cells =
1670 ((struct yac_basic_grid_data *)grid)->num_cells_per_vertex[vertex_idx];
1671}
1672
1673static void get_edge_cells(
1674 void * edge_to_cell, size_t edge_idx, size_t ** cells, int * num_cells) {
1675
1676 *cells = ((yac_size_t_2_pointer)edge_to_cell)[edge_idx];
1677 *num_cells = 2;
1678}
1679
1680static void get_ve_ranks(
1681 int ** rank_buffer, size_t * rank_buffer_size,
1682 size_t * rank_buffer_array_size, int * num_ve_ranks,
1683 int * core_mask, size_t count,
1684 void(*get_cells)(
1685 void * ve_to_cell_data, size_t idx, size_t ** cells, int * num_cells),
1686 void * ve_to_cell_data, int * num_cell_ranks,
1687 size_t * dist_cell_rank_offsets) {
1688
1689 // determine dist ranks for all vertices/edges based on the dist ranks of
1690 // adjacent cells
1691 for (size_t i = 0; i < count; ++i) {
1692
1693 if (core_mask[i]) {
1694
1695 size_t * cells;
1696 int num_cells;
1697 get_cells(ve_to_cell_data, i, &cells, &num_cells);
1698
1699 size_t max_num_ranks = 0;
1700 for (int j = 0; j < num_cells; ++j)
1701 if (cells[j] != SIZE_MAX)
1702 max_num_ranks += (size_t)(num_cell_ranks[cells[j]]);
1703
1704 ENSURE_ARRAY_SIZE(*rank_buffer, *rank_buffer_array_size,
1705 *rank_buffer_size + (size_t)max_num_ranks);
1706
1707 int * curr_ranks = *rank_buffer + *rank_buffer_size;
1708 int curr_num_ranks = 0;
1709
1710 for (int j = 0; j < num_cells; ++j) {
1711
1712 size_t curr_cell_idx = cells[j];
1713 if (curr_cell_idx == SIZE_MAX) continue;
1714
1715 int curr_num_cell_ranks = num_cell_ranks[curr_cell_idx];
1716 int * curr_cell_ranks =
1717 *rank_buffer + dist_cell_rank_offsets[curr_cell_idx];
1718
1719 for (int k = 0; k < curr_num_cell_ranks; ++k)
1720 insert_rank(curr_ranks, &curr_num_ranks, curr_cell_ranks[k]);
1721 }
1722 *rank_buffer_size += (size_t)(num_ve_ranks[i] = curr_num_ranks);
1723 } else {
1724 num_ve_ranks[i] = 0;
1725 }
1726 }
1727}
1728
1729// generates mapping information from the decomposition provided by the user to
1730// one of the distributed grid
1732 struct proc_sphere_part_node * proc_sphere_part,
1733 struct yac_basic_grid_data * grid, MPI_Comm comm) {
1734
1735 // generate global ids if they are missing
1736 generate_global_ids(proc_sphere_part, grid, comm);
1737
1738 // determine dist ranks for all cells based on their bounding circles
1739 int * rank_buffer;
1740 int * num_ranks_buffer =
1741 xmalloc((grid->num_cells + grid->num_vertices + grid->num_edges) *
1742 sizeof(*num_ranks_buffer));
1743 int * num_cell_ranks = num_ranks_buffer;
1744 int * num_vertex_ranks = num_ranks_buffer + grid->num_cells;
1745 int * num_edge_ranks =
1746 num_ranks_buffer + grid->num_cells + grid->num_vertices;
1747 size_t * dist_cell_rank_offsets =
1748 xmalloc((grid->num_cells + 1) * sizeof(*dist_cell_rank_offsets));
1750 proc_sphere_part, grid, comm,
1751 &rank_buffer, num_cell_ranks, dist_cell_rank_offsets);
1752
1753 size_t rank_buffer_size = dist_cell_rank_offsets[grid->num_cells];
1754 size_t rank_buffer_array_size = dist_cell_rank_offsets[grid->num_cells];
1755
1756 // determine dist ranks for all vertices based on the dist ranks of
1757 // adjacent cells
1759 &rank_buffer, &rank_buffer_size, &rank_buffer_array_size, num_vertex_ranks,
1761 (void*)grid, num_cell_ranks, dist_cell_rank_offsets);
1762
1763 // determine dist ranks for all edges based on the dist ranks of
1764 // adjacent cells
1765 yac_size_t_2_pointer edge_to_cell =
1768 grid->core_cell_mask, grid->num_cells, grid->num_edges);
1770 &rank_buffer, &rank_buffer_size, &rank_buffer_array_size, num_edge_ranks,
1772 (void*)edge_to_cell, num_cell_ranks, dist_cell_rank_offsets);
1773 free(edge_to_cell);
1774
1775 int comm_size;
1776 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1777
1778 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1780 3, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
1781 size_t * size_t_buffer =
1782 xmalloc(4 * (size_t)comm_size * sizeof(*size_t_buffer));
1783 size_t * total_sendcounts = size_t_buffer + 0 * comm_size;
1784 size_t * total_recvcounts = size_t_buffer + 1 * comm_size;
1785 size_t * total_sdispls = size_t_buffer + 2 * comm_size;
1786 size_t * total_rdispls = size_t_buffer + 3 * comm_size;
1787
1788 struct {
1789 size_t count;
1790 int * num_ranks;
1791 int * core_mask;
1792 yac_int * ids;
1793 } cve_data[3] =
1794 {{.count = grid->num_cells,
1795 .num_ranks = num_cell_ranks,
1796 .core_mask = grid->core_cell_mask,
1797 .ids = grid->cell_ids},
1798 {.count = grid->num_vertices,
1799 .num_ranks = num_vertex_ranks,
1800 .core_mask = grid->core_vertex_mask,
1801 .ids = grid->vertex_ids},
1802 {.count = grid->num_edges,
1803 .num_ranks = num_edge_ranks,
1804 .core_mask = grid->core_edge_mask,
1805 .ids = grid->edge_ids}};
1806 size_t offset = 0;
1807
1808 // determine number of cells/vertices/edges that have to be
1809 // sent to other processes
1810 for (int location = 0; location < 3; ++location) {
1811 size_t count = cve_data[location].count;
1812 int * num_ranks = cve_data[location].num_ranks;
1813 int * core_mask = cve_data[location].core_mask;
1814 for (size_t i = 0; i < count; ++i) {
1815 int curr_num_ranks = num_ranks[i];
1816 int * ranks = rank_buffer + offset;
1817 offset += (size_t)curr_num_ranks;
1818 if (core_mask[i])
1819 for (int j = 0; j < curr_num_ranks; ++j)
1820 sendcounts[3 * ranks[j] + location]++;
1821 }
1822 }
1823
1825 3, sendcounts, recvcounts, sdispls, rdispls, comm);
1826
1827 size_t receive_counts[3] = {0,0,0};
1828 size_t saccu = 0, raccu = 0;
1829 for (int i = 0; i < comm_size; ++i) {
1830 total_sdispls[i] = saccu;
1831 total_rdispls[i] = raccu;
1832 total_sendcounts[i] = 0;
1833 total_recvcounts[i] = 0;
1834 for (int location = 0; location < 3; ++location) {
1835 total_sendcounts[i] += sendcounts[3 * i + location];
1836 total_recvcounts[i] += recvcounts[3 * i + location];
1837 receive_counts[location] += recvcounts[3 * i + location];
1838 }
1839 saccu += total_sendcounts[i];
1840 raccu += total_recvcounts[i];
1841 }
1842 size_t local_data_count = total_sendcounts[comm_size - 1] +
1843 total_sdispls[comm_size - 1];
1844 size_t recv_count = total_recvcounts[comm_size - 1] +
1845 total_rdispls[comm_size - 1];
1846
1847 struct id_pos * id_pos_buffer =
1848 xmalloc((local_data_count + recv_count) * sizeof(*id_pos_buffer));
1849 struct id_pos * id_pos_send_buffer = id_pos_buffer;
1850 struct id_pos * id_pos_recv_buffer =
1851 id_pos_buffer + local_data_count;
1852
1853 // pack cell/vertex/edge information for distributed owners
1854 offset = 0;
1855 for (int location = 0; location < 3; ++location) {
1856 size_t count = cve_data[location].count;
1857 int * num_ranks = cve_data[location].num_ranks;
1858 int * core_mask = cve_data[location].core_mask;
1859 yac_int * ids = cve_data[location].ids;
1860 for (size_t i = 0; i < count; ++i) {
1861 int curr_num_ranks = num_ranks[i];
1862 int * ranks = rank_buffer + offset;
1863 offset += (size_t)curr_num_ranks;
1864 if (core_mask[i]) {
1865 yac_int global_id = ids[i];
1866 for (int j = 0; j < curr_num_ranks; ++j) {
1867 size_t pos = sdispls[3 * ranks[j] + location + 1]++;
1868 id_pos_send_buffer[pos].global_id = global_id;
1869 id_pos_send_buffer[pos].orig_pos = i;
1870 }
1871 }
1872 }
1873 }
1874 free(num_ranks_buffer);
1875 free(rank_buffer);
1876 free(dist_cell_rank_offsets);
1877
1878 MPI_Datatype id_pos_dt = yac_get_id_pos_mpi_datatype(comm);
1879
1880 // exchange cell/vertex/edge information for distributed owners
1882 id_pos_send_buffer, total_sendcounts, total_sdispls,
1883 id_pos_recv_buffer, total_recvcounts, total_rdispls,
1884 sizeof(*id_pos_send_buffer), id_pos_dt, comm);
1885
1886 yac_mpi_call(MPI_Type_free(&id_pos_dt), comm);
1887
1888 size_t dist_owner_counts[3] = {0, 0, 0};
1889 for (int i = 0; i < comm_size; ++i)
1890 for (int location = 0; location < 3; ++location)
1891 dist_owner_counts[location] += recvcounts[3 * i + location];
1892 size_t max_dist_owner_count =
1893 MAX(MAX(dist_owner_counts[0], dist_owner_counts[1]), dist_owner_counts[2]);
1894 struct single_remote_point * temp_buffer =
1895 xmalloc(max_dist_owner_count * sizeof(*temp_buffer));
1896
1897 struct remote_points ** dist_owners = xmalloc(3 * sizeof(*dist_owners));
1898
1899 // unpack data
1900 for (int location = 0; location < 3; ++location) {
1901
1902 size_t count = 0;
1903 for (int i = 0; i < comm_size; ++i) {
1904 size_t curr_recvcount = recvcounts[3 * i + location];
1905 struct id_pos * curr_id_pos =
1906 id_pos_recv_buffer + rdispls[3 * i + location];
1907 for (size_t k = 0; k < curr_recvcount; ++k, ++count) {
1908 temp_buffer[count].global_id = curr_id_pos[k].global_id;
1909 temp_buffer[count].data.orig_pos = curr_id_pos[k].orig_pos;
1910 temp_buffer[count].data.rank = i;
1911 }
1912 }
1913
1914 // sort received global ids
1915 qsort(temp_buffer, count, sizeof(*temp_buffer),
1917
1918 struct remote_point * unique_ids = xmalloc(count * sizeof(*unique_ids));
1919 size_t num_unique_ids = 0;
1920
1921 // determine unique global ids
1922 yac_int prev_id = (count > 0)?temp_buffer[0].global_id - 1:-1;
1923 for (size_t i = 0; i < count; ++i) {
1924
1925 yac_int curr_id = temp_buffer[i].global_id;
1926 if (curr_id != prev_id) {
1927 prev_id = curr_id;
1928 unique_ids[num_unique_ids].global_id = curr_id;
1929 unique_ids[num_unique_ids].data.count = 1;
1930 num_unique_ids++;
1931 } else {
1932 unique_ids[num_unique_ids-1].data.count++;
1933 }
1934 }
1935
1936 size_t remote_point_info_buffer_size = 0;
1937 for (size_t i = 0; i < num_unique_ids; ++i)
1938 if (unique_ids[i].data.count > 1)
1939 remote_point_info_buffer_size +=
1940 (size_t)(unique_ids[i].data.count);
1941
1942 dist_owners[location] =
1943 xmalloc(remote_point_info_buffer_size * sizeof(struct remote_point_info) +
1944 sizeof(**dist_owners));
1945 dist_owners[location]->data =
1946 (unique_ids = xrealloc(unique_ids, num_unique_ids * sizeof(*unique_ids)));
1947 dist_owners[location]->count = num_unique_ids;
1948
1949 for (size_t i = 0, l = 0, offset = 0; i < num_unique_ids; ++i) {
1950 int curr_count = unique_ids[i].data.count;
1951 if (curr_count == 1) {
1952 unique_ids[i].data.data.single = temp_buffer[l].data;
1953 ++l;
1954 } else {
1955 unique_ids[i].data.data.multi = &(dist_owners[location]->buffer[offset]);
1956 for (int k = 0; k < curr_count; ++k, ++l, ++offset) {
1957 dist_owners[location]->buffer[offset] = temp_buffer[l].data;
1958 }
1959 }
1960 }
1961
1962 qsort(
1963 unique_ids, num_unique_ids, sizeof(*unique_ids), compare_remote_point);
1964 }
1965
1966 free(id_pos_buffer);
1967 free(temp_buffer);
1968 free(size_t_buffer);
1969 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1970
1971 return dist_owners;
1972}
1973
1975 yac_int * ids, size_t count, yac_int ** sorted_ids, size_t ** reorder_idx) {
1976
1977 yac_int * sorted_ids_ = xrealloc(*sorted_ids, count * sizeof(*sorted_ids_));
1978 size_t * reorder_idx_ = xrealloc(*reorder_idx, count * sizeof(*reorder_idx_));
1979
1980 memcpy(sorted_ids_, ids, count * sizeof(*sorted_ids_));
1981 for (size_t i = 0; i < count; ++i) reorder_idx_[i] = i;
1982
1983 yac_quicksort_index_yac_int_size_t(sorted_ids_, count, reorder_idx_);
1984
1985 *sorted_ids = sorted_ids_;
1986 *reorder_idx = reorder_idx_;
1987}
1988
1989static Xt_xmap generate_xmap_data(
1990 void * data, size_t count, MPI_Comm comm,
1991 void(*set_sendcounts)(void*,size_t,size_t*),
1992 void(*pack)(void*,size_t,size_t*,int*,int*)) {
1993
1994 int comm_size;
1995 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1996
1997 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1999 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
2000
2001 set_sendcounts(data, count, sendcounts);
2002
2004 1, sendcounts, recvcounts, sdispls, rdispls, comm);
2005 size_t num_src_msg = 0, num_dst_msg = 0;
2006 for (int i = 0; i < comm_size; ++i) {
2007 num_src_msg += (recvcounts[i] > 0);
2008 num_dst_msg += (sendcounts[i] > 0);
2009 }
2010
2011 size_t recv_count =
2012 rdispls[comm_size-1] + recvcounts[comm_size-1];
2013
2014 int * pos_buffer =
2015 xmalloc((recv_count + 2 * count) * sizeof(*pos_buffer));
2016 int * src_pos_buffer = pos_buffer;
2017 int * dst_pos_buffer = pos_buffer + recv_count;
2018 int * send_pos_buffer = pos_buffer + recv_count + count;
2019
2020 // pack send buffer
2021 pack(data, count, sdispls, dst_pos_buffer, send_pos_buffer);
2022
2023 // redistribute positions of requested data
2024 yac_alltoallv_int_p2p(
2025 send_pos_buffer, sendcounts, sdispls,
2026 src_pos_buffer, recvcounts, rdispls, comm);
2027
2028 struct Xt_com_pos * com_pos =
2029 xmalloc(((size_t)num_src_msg + (size_t)num_dst_msg) * sizeof(*com_pos));
2030 struct Xt_com_pos * src_com = com_pos;
2031 struct Xt_com_pos * dst_com = com_pos + num_src_msg;
2032
2033 // set transfer_pos pointers and transfer_pos counts in com_pos's
2034 num_src_msg = 0;
2035 num_dst_msg = 0;
2036 for (int i = 0; i < comm_size; ++i) {
2037 if (recvcounts[i] > 0) {
2038 src_com[num_src_msg].transfer_pos = src_pos_buffer;
2039 src_com[num_src_msg].num_transfer_pos = recvcounts[i];
2040 src_com[num_src_msg].rank = i;
2041 src_pos_buffer += recvcounts[i];
2042 ++num_src_msg;
2043 }
2044 if (sendcounts[i] > 0) {
2045 dst_com[num_dst_msg].transfer_pos = dst_pos_buffer;
2046 dst_com[num_dst_msg].num_transfer_pos = sendcounts[i];
2047 dst_com[num_dst_msg].rank = i;
2048 dst_pos_buffer += sendcounts[i];
2049 ++num_dst_msg;
2050 }
2051 }
2052 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
2053
2054 Xt_xmap xmap =
2055 xt_xmap_intersection_pos_new(
2056 num_src_msg, src_com, num_dst_msg, dst_com, comm);
2057
2058 free(com_pos);
2059 free(pos_buffer);
2060
2061 return xmap;
2062}
2063
2065 void * data, size_t count, size_t * sendcounts) {
2066
2067 struct remote_point * remote_point_data = (struct remote_point *)data;
2068
2069 for (size_t i = 0; i < count; ++i) {
2070 struct remote_point_info * curr_info =
2071 (remote_point_data[i].data.count > 1)?
2072 (remote_point_data[i].data.data.multi):
2073 (&(remote_point_data[i].data.data.single));
2074 sendcounts[curr_info->rank]++;
2075 }
2076}
2077
2079 void * data, size_t count, size_t * sdispls,
2080 int * dst_pos_buffer, int * send_pos_buffer) {
2081
2082 struct remote_point * remote_point_data = (struct remote_point *)data;
2083
2084 YAC_ASSERT(
2085 count <= INT_MAX,
2086 "ERROR(generate_xmap_pack_remote_points): count exceeds INT_MAX");
2087
2088 for (size_t i = 0; i < count; ++i) {
2089 struct remote_point_info * curr_info =
2090 (remote_point_data[i].data.count > 1)?
2091 (remote_point_data[i].data.data.multi):
2092 (&(remote_point_data[i].data.data.single));
2093 size_t pos = sdispls[curr_info->rank+1]++;
2094 dst_pos_buffer[pos] = i;
2095 send_pos_buffer[pos] = (int)(curr_info->orig_pos);
2096 }
2097}
2098
2100 struct remote_point * remote_point_data, size_t count, MPI_Comm comm) {
2101
2102 return
2103 generate_xmap_data(remote_point_data, count, comm,
2106}
2107
2109 void * data, size_t count, size_t * sendcounts) {
2110
2111 struct remote_point_info * point_infos = (struct remote_point_info *)data;
2112
2113 for (size_t i = 0; i < count; ++i) sendcounts[point_infos[i].rank]++;
2114}
2115
2117 void * data, size_t count, size_t * sdispls,
2118 int * dst_pos_buffer, int * send_pos_buffer) {
2119
2120 struct remote_point_info * point_infos = (struct remote_point_info *)data;
2121
2122 YAC_ASSERT(
2123 count <= INT_MAX,
2124 "ERROR(generate_xmap_pack_remote_point_info): count exceeds INT_MAX");
2125
2126 for (size_t i = 0; i < count; ++i) {
2127 size_t pos = sdispls[point_infos[i].rank+1]++;
2128 dst_pos_buffer[pos] = i;
2129 send_pos_buffer[pos] = (int)(point_infos[i].orig_pos);
2130 }
2131}
2132
2134 struct remote_point_info * point_infos, size_t count, MPI_Comm comm) {
2135
2136 return
2137 generate_xmap_data(point_infos, count, comm,
2140}
2141
2143 const void * a, const void * b) {
2144
2145 return (((const struct single_remote_point_reorder *)a)->data.global_id >
2146 ((const struct single_remote_point_reorder *)b)->data.global_id) -
2147 (((const struct single_remote_point_reorder *)a)->data.global_id <
2148 ((const struct single_remote_point_reorder *)b)->data.global_id);
2149}
2150
2152 const void * a, const void * b) {
2153
2154 return (((const struct single_remote_point_reorder *)a)->reorder_idx >
2155 ((const struct single_remote_point_reorder *)b)->reorder_idx) -
2156 (((const struct single_remote_point_reorder *)a)->reorder_idx <
2157 ((const struct single_remote_point_reorder *)b)->reorder_idx);
2158}
2159
2161 size_t max_num_cell_ve, size_t num_cells, int * num_ve_per_cell,
2162 struct single_remote_point_reorder * cell_ve_point_data,
2163 yac_int ** ids, size_t * num_ids, size_t ** cell_to_ve, Xt_xmap * xmap,
2164 MPI_Comm comm) {
2165
2166 size_t num_total_ve = num_cells * max_num_cell_ve;
2167
2168 size_t total_num_cell_ve = 0;
2169 for (size_t i = 0, k = 0, l = 0; i < num_cells; ++i) {
2170 size_t num_vertices = (size_t)(num_ve_per_cell[i]);
2171 total_num_cell_ve += num_vertices;
2172 size_t j = 0;
2173 for (; j < num_vertices; ++j, ++k, ++l) {
2174 cell_ve_point_data[k].reorder_idx = l;
2175 }
2176 for (; j < max_num_cell_ve; ++j, ++k) {
2177 cell_ve_point_data[k].data.global_id = XT_INT_MAX;
2178 cell_ve_point_data[k].reorder_idx = SIZE_MAX;
2179 }
2180 }
2181 qsort(cell_ve_point_data, num_total_ve, sizeof(*cell_ve_point_data),
2183 yac_int * ids_ = xmalloc(total_num_cell_ve * sizeof(*ids_));
2184 size_t num_ids_ = 0;
2185 size_t * cell_to_ve_ =
2186 xmalloc(total_num_cell_ve * sizeof(*cell_to_ve_));
2187 struct remote_point_info * ve_point_info =
2188 xmalloc(total_num_cell_ve * sizeof(*ve_point_info));
2189 yac_int prev_global_id = XT_INT_MAX;
2190 for (size_t i = 0; i < num_total_ve; ++i) {
2191 yac_int curr_global_id = cell_ve_point_data[i].data.global_id;
2192 size_t curr_reorder_idx = cell_ve_point_data[i].reorder_idx;
2193 if (curr_global_id == XT_INT_MAX) break;
2194 if (curr_global_id != prev_global_id) {
2195 ids_[num_ids_] = (prev_global_id = curr_global_id);
2196 ve_point_info[num_ids_] = cell_ve_point_data[i].data.data;
2197 num_ids_++;
2198 }
2199 cell_to_ve_[curr_reorder_idx] = num_ids_ - 1;
2200 }
2201
2202 *ids = xrealloc(ids_, num_ids_ * sizeof(*ids_));
2203 *num_ids = num_ids_;
2204 *cell_to_ve = cell_to_ve_;
2205 *xmap = generate_xmap_from_remote_point_info(ve_point_info, num_ids_, comm);
2206 free(ve_point_info);
2207}
2208
2209static MPI_Datatype yac_get_coordinate_mpi_datatype(MPI_Comm comm) {
2210
2211 MPI_Datatype coord_dt;
2212 yac_mpi_call(MPI_Type_contiguous(3, MPI_DOUBLE, &coord_dt), comm);
2213 yac_mpi_call(MPI_Type_commit(&coord_dt), comm);
2214 return coord_dt;
2215}
2216
2218 struct yac_field_data * orig_field_data, size_t dist_size,
2219 Xt_redist redist_mask, Xt_redist redist_coords, MPI_Comm comm) {
2220
2221 struct yac_field_data * dist_field_data = yac_field_data_empty_new();
2222
2223 uint64_t counts[2], max_counts[2];
2224 if (orig_field_data != NULL) {
2225 counts[0] = yac_field_data_get_masks_count(orig_field_data);
2226 counts[1] = yac_field_data_get_coordinates_count(orig_field_data);
2227 } else {
2228 counts[0] = 0;
2229 counts[1] = 0;
2230 }
2232 MPI_Allreduce(
2233 counts, max_counts, 2, MPI_UINT64_T, MPI_MAX, comm), comm);
2234 YAC_ASSERT(
2235 (orig_field_data == NULL) ||
2236 ((counts[0] == max_counts[0]) && (counts[1] == max_counts[1])),
2237 "ERROR(field_data_init): inconsistent number of masks or coordinates")
2238
2239 int * data_available_flag =
2240 xcalloc(2 * max_counts[0] + max_counts[1], sizeof(*data_available_flag));
2241
2242 for (size_t i = 0; i < counts[0]; ++i) {
2243 data_available_flag[i] =
2244 yac_field_data_get_mask_data(orig_field_data, i) != NULL;
2245 data_available_flag[i + counts[0]] =
2246 (yac_field_data_get_mask_name(orig_field_data, i) != NULL)?
2247 ((int)strlen(yac_field_data_get_mask_name(orig_field_data, i))+1):0;
2248 }
2249 for (size_t i = 0; i < counts[1]; ++i)
2250 data_available_flag[i + 2 * counts[0]] =
2251 yac_field_data_get_coordinates_data(orig_field_data, i) != NULL;
2252
2254 MPI_Allreduce(
2255 MPI_IN_PLACE, data_available_flag,
2256 (int)(2 * max_counts[0] + max_counts[1]), MPI_INT, MPI_MAX, comm), comm);
2257
2258 for (size_t i = 0; i < counts[0]; ++i) {
2259 YAC_ASSERT(
2260 data_available_flag[i] ==
2261 (yac_field_data_get_mask_data(orig_field_data, i) != NULL),
2262 "ERROR(field_data_init): inconsistent availability of masks")
2263 int mask_name_len =
2264 (yac_field_data_get_mask_name(orig_field_data, i) != NULL)?
2265 ((int)strlen(yac_field_data_get_mask_name(orig_field_data, i))+1):0;
2266 YAC_ASSERT(
2267 data_available_flag[i + counts[0]] ==
2268 mask_name_len,
2269 "ERROR(field_data_init): inconsistent mask names")
2270 }
2271
2272 for (size_t i = 0; i < counts[1]; ++i)
2273 YAC_ASSERT(
2274 data_available_flag[i + 2 * counts[0]] ==
2275 (yac_field_data_get_coordinates_data(orig_field_data, i) != NULL),
2276 "ERROR(field_data_init): inconsistent availability of coordinates")
2277
2278 for (uint64_t i = 0; i < max_counts[0]; ++i) {
2279 int * dist_mask = NULL;
2280 if (data_available_flag[i]) {
2281 dist_mask = xmalloc(dist_size * sizeof(*dist_mask));
2282 int const * orig_mask =
2283 (orig_field_data != NULL)?
2284 yac_field_data_get_mask_data(orig_field_data, i):NULL;
2285 xt_redist_s_exchange1(redist_mask, orig_mask, dist_mask);
2286 }
2287
2288 int mask_name_len = data_available_flag[i + max_counts[0]];
2289 char * mask_name = NULL;
2290 if (mask_name_len > 0) {
2291 mask_name = xmalloc((size_t)mask_name_len * sizeof(*mask_name));
2292 if ((orig_field_data != NULL) &&
2293 (yac_field_data_get_mask_name(orig_field_data, i) != NULL))
2294 memcpy(
2295 mask_name, yac_field_data_get_mask_name(orig_field_data, i),
2296 (size_t)mask_name_len);
2297 else
2298 memset(mask_name, 0, (size_t)mask_name_len * sizeof(*mask_name));
2300 MPI_Allreduce(
2301 MPI_IN_PLACE, mask_name, mask_name_len, MPI_CHAR, MPI_MAX, comm),
2302 comm);
2303 YAC_ASSERT(
2304 (orig_field_data == NULL) ||
2305 (yac_field_data_get_mask_name(orig_field_data, i) == NULL) ||
2306 !memcmp(
2307 yac_field_data_get_mask_name(orig_field_data, i), mask_name,
2308 (size_t)mask_name_len * sizeof(*mask_name)),
2309 "ERROR(field_data_init): inconsistent mask names")
2310 }
2311 yac_field_data_add_mask_nocpy(dist_field_data, dist_mask, mask_name);
2312 }
2313
2314 for (uint64_t i = 0; i < max_counts[1]; ++i) {
2315 yac_coordinate_pointer dist_coordinates = NULL;
2316 if (data_available_flag[i + 2 * max_counts[0]]) {
2317 dist_coordinates = xmalloc(dist_size * sizeof(*dist_coordinates));
2318 yac_const_coordinate_pointer orig_coordinates =
2319 (orig_field_data != NULL)?
2320 yac_field_data_get_coordinates_data(orig_field_data, i):NULL;
2321 xt_redist_s_exchange1(redist_coords, orig_coordinates, dist_coordinates);
2322 }
2323 yac_field_data_add_coordinates_nocpy(dist_field_data, dist_coordinates);
2324 }
2325
2326 free(data_available_flag);
2327
2328 return dist_field_data;
2329}
2330
2332 struct proc_sphere_part_node * proc_sphere_part,
2333 struct yac_basic_grid * grid, MPI_Comm comm) {
2334
2335 struct yac_basic_grid_data * grid_data = yac_basic_grid_get_data(grid);
2336
2337 int comm_rank;
2338 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
2339
2340 int max_num_vertices_per_cell = 0;
2341 { // compute the global maximum number of vertices per cell
2342 for (size_t i = 0; i < grid_data->num_cells; ++i)
2343 if (grid_data->num_vertices_per_cell[i] > max_num_vertices_per_cell)
2344 max_num_vertices_per_cell = grid_data->num_vertices_per_cell[i];
2345 yac_mpi_call(MPI_Allreduce(MPI_IN_PLACE, &max_num_vertices_per_cell, 1,
2346 MPI_INT, MPI_MAX, comm), comm);
2347 }
2348
2349 struct remote_points ** dist_owner =
2350 generate_dist_remote_points(proc_sphere_part, grid_data, comm);
2351
2352 Xt_xmap xmap_cell_orig_to_dist =
2354 dist_owner[YAC_LOC_CELL]->data, dist_owner[YAC_LOC_CELL]->count, comm);
2355
2356 MPI_Datatype dt_single_remote_point =
2358 max_num_vertices_per_cell, comm);
2359 MPI_Datatype dt_coord = yac_get_coordinate_mpi_datatype(comm);
2360
2361 Xt_redist redist_cell_yac_int,
2362 redist_cell_int,
2363 redist_cell_corner_point_data,
2364 redist_cell_coords;
2365 redist_cell_yac_int = xt_redist_p2p_new(xmap_cell_orig_to_dist, yac_int_dt);
2366 redist_cell_int = xt_redist_p2p_new(xmap_cell_orig_to_dist, MPI_INT);
2367 redist_cell_corner_point_data =
2368 xt_redist_p2p_new(xmap_cell_orig_to_dist, dt_single_remote_point);
2369 yac_mpi_call(MPI_Type_free(&dt_single_remote_point), comm);
2370 redist_cell_coords = xt_redist_p2p_new(xmap_cell_orig_to_dist, dt_coord);
2371
2372 xt_xmap_delete(xmap_cell_orig_to_dist);
2373
2374 size_t num_cells = dist_owner[YAC_LOC_CELL]->count;
2375 size_t max_num_cell_corners =
2376 (size_t)max_num_vertices_per_cell * num_cells;
2377 size_t max_num_local_cell_corners =
2378 (size_t)max_num_vertices_per_cell * grid_data->num_cells;
2379 yac_int * cell_ids = xmalloc(num_cells * sizeof(*cell_ids));
2380 int * num_vertices_per_cell =
2381 xmalloc(num_cells * sizeof(*num_vertices_per_cell));
2383 cell_corner_point_data =
2384 xmalloc(2 * (max_num_cell_corners + max_num_local_cell_corners) *
2385 sizeof(*cell_corner_point_data));
2386 struct single_remote_point_reorder * cell_edge_point_data =
2387 cell_corner_point_data + max_num_cell_corners;
2388 struct single_remote_point_reorder * local_cell_corner_point_data =
2389 cell_corner_point_data + 2 * max_num_cell_corners;
2390 struct single_remote_point_reorder * local_cell_edge_point_data =
2391 cell_corner_point_data + 2 * max_num_cell_corners +
2392 max_num_local_cell_corners;
2393 for (size_t i = 0; i < grid_data->num_cells; ++i){
2394 int num_corners = (size_t)(grid_data->num_vertices_per_cell[i]);
2395 size_t * corners = grid_data->cell_to_vertex + grid_data->cell_to_vertex_offsets[i];
2396 size_t * edges = grid_data->cell_to_edge + grid_data->cell_to_edge_offsets[i];
2397 struct single_remote_point_reorder * curr_local_cell_corner_point_data =
2398 local_cell_corner_point_data + i * (size_t)max_num_vertices_per_cell;
2399 struct single_remote_point_reorder * curr_local_cell_edge_point_data =
2400 local_cell_edge_point_data + i * (size_t)max_num_vertices_per_cell;
2401 for (size_t j = 0; j < num_corners; ++j) {
2402 curr_local_cell_corner_point_data[j].data.global_id = grid_data->vertex_ids[corners[j]];
2403 curr_local_cell_corner_point_data[j].data.data.rank = comm_rank;
2404 curr_local_cell_corner_point_data[j].data.data.orig_pos = corners[j];
2405 curr_local_cell_edge_point_data[j].data.global_id = grid_data->edge_ids[edges[j]];
2406 curr_local_cell_edge_point_data[j].data.data.rank = comm_rank;
2407 curr_local_cell_edge_point_data[j].data.data.orig_pos = edges[j];
2408 }
2409 }
2410
2411 xt_redist_s_exchange1(redist_cell_yac_int, grid_data->cell_ids, cell_ids);
2412 xt_redist_s_exchange1(
2413 redist_cell_int, grid_data->num_vertices_per_cell, num_vertices_per_cell);
2414 xt_redist_s_exchange1(
2415 redist_cell_corner_point_data,
2416 local_cell_corner_point_data, cell_corner_point_data);
2417 xt_redist_s_exchange1(
2418 redist_cell_corner_point_data,
2419 local_cell_edge_point_data, cell_edge_point_data);
2420
2421 struct yac_field_data * cell_field_data =
2424 redist_cell_int, redist_cell_coords, comm);
2425
2426 xt_redist_delete(redist_cell_coords);
2427 xt_redist_delete(redist_cell_corner_point_data);
2428 xt_redist_delete(redist_cell_yac_int);
2429 xt_redist_delete(redist_cell_int);
2430
2431 yac_int * vertex_ids;
2432 size_t num_vertices;
2433 size_t * cell_to_vertex;
2434 size_t * cell_to_vertex_offsets =
2435 xmalloc(num_cells * sizeof(*cell_to_vertex_offsets));
2436 Xt_xmap xmap_vertex_orig_to_dist;
2437 for (size_t i = 0, accu = 0; i < num_cells; ++i) {
2438 cell_to_vertex_offsets[i] = accu;
2439 accu += (size_t)(num_vertices_per_cell[i]);
2440 }
2442 max_num_vertices_per_cell, num_cells, num_vertices_per_cell,
2443 cell_corner_point_data, &vertex_ids, &num_vertices,
2444 &cell_to_vertex, &xmap_vertex_orig_to_dist, comm);
2445
2446 yac_int * edge_ids;
2447 size_t num_edges;
2448 size_t * cell_to_edge;
2449 size_t * cell_to_edge_offsets = cell_to_vertex_offsets;
2450 Xt_xmap xmap_edge_orig_to_dist;
2452 max_num_vertices_per_cell, num_cells, num_vertices_per_cell,
2453 cell_edge_point_data, &edge_ids, &num_edges,
2454 &cell_to_edge, &xmap_edge_orig_to_dist, comm);
2455
2456 free(cell_corner_point_data);
2457
2458 // generate redists for redistribution of vertex data
2459 Xt_redist redist_vertex_coords =
2460 xt_redist_p2p_new(xmap_vertex_orig_to_dist, dt_coord);
2461 Xt_redist redist_vertex_int =
2462 xt_redist_p2p_new(xmap_vertex_orig_to_dist, MPI_INT);
2463 xt_xmap_delete(xmap_vertex_orig_to_dist);
2464
2465 // get vertex coordinates
2466 yac_coordinate_pointer vertex_coordinates =
2467 xmalloc(num_vertices * sizeof(*vertex_coordinates));
2468 xt_redist_s_exchange1(
2469 redist_vertex_coords, grid_data->vertex_coordinates, vertex_coordinates);
2470
2471 struct yac_field_data * vertex_field_data =
2473 yac_basic_grid_get_field_data(grid, YAC_LOC_CORNER), num_vertices,
2474 redist_vertex_int, redist_vertex_coords, comm);
2475
2476 xt_redist_delete(redist_vertex_int);
2477 xt_redist_delete(redist_vertex_coords);
2478
2479 Xt_redist redist_edge_int,
2480 redist_edge_coords,
2481 redist_edge_2yac_int;
2482 { // generate redists for redistribution of edge data
2483
2484 MPI_Datatype dt_2yac_int;
2485 yac_mpi_call(MPI_Type_contiguous(2, yac_int_dt, &dt_2yac_int), comm);
2486 yac_mpi_call(MPI_Type_commit(&dt_2yac_int), comm);
2487
2488 redist_edge_int = xt_redist_p2p_new(xmap_edge_orig_to_dist, MPI_INT);
2489 redist_edge_coords = xt_redist_p2p_new(xmap_edge_orig_to_dist, dt_coord);
2490 redist_edge_2yac_int = xt_redist_p2p_new(xmap_edge_orig_to_dist, dt_2yac_int);
2491
2492 yac_mpi_call(MPI_Type_free(&dt_2yac_int), comm);
2493
2494 }
2495 xt_xmap_delete(xmap_edge_orig_to_dist);
2496
2497 enum yac_edge_type * edge_type = xmalloc(num_edges * sizeof(*edge_type));
2498
2499 { // get edge types
2500 int * temp_edge_type_src, * temp_edge_type_dst;
2501 if (sizeof(*edge_type) == sizeof(int)) {
2502 temp_edge_type_src = (int*)(grid_data->edge_type);
2503 temp_edge_type_dst = (int*)edge_type;
2504 } else {
2505 temp_edge_type_src =
2506 xmalloc(grid_data->num_edges * sizeof(*temp_edge_type_src));
2507 for (size_t i = 0; i < grid_data->num_edges; ++i)
2508 temp_edge_type_src[i] = (int)(grid_data->edge_type[i]);
2509 temp_edge_type_dst = xmalloc(num_edges * sizeof(*temp_edge_type_dst));
2510 for (size_t i = 0; i < num_edges; ++i)
2511 temp_edge_type_dst[i] = (int)(edge_type[i]);
2512 }
2513
2514 xt_redist_s_exchange1(
2515 redist_edge_int, temp_edge_type_src, temp_edge_type_dst);
2516
2517 if (sizeof(*edge_type) != sizeof(int)) {
2518
2519 for (size_t i = 0; i < num_edges; ++i)
2520 edge_type[i] = (enum yac_edge_type)(temp_edge_type_dst[i]);
2521
2522 free(temp_edge_type_src);
2523 free(temp_edge_type_dst);
2524 }
2525 }
2526
2527 struct yac_field_data * edge_field_data =
2530 redist_edge_int, redist_edge_coords, comm);
2531
2532 xt_redist_delete(redist_edge_int);
2533 xt_redist_delete(redist_edge_coords);
2534
2535 struct bounding_circle * cell_bnd_circles =
2536 xmalloc(num_cells * sizeof(*cell_bnd_circles));
2537 {
2538 struct grid_cell cell;
2539 cell.coordinates_xyz = xmalloc((size_t)max_num_vertices_per_cell *
2540 sizeof(*(cell.coordinates_xyz)));
2541 cell.edge_type = xmalloc((size_t)max_num_vertices_per_cell *
2542 sizeof(*(cell.edge_type)));
2543
2544 for (size_t i = 0; i < num_cells; ++i) {
2545 size_t * curr_cell_to_vertex =
2546 cell_to_vertex + cell_to_vertex_offsets[i];
2547 size_t * curr_cell_to_edge =
2548 cell_to_edge + cell_to_edge_offsets[i];
2549 for (int j = 0; j < num_vertices_per_cell[i]; ++j) {
2550 yac_coordinate_pointer curr_vertex_coords =
2551 vertex_coordinates + curr_cell_to_vertex[j];
2552 for (int k = 0; k < 3; ++k)
2553 cell.coordinates_xyz[j][k] = (*curr_vertex_coords)[k];
2554 cell.edge_type[j] = edge_type[curr_cell_to_edge[j]];
2555 }
2556 cell.num_corners = num_vertices_per_cell[i];
2557 if (cell.num_corners > 0)
2558 yac_get_cell_bounding_circle(cell, cell_bnd_circles + i);
2559 else
2560 cell_bnd_circles[i] =
2561 (struct bounding_circle) {
2562 .base_vector = {1.0, 0.0, 0.0},
2563 .inc_angle = SIN_COS_ZERO,
2564 .sq_crd = DBL_MAX};
2565 }
2566 free(cell.edge_type);
2567 free(cell.coordinates_xyz);
2568 }
2569
2570 yac_size_t_2_pointer edge_to_vertex =
2571 xmalloc(num_edges * sizeof(*edge_to_vertex));
2572
2573 // get edge to vertex
2574 {
2575 yac_int * vertex_id_buffer =
2576 xmalloc(
2577 2 * (grid_data->num_edges + num_edges) * sizeof(*vertex_id_buffer));
2578 yac_int * grid_edge_vertex_ids = vertex_id_buffer;
2579 yac_int * edge_vertex_ids = vertex_id_buffer + 2 * grid_data->num_edges;
2580
2581 size_t * grid_edge_to_vertex = &(grid_data->edge_to_vertex[0][0]);
2582
2583 for (size_t i = 0; i < 2 * grid_data->num_edges; ++i)
2584 grid_edge_vertex_ids[i] =
2585 grid_data->vertex_ids[grid_edge_to_vertex[i]];
2586
2587 xt_redist_s_exchange1(
2588 redist_edge_2yac_int, grid_edge_vertex_ids, edge_vertex_ids);
2589
2590 id2idx(edge_vertex_ids, &(edge_to_vertex[0][0]), 2 * num_edges,
2591 vertex_ids, num_vertices);
2592
2593 free(vertex_id_buffer);
2594 }
2595
2596 xt_redist_delete(redist_edge_2yac_int);
2597
2598 yac_mpi_call(MPI_Type_free(&dt_coord), comm);
2599
2600
2601 struct yac_dist_grid dist_grid =
2602 {.comm = comm,
2603 .vertex_coordinates = vertex_coordinates,
2604 .ids = {cell_ids, vertex_ids, edge_ids},
2605 .total_count = {num_cells, num_vertices, num_edges},
2606 .count = {num_cells, num_vertices, num_edges},
2607 .num_vertices_per_cell = num_vertices_per_cell,
2608 .cell_to_vertex = cell_to_vertex,
2609 .cell_to_vertex_offsets = cell_to_vertex_offsets,
2610 .cell_to_edge = cell_to_edge,
2611 .cell_to_edge_offsets = cell_to_edge_offsets,
2612 .edge_to_vertex = edge_to_vertex,
2613 .cell_bnd_circles = cell_bnd_circles,
2614 .edge_type = edge_type,
2615 .sorted_ids = {NULL, NULL, NULL},
2616 .sorted_reorder_idx = {NULL, NULL, NULL}};
2618 cell_ids, num_cells, &(dist_grid.sorted_ids[YAC_LOC_CELL]),
2619 &(dist_grid.sorted_reorder_idx[YAC_LOC_CELL]));
2621 vertex_ids, num_vertices, &(dist_grid.sorted_ids[YAC_LOC_CORNER]),
2622 &(dist_grid.sorted_reorder_idx[YAC_LOC_CORNER]));
2624 edge_ids, num_edges, &(dist_grid.sorted_ids[YAC_LOC_EDGE]),
2625 &(dist_grid.sorted_reorder_idx[YAC_LOC_EDGE]));
2626 dist_grid.field_data =
2628 cell_field_data, vertex_field_data, edge_field_data);
2629
2631 &dist_grid, proc_sphere_part, dist_owner);
2632
2633 generate_core_masks(&dist_grid, proc_sphere_part, comm_rank);
2634
2635 for (int i = 0; i < 3; ++i) {
2636 free(dist_owner[i]->data);
2637 free(dist_owner[i]);
2638 }
2639 free(dist_owner);
2640
2641 return dist_grid;
2642}
2643
2644static void setup_search_data(struct yac_dist_grid_pair * dist_grid_pair) {
2645
2646 // build sphere part for vertices
2647 for (int i = 0; i < 2; ++i)
2648 dist_grid_pair->vertex_sphere_part[i] =
2650 dist_grid_pair->dist_grid[i].count[YAC_LOC_CORNER],
2652 (dist_grid_pair->dist_grid[i].vertex_coordinates),
2653 dist_grid_pair->dist_grid[i].ids[YAC_LOC_CORNER]);
2654
2655 // build sphere part for bounding circle of cells
2656 for (int i = 0; i < 2; ++i) {
2657 dist_grid_pair->cell_sphere_part[i] =
2659 dist_grid_pair->dist_grid[i].cell_bnd_circles,
2660 dist_grid_pair->dist_grid[i].count[YAC_LOC_CELL]);
2661 }
2662}
2663
2664static void get_grid_cells(
2665 struct yac_basic_grid * grid, struct dist_cell * cells, MPI_Comm comm) {
2666
2667 struct yac_basic_grid_data * grid_data = yac_basic_grid_get_data(grid);
2668
2669 size_t num_cells = grid_data->num_cells;
2670 for (size_t i = 0; i < num_cells; ++i) {
2671
2672 double * cell_coord = cells[i].coord;
2673 for (int j = 0; j < 3; ++j) cell_coord[j] = 0.0;
2674
2675 if (grid_data->num_vertices_per_cell[i] == 0) continue;
2676
2677 size_t * curr_cell_to_vertex =
2678 grid_data->cell_to_vertex + grid_data->cell_to_vertex_offsets[i];
2679 // compute the middle point of the cell
2680 for (int j = 0; j < grid_data->num_vertices_per_cell[i]; ++j) {
2681 yac_coordinate_pointer curr_vertex_coords =
2682 grid_data->vertex_coordinates + curr_cell_to_vertex[j];
2683 for (int k = 0; k < 3; ++k)
2684 cell_coord[k] += (*curr_vertex_coords)[k];
2685 }
2686 normalise_vector(cell_coord);
2687 }
2688}
2689
2690static struct proc_sphere_part_node *
2692 struct yac_basic_grid * grid_a, struct yac_basic_grid * grid_b,
2693 MPI_Comm comm) {
2694
2695 size_t num_cells_a = yac_basic_grid_get_data(grid_a)->num_cells;
2696 size_t num_cells_b = yac_basic_grid_get_data(grid_b)->num_cells;
2697
2698 // gather cell centers from both grids into single array
2699 size_t num_cells = num_cells_a + num_cells_b;
2700 struct dist_cell * cells = xmalloc(num_cells * sizeof(*cells));
2701 get_grid_cells(grid_a, cells, comm);
2702 get_grid_cells(grid_b, cells + num_cells_a, comm);
2703
2704 // redistribute all cell centers and build parallel sphere
2705 // part for vertices
2706 struct proc_sphere_part_node * proc_sphere_part =
2707 yac_redistribute_cells(&cells, &num_cells, comm);
2708
2709 free(cells);
2710
2711 return proc_sphere_part;
2712}
2713
2715 struct yac_basic_grid * grid_a, struct yac_basic_grid * grid_b,
2716 MPI_Comm comm) {
2717
2718 YAC_ASSERT(
2719 grid_a,
2720 "ERROR(yac_dist_grid_pair_new): "
2721 "NULL is not a valid value for parameter grid_a")
2722 YAC_ASSERT(
2723 grid_b,
2724 "ERROR(yac_dist_grid_pair_new): "
2725 "NULL is not a valid value for parameter grid_b")
2726
2727 YAC_ASSERT(
2728 strcmp(yac_basic_grid_get_name(grid_a),
2729 yac_basic_grid_get_name(grid_b)),
2730 "ERROR(yac_dist_grid_pair_new): identical grid names")
2731
2732 MPI_Comm comm_copy;
2733 yac_mpi_call(MPI_Comm_dup(comm, &comm_copy), comm);
2734 comm = comm_copy;
2735
2736 // ensure same grid ordering on all processes
2737 if (strcmp(yac_basic_grid_get_name(grid_a),
2738 yac_basic_grid_get_name(grid_b)) > 0) {
2739 struct yac_basic_grid * grid_swap = grid_a;
2740 grid_a = grid_b;
2741 grid_b = grid_swap;
2742 }
2743
2744 struct yac_dist_grid_pair * grid_pair = xmalloc(1 * sizeof(*grid_pair));
2745
2746 grid_pair->grid_names[0] = strdup(yac_basic_grid_get_name(grid_a));
2747 grid_pair->grid_names[1] = strdup(yac_basic_grid_get_name(grid_b));
2748 grid_pair->comm = comm;
2749
2750 // generate a decomposition for the distributed grid pair
2751 // with the following properties:
2752 // * each process covers a unique area on the sphere
2753 // * number of cells (from grid_a and/or grid_b) per area
2754 // is roughly the same
2755 grid_pair->proc_sphere_part =
2756 generate_dist_grid_decomposition(grid_a, grid_b, comm);
2757
2758 // redistribute grid_a and grid_b according to decomposition
2759 grid_pair->dist_grid[0] =
2760 generate_dist_grid(grid_pair->proc_sphere_part, grid_a, comm);
2761 grid_pair->dist_grid[1] =
2762 generate_dist_grid(grid_pair->proc_sphere_part, grid_b, comm);
2763
2764 // build search data structures for local cells and vertices in
2765 // distributed grid
2766 setup_search_data(grid_pair);
2767
2768 return grid_pair;
2769}
2770
2772 struct yac_basic_grid * grid_a, struct yac_basic_grid * grid_b,
2773 MPI_Fint comm) {
2774
2775 return
2776 yac_dist_grid_pair_new(grid_a, grid_b, MPI_Comm_f2c(comm));
2777}
2778
2780 struct yac_dist_grid_pair * grid_pair) {
2781 return grid_pair->comm;
2782}
2783
2785 struct yac_dist_grid_pair * grid_pair, char const * grid_name) {
2786
2787 struct yac_dist_grid * dist_grid = NULL;
2788 for (int i = 0; (i < 2) && (dist_grid == NULL); ++i)
2789 if (!strcmp(grid_name, grid_pair->grid_names[i]))
2790 dist_grid = &(grid_pair->dist_grid[i]);
2791 YAC_ASSERT(
2792 dist_grid, "ERROR(yac_dist_grid_pair_get_dist_grid): invalid grid_name")
2793 return dist_grid;
2794}
2795
2797 struct yac_dist_grid * dist_grid) {
2798
2799 return (struct yac_const_basic_grid_data *)dist_grid;
2800}
2801
2803 struct yac_dist_grid * dist_grid, enum yac_location location) {
2804
2805 YAC_ASSERT(
2806 (location == YAC_LOC_CELL) ||
2807 (location == YAC_LOC_CORNER) ||
2808 (location == YAC_LOC_EDGE),
2809 "ERROR(yac_dist_grid_get_local_count): invalid location")
2810 size_t local_count = 0;
2811 size_t count = dist_grid->count[location];
2812 int * core_mask = dist_grid->core_mask[location];
2813 for (size_t i = 0; i < count; ++i) if (core_mask[i]) ++local_count;
2814 return local_count;
2815}
2816
2818 struct yac_dist_grid * dist_grid, enum yac_location location) {
2819
2820 YAC_ASSERT(
2821 (location == YAC_LOC_CELL) ||
2822 (location == YAC_LOC_CORNER) ||
2823 (location == YAC_LOC_EDGE),
2824 "ERROR(yac_dist_grid_get_count): invalid location")
2825 return dist_grid->total_count[location];
2826}
2827
2829 struct yac_dist_grid * dist_grid, enum yac_location location) {
2830
2831 YAC_ASSERT(
2832 (location == YAC_LOC_CELL) ||
2833 (location == YAC_LOC_CORNER) ||
2834 (location == YAC_LOC_EDGE),
2835 "ERROR(yac_dist_grid_get_core_mask): invalid location")
2836 return dist_grid->core_mask[location];
2837}
2838
2840 struct yac_dist_grid * dist_grid, enum yac_location location) {
2841
2842 YAC_ASSERT(
2843 (location == YAC_LOC_CELL) ||
2844 (location == YAC_LOC_CORNER) ||
2845 (location == YAC_LOC_EDGE),
2846 "ERROR(yac_dist_grid_get_global_ids): invalid location")
2847 return dist_grid->ids[location];
2848}
2849
2851 struct yac_dist_grid * dist_grid, struct yac_interp_field field,
2852 size_t ** indices, size_t * count) {
2853
2854 int const * mask = yac_dist_grid_get_field_mask(dist_grid, field);
2855
2856 size_t total_count = yac_dist_grid_get_count(dist_grid, field.location);
2857 int const * core_mask =
2858 yac_dist_grid_get_core_mask(dist_grid, field.location);
2859
2860 size_t * temp_indices = xmalloc(total_count * sizeof(*temp_indices));
2861
2862 size_t count_ = 0;
2863
2864 if (mask != NULL) {
2865 for (size_t i = 0; i < total_count; ++i)
2866 if (core_mask[i] && mask[i]) temp_indices[count_++] = i;
2867 } else {
2868 for (size_t i = 0; i < total_count; ++i)
2869 if (core_mask[i]) temp_indices[count_++] = i;
2870 }
2871
2872 *indices = xrealloc(temp_indices, count_ * sizeof(**indices));
2873 *count = count_;
2874}
2875
2877 struct yac_dist_grid * dist_grid, enum yac_location location) {
2878
2879 return
2880 yac_field_data_set_get_field_data(dist_grid->field_data, location);
2881}
2882
2884 struct yac_dist_grid * dist_grid, struct yac_interp_field field) {
2885
2886 if (field.masks_idx == SIZE_MAX) return NULL;
2887
2888 return
2889 (field.masks_idx != SIZE_MAX)?
2891 yac_dist_grid_get_field_data(dist_grid, field.location),
2892 field.masks_idx):NULL;
2893}
2894
2896 struct yac_dist_grid * dist_grid, struct yac_interp_field field) {
2897
2899 (field.coordinates_idx != SIZE_MAX)?
2901 yac_dist_grid_get_field_data(dist_grid, field.location),
2902 field.coordinates_idx):NULL;
2903
2904 // if no field coordinates are defined, but the location is at the corners of
2905 // of the grid cells, return coordinates of them
2906 return
2907 ((coords != NULL) || (field.location != YAC_LOC_CORNER))?
2908 coords:((yac_const_coordinate_pointer)(dist_grid->vertex_coordinates));
2909}
2910
2912 struct yac_dist_grid * dist_grid, struct yac_interp_field field) {
2913
2914 size_t total_count = yac_dist_grid_get_count(dist_grid, field.location);
2915
2916 int const * mask = yac_dist_grid_get_field_mask(dist_grid, field);
2917 if (mask == NULL)
2918 return yac_dist_grid_get_local_count(dist_grid, field.location);
2919
2920 int const * core_mask =
2921 yac_dist_grid_get_core_mask(dist_grid, field.location);
2922
2923 size_t unmasked_local_count = 0;
2924 for (size_t i = 0; i < total_count; ++i)
2925 if (core_mask[i] && mask[i]) ++unmasked_local_count;
2926 return unmasked_local_count;
2927}
2928
2930 struct remote_point_infos * point_infos, size_t count) {
2931
2932 for (size_t i = 0; i < count; ++i)
2933 if (point_infos[i].count > 1) free(point_infos[i].data.multi);
2934 free(point_infos);
2935}
2936
2937static void yac_dist_grid_free(struct yac_dist_grid grid) {
2938
2939 free(grid.vertex_coordinates);
2940 free(grid.num_vertices_per_cell);
2941 free(grid.cell_to_vertex);
2942 free(grid.cell_to_vertex_offsets);
2943 free(grid.cell_to_edge);
2944 free(grid.cell_bnd_circles);
2945 free(grid.edge_type);
2946 free(grid.edge_to_vertex);
2947 for (int i = 0; i < 3; ++i) {
2948 free(grid.ids[i]);
2949 free(grid.core_mask[i]);
2950 free(grid.sorted_ids[i]);
2951 free(grid.sorted_reorder_idx[i]);
2953 }
2955}
2956
2958
2959 if (grid_pair == NULL) return;
2960 free(grid_pair->grid_names[0]);
2961 free(grid_pair->grid_names[1]);
2962 yac_mpi_call(MPI_Comm_free(&(grid_pair->comm)), MPI_COMM_WORLD);
2964 for (int i = 0; i < 2; ++i) {
2965 yac_dist_grid_free(grid_pair->dist_grid[i]);
2968 }
2969 free(grid_pair);
2970}
2971
2972static int coord_in_cell(double coord[3], struct yac_dist_grid * dist_grid,
2973 size_t cell_idx, struct grid_cell * buffer_cell) {
2974
2976 (struct yac_const_basic_grid_data *)dist_grid, cell_idx, buffer_cell);
2977
2978 return
2980 coord, *buffer_cell, dist_grid->cell_bnd_circles[cell_idx]);
2981}
2982
2983static int coord_in_cell_gc(double coord[3], struct yac_dist_grid * dist_grid,
2984 size_t cell_idx, struct grid_cell * buffer_cell) {
2985
2987 (struct yac_const_basic_grid_data *)dist_grid, cell_idx, buffer_cell);
2988 for (size_t i = 0; i < buffer_cell->num_corners; ++i)
2989 buffer_cell->edge_type[i] = GREAT_CIRCLE_EDGE;
2990
2991 return
2993 coord, *buffer_cell, dist_grid->cell_bnd_circles[cell_idx]);
2994}
2995
2997 struct yac_const_basic_grid_data * grid_data, size_t cell_idx,
2998 struct grid_cell * buffer_cell) {
2999
3000 size_t num_vertices = (size_t)(grid_data->num_vertices_per_cell[cell_idx]);
3001
3002 struct grid_cell cell = *buffer_cell;
3003
3004 if (cell.array_size < num_vertices) {
3005 cell.coordinates_xyz =
3006 xrealloc(cell.coordinates_xyz, num_vertices *
3007 sizeof(*(cell.coordinates_xyz)));
3008 cell.edge_type = xrealloc(cell.edge_type, num_vertices *
3009 sizeof(*(cell.edge_type)));
3010 cell.array_size = num_vertices;
3011 *buffer_cell = cell;
3012 }
3013
3014 for (size_t i = 0; i < num_vertices; ++i) {
3015 size_t vertex_idx =
3016 grid_data->cell_to_vertex[
3017 grid_data->cell_to_vertex_offsets[cell_idx] + i];
3018 cell.coordinates_xyz[i][0] = grid_data->vertex_coordinates[vertex_idx][0];
3019 cell.coordinates_xyz[i][1] = grid_data->vertex_coordinates[vertex_idx][1];
3020 cell.coordinates_xyz[i][2] = grid_data->vertex_coordinates[vertex_idx][2];
3021 size_t edge_idx =
3022 grid_data->cell_to_edge[grid_data->cell_to_edge_offsets[cell_idx] + i];
3023 cell.edge_type[i] = grid_data->edge_type[edge_idx];
3024 }
3025 buffer_cell->num_corners = num_vertices;
3026}
3027
3029 struct yac_dist_grid_pair * grid_pair, char const * grid_name) {
3030
3031 struct bnd_sphere_part_search * search = NULL;
3032
3033 for (int i = 0; (i < 2) && (search == NULL); ++i)
3034 if (!strcmp(grid_name, grid_pair->grid_names[i]))
3035 search = grid_pair->cell_sphere_part[i];
3036 YAC_ASSERT(
3037 search != NULL,
3038 "ERROR(yac_dist_grid_pair_get_cell_sphere_part): invalid grid_name")
3039 return search;
3040}
3041
3043 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
3044 yac_coordinate_pointer search_coords, size_t count, size_t * cells,
3045 int (*coord_in_cell)(
3046 double coord[3], struct yac_dist_grid * dist_grid, size_t cell_idx,
3047 struct grid_cell * buffer_cell)) {
3048
3049 struct bnd_sphere_part_search * cell_sphere_part =
3050 dist_grid_pair_get_cell_sphere_part(grid_pair, grid_name);
3051 struct yac_dist_grid * dist_grid =
3052 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
3053
3054 size_t * temp_cells;
3055 size_t * num_cells_per_coord =
3056 xmalloc(count * sizeof(*num_cells_per_coord));
3057
3058 // search for all matching source cells
3060 cell_sphere_part, search_coords, count, &temp_cells,
3061 num_cells_per_coord);
3062
3063 struct grid_cell buffer_cell;
3064 yac_init_grid_cell(&buffer_cell);
3065
3066 // if we have multiple source cells for a single search coordinate, get the
3067 // source cell with the lowest global id
3068 for (size_t i = 0, k = 0; i < count; ++i) {
3069 size_t curr_num_cells = num_cells_per_coord[i];
3070 if (curr_num_cells == 0) {
3071 cells[i] = SIZE_MAX;
3072 } else if (curr_num_cells == 1) {
3073 if (coord_in_cell(
3074 search_coords[i], dist_grid, temp_cells[k], &buffer_cell))
3075 cells[i] = temp_cells[k];
3076 else
3077 cells[i] = SIZE_MAX;
3078 ++k;
3079 } else {
3080 size_t cell_idx = SIZE_MAX;
3081 yac_int cell_id = XT_INT_MAX;
3082 for (size_t j = 0; j < curr_num_cells; ++j, ++k) {
3083 size_t curr_cell_idx = temp_cells[k];
3084 yac_int curr_cell_id = dist_grid->ids[YAC_LOC_CELL][curr_cell_idx];
3085 if (!coord_in_cell(
3086 search_coords[i], dist_grid, curr_cell_idx, &buffer_cell))
3087 continue;
3088 if (curr_cell_id < cell_id) {
3089 cell_idx = curr_cell_idx;
3090 cell_id = curr_cell_id;
3091 }
3092 }
3093 cells[i] = cell_idx;
3094 }
3095 }
3096
3097 yac_free_grid_cell(&buffer_cell);
3098 free(num_cells_per_coord);
3099 free(temp_cells);
3100}
3101
3103 struct yac_dist_grid * dist_grid, enum yac_location location,
3104 struct single_remote_point_reorder * ids, size_t * count, size_t * idx) {
3105
3106 YAC_ASSERT(
3107 (location == YAC_LOC_CELL) ||
3108 (location == YAC_LOC_CORNER) ||
3109 (location == YAC_LOC_EDGE),
3110 "ERROR(lookup_single_remote_point_reorder_locally): invalid location")
3111
3112 yac_int * sorted_ids = dist_grid->sorted_ids[location];
3113 size_t * reorder_idx = dist_grid->sorted_reorder_idx[location];
3114 size_t num_ids = dist_grid->total_count[location];
3115
3116 size_t count_ = *count;
3117 size_t new_count = 0;
3118
3119 // sort ids by global ids
3120 qsort(ids, count_, sizeof(*ids),
3122
3123 for (size_t i = 0, j = 0; i < count_; ++i) {
3124 yac_int curr_id = ids[i].data.global_id;
3125 while ((j < num_ids) && (sorted_ids[j] < curr_id)) ++j;
3126 if ((j < num_ids) && (sorted_ids[j] == curr_id)) {
3127 idx[ids[i].reorder_idx] = reorder_idx[j];
3128 } else {
3129 if (i != new_count) ids[new_count] = ids[i];
3130 ++new_count;
3131 }
3132 }
3133
3134 *count = new_count;
3135}
3136
3138 struct yac_field_data * field_data, MPI_Comm comm) {
3139
3140 int pack_size_field_coord, pack_size_field_mask;
3141
3143 MPI_Pack_size(3, MPI_DOUBLE, comm, &pack_size_field_coord), comm);
3144 pack_size_field_coord *=
3145 (int)yac_field_data_get_coordinates_count(field_data);
3146
3148 MPI_Pack_size(1, MPI_INT, comm, &pack_size_field_mask), comm);
3149 pack_size_field_mask *=
3150 (int)yac_field_data_get_masks_count(field_data);
3151
3152 return pack_size_field_coord + pack_size_field_mask;
3153}
3154
3156 struct yac_field_data * cell_field_data,
3157 MPI_Datatype bnd_circle_dt, MPI_Comm comm) {
3158
3159 int pack_size_id,
3160 pack_size_num_vertices,
3161 pack_size_bnd_circle;
3162
3163 // id
3164 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &pack_size_id), comm);
3165 // num_vertices
3166 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &pack_size_num_vertices), comm);
3167 // bounding circle
3169 MPI_Pack_size(1, bnd_circle_dt, comm, &pack_size_bnd_circle), comm);
3170
3171 return pack_size_id + pack_size_num_vertices + pack_size_bnd_circle +
3172 get_pack_size_field_data(cell_field_data, comm);
3173}
3174
3176 struct yac_field_data * vertex_field_data, MPI_Comm comm) {
3177
3178 int pack_size_id,
3179 pack_size_vertex_coords;
3180 // id
3181 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &pack_size_id), comm);
3182 // vertex coordinates
3184 MPI_Pack_size(3, MPI_DOUBLE, comm, &pack_size_vertex_coords), comm);
3185
3186 return pack_size_id + pack_size_vertex_coords +
3187 get_pack_size_field_data(vertex_field_data, comm);
3188}
3189
3191 struct yac_field_data * edge_field_data, MPI_Comm comm) {
3192
3193 int pack_size_id,
3194 pack_size_edge_to_vertex,
3195 pack_size_edge_type;
3196 // id
3197 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &pack_size_id), comm);
3198 // edge type
3199 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &pack_size_edge_type), comm);
3200 // edge vertex ids
3202 MPI_Pack_size(2, yac_int_dt, comm, &pack_size_edge_to_vertex), comm);
3203
3204 return pack_size_id + pack_size_edge_type + pack_size_edge_to_vertex +
3205 get_pack_size_field_data(edge_field_data, comm);
3206}
3207
3209 struct yac_dist_grid * dist_grid, uint64_t * pos, size_t count,
3210 int * pack_sizes, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
3211 MPI_Comm comm) {
3212
3213 int pack_size_base_cell =
3216 dist_grid->field_data, YAC_LOC_CELL),
3217 bnd_circle_dt, comm);
3218 int pack_size_base_vertex =
3221 dist_grid->field_data, YAC_LOC_CORNER), comm);
3222 int pack_size_base_edge =
3225 dist_grid->field_data, YAC_LOC_EDGE), comm);
3226
3227 for (size_t i = 0; i < count; ++i) {
3228 size_t idx = (size_t)(pos[i]);
3229 int num_vertices = dist_grid->num_vertices_per_cell[idx];
3230 size_t * curr_vertices =
3231 dist_grid->cell_to_vertex + dist_grid->cell_to_vertex_offsets[idx];
3232 size_t * curr_edges =
3233 dist_grid->cell_to_edge + dist_grid->cell_to_edge_offsets[idx];
3234 int pack_size =
3235 pack_size_base_cell +
3236 num_vertices * (pack_size_base_vertex + pack_size_base_edge) +
3238 dist_grid->owners[YAC_LOC_CELL] + idx, point_info_dt, comm);
3239 for (int j = 0; j < num_vertices; ++j) {
3240 pack_size +=
3242 dist_grid->owners[YAC_LOC_CORNER] + curr_vertices[j],
3243 point_info_dt, comm) +
3245 dist_grid->owners[YAC_LOC_EDGE] + curr_edges[j], point_info_dt, comm);
3246 }
3247 pack_sizes[i] = pack_size;
3248 }
3249}
3250
3252 struct yac_dist_grid * dist_grid, uint64_t * pos, size_t count,
3253 int * pack_sizes, MPI_Datatype point_info_dt, MPI_Comm comm) {
3254
3255 int pack_size_base_vertex =
3258 dist_grid->field_data, YAC_LOC_CORNER), comm);
3259 for (size_t i = 0; i < count; ++i)
3260 pack_sizes[i] =
3261 pack_size_base_vertex +
3263 dist_grid->owners[YAC_LOC_CORNER] + pos[i], point_info_dt, comm);
3264}
3265
3267 struct yac_dist_grid * dist_grid, uint64_t * pos, size_t count,
3268 int * pack_sizes, MPI_Datatype point_info_dt, MPI_Comm comm) {
3269
3270 int pack_size_base_vertex =
3273 dist_grid->field_data, YAC_LOC_CORNER), comm);
3274 int pack_size_base_edge =
3277 dist_grid->field_data, YAC_LOC_EDGE), comm);
3278 for (size_t i = 0; i < count; ++i) {
3279 size_t * curr_vertices = dist_grid->edge_to_vertex[pos[i]];
3280 pack_sizes[i] =
3281 pack_size_base_edge +
3282 2 * pack_size_base_vertex +
3284 dist_grid->owners[YAC_LOC_EDGE] + pos[i], point_info_dt, comm) +
3286 dist_grid->owners[YAC_LOC_CORNER] + curr_vertices[0],
3287 point_info_dt, comm) +
3289 dist_grid->owners[YAC_LOC_CORNER] + curr_vertices[1],
3290 point_info_dt, comm);
3291 }
3292}
3293
3294static void get_pack_sizes(
3295 struct yac_dist_grid * dist_grid, enum yac_location location, uint64_t * pos,
3296 size_t count, int * pack_sizes, MPI_Datatype bnd_circle_dt,
3297 MPI_Datatype point_info_dt, MPI_Comm comm) {
3298
3299 YAC_ASSERT(
3300 (location == YAC_LOC_CELL) ||
3301 (location == YAC_LOC_CORNER) ||
3302 (location == YAC_LOC_EDGE),
3303 "ERROR(get_pack_sizes): invalid location")
3304
3305 switch(location) {
3306 default:
3307 case(YAC_LOC_CELL):
3309 dist_grid, pos, count, pack_sizes, bnd_circle_dt, point_info_dt, comm);
3310 break;
3311 case(YAC_LOC_CORNER):
3313 dist_grid, pos, count, pack_sizes, point_info_dt, comm);
3314 break;
3315 case(YAC_LOC_EDGE):
3317 dist_grid, pos, count, pack_sizes, point_info_dt, comm);
3318 break;
3319 };
3320}
3321
3323 size_t idx, void * buffer, int buffer_size, int * position,
3324 struct yac_field_data * field_data, MPI_Comm comm) {
3325
3326 size_t coordinates_count =
3328 size_t masks_count =
3330
3331 // coordinates
3332 for (size_t i = 0; i < coordinates_count; ++i)
3334 MPI_Pack(
3335 yac_field_data_get_coordinates_data(field_data, i)[idx],
3336 3, MPI_DOUBLE, buffer, buffer_size, position, comm), comm);
3337
3338 // masks
3339 for (size_t i = 0; i < masks_count; ++i)
3341 MPI_Pack(
3342 yac_field_data_get_mask_data(field_data, i) + idx, 1, MPI_INT, buffer,
3343 buffer_size, position, comm), comm);
3344}
3345
3347 struct yac_dist_grid * dist_grid, size_t idx, void * buffer, int buffer_size,
3348 int * position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
3349 MPI_Comm comm) {
3350
3351 UNUSED(bnd_circle_dt);
3352
3353 // id
3355 MPI_Pack(dist_grid->ids[YAC_LOC_CORNER] + idx, 1, yac_int_dt, buffer, buffer_size,
3356 position, comm), comm);
3357 // vertex coordinates
3359 MPI_Pack(&(dist_grid->vertex_coordinates[idx][0]), 3, MPI_DOUBLE, buffer,
3360 buffer_size, position, comm), comm);
3361 // vertex owner
3363 dist_grid->owners[YAC_LOC_CORNER] + idx, buffer, buffer_size, position,
3364 point_info_dt, comm);
3365 // pack field data
3367 idx, buffer, buffer_size, position,
3369}
3370
3372 struct yac_dist_grid * dist_grid, size_t idx, void * buffer, int buffer_size,
3373 int * position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
3374 MPI_Comm comm) {
3375
3376 UNUSED(bnd_circle_dt);
3377
3378 int edge_type = (int)(dist_grid->edge_type[idx]);
3379
3380 // id
3382 MPI_Pack(
3383 dist_grid->ids[YAC_LOC_EDGE] + idx, 1, yac_int_dt, buffer, buffer_size, position,
3384 comm), comm);
3385 // edge type
3387 MPI_Pack(
3388 &edge_type, 1, MPI_INT, buffer, buffer_size, position, comm), comm);
3389 // edge to vertex
3390 yac_int edge_to_vertex[2] = {
3391 dist_grid->ids[YAC_LOC_CORNER][dist_grid->edge_to_vertex[idx][0]],
3392 dist_grid->ids[YAC_LOC_CORNER][dist_grid->edge_to_vertex[idx][1]]};
3394 MPI_Pack(
3395 edge_to_vertex, 2, yac_int_dt, buffer, buffer_size, position, comm),
3396 comm);
3397 // edge owner
3399 dist_grid->owners[YAC_LOC_EDGE] + idx, buffer, buffer_size, position,
3400 point_info_dt, comm);
3401 // pack field data
3403 idx, buffer, buffer_size, position,
3405}
3406
3408 struct yac_dist_grid * dist_grid, size_t idx, void * buffer, int buffer_size,
3409 int * position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
3410 MPI_Comm comm) {
3411
3413 dist_grid, idx, buffer, buffer_size, position,
3414 bnd_circle_dt, point_info_dt, comm);
3415
3416 // pack edge vertices
3417 for (int i = 0; i < 2; ++i)
3419 dist_grid, dist_grid->edge_to_vertex[idx][i],
3420 buffer, buffer_size, position, bnd_circle_dt, point_info_dt, comm);
3421}
3422
3424 struct yac_dist_grid * dist_grid, size_t idx, void * buffer, int buffer_size,
3425 int * position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
3426 MPI_Comm comm) {
3427
3428 int num_vertices = dist_grid->num_vertices_per_cell[idx];
3429
3430 // id
3432 MPI_Pack(
3433 dist_grid->ids[YAC_LOC_CELL] + idx, 1, yac_int_dt, buffer, buffer_size, position,
3434 comm), comm);
3435 // pack field data
3437 idx, buffer, buffer_size, position,
3439 // num_vertices
3441 MPI_Pack(&num_vertices, 1, MPI_INT, buffer,
3442 buffer_size, position, comm), comm);
3443 // bounding_circle
3445 MPI_Pack(dist_grid->cell_bnd_circles + idx, 1, bnd_circle_dt, buffer,
3446 buffer_size, position, comm), comm);
3447 // cell owner
3449 dist_grid->owners[YAC_LOC_CELL] + idx, buffer, buffer_size, position,
3450 point_info_dt, comm);
3451
3452 for (int i = 0; i < num_vertices; ++i) {
3454 dist_grid,
3455 dist_grid->cell_to_vertex[dist_grid->cell_to_vertex_offsets[idx] + i],
3456 buffer, buffer_size, position, bnd_circle_dt, point_info_dt, comm);
3458 dist_grid,
3459 dist_grid->cell_to_edge[dist_grid->cell_to_edge_offsets[idx] + i],
3460 buffer, buffer_size, position, bnd_circle_dt, point_info_dt, comm);
3461 }
3462}
3463
3464static void pack_grid_data(
3465 struct yac_dist_grid * dist_grid, enum yac_location location, uint64_t * pos,
3466 size_t count, void ** pack_data, int * pack_sizes,
3467 MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm) {
3468
3469 get_pack_sizes(dist_grid, location, pos, count, pack_sizes,
3470 bnd_circle_dt, point_info_dt, comm);
3471
3472 size_t pack_size = 0;
3473 for (size_t i = 0; i < count; ++i) pack_size += (size_t)(pack_sizes[i]);
3474
3475 void * pack_data_ = xmalloc(pack_size);
3476
3477 YAC_ASSERT(
3478 (location == YAC_LOC_CELL) ||
3479 (location == YAC_LOC_CORNER) ||
3480 (location == YAC_LOC_EDGE),
3481 "ERROR(pack_grid_data): invalid location")
3482
3483 void (*func_pack[3])(
3484 struct yac_dist_grid * dist_grid, size_t idx, void * buffer,
3485 int buffer_size, int * position, MPI_Datatype bnd_circle_dt,
3486 MPI_Datatype point_info_dt, MPI_Comm comm) =
3488
3489 for (size_t i = 0, offset = 0; i < count; ++i) {
3490 int position = 0;
3491 func_pack[location](
3492 dist_grid, pos[i], (char*)pack_data_ + offset, pack_sizes[i],
3493 &position, bnd_circle_dt, point_info_dt, comm);
3494 pack_sizes[i] = position;
3495 offset += (size_t)position;
3496 }
3497
3498 *pack_data = pack_data_;
3499}
3500
3502 void * buffer, int buffer_size, int * position, size_t idx,
3503 struct temp_field_data temp_field_data, MPI_Comm comm) {
3504
3505 for (size_t i = 0; i < temp_field_data.coordinates_count; ++i)
3507 MPI_Unpack(
3508 buffer, buffer_size, position, temp_field_data.coordinates[i][idx],
3509 3, MPI_DOUBLE, comm), comm);
3510
3511 for (size_t i = 0; i < temp_field_data.masks_count; ++i)
3513 MPI_Unpack(buffer, buffer_size, position,
3514 temp_field_data.masks[i] + idx, 1, MPI_INT, comm), comm);
3515}
3516
3518 struct global_vertex_reorder * vertex, size_t idx, void * buffer,
3519 int buffer_size, int * position,
3520 struct temp_field_data temp_vertex_field_data,
3521 MPI_Datatype point_info_dt, MPI_Comm comm) {
3522
3523 // id
3525 MPI_Unpack(buffer, buffer_size, position, &(vertex[idx].global_id), 1,
3526 yac_int_dt, comm), comm);
3527 // vertex coordinates
3529 MPI_Unpack(buffer, buffer_size, position, &(vertex[idx].coord[0]), 3,
3530 MPI_DOUBLE, comm), comm);
3531 // vertex owners
3533 buffer, buffer_size, position, &(vertex[idx].owners), point_info_dt, comm);
3534 // unpack field data
3536 buffer, buffer_size, position, idx, temp_vertex_field_data, comm);
3537}
3538
3540 struct global_edge_reorder * edge, size_t idx, void * buffer,
3541 int buffer_size, int * position,
3542 struct temp_field_data temp_edge_field_data,
3543 MPI_Datatype point_info_dt, MPI_Comm comm) {
3544
3545 int edge_type;
3546
3547 // id
3549 MPI_Unpack(buffer, buffer_size, position, &(edge[idx].global_id), 1,
3550 yac_int_dt, comm), comm);
3551 // edge type
3553 MPI_Unpack(buffer, buffer_size, position, &edge_type, 1,
3554 MPI_INT, comm), comm);
3555 edge[idx].edge_type = (enum yac_edge_type)edge_type;
3556 // edge to vertex
3558 MPI_Unpack(buffer, buffer_size, position, edge[idx].edge_to_vertex, 2,
3559 yac_int_dt, comm), comm);
3560 // edge owners
3561 yac_remote_point_infos_unpack(buffer, buffer_size, position,
3562 &(edge[idx].owners), point_info_dt, comm);
3563 // unpack field data
3565 buffer, buffer_size, position, idx, temp_edge_field_data, comm);
3566}
3567
3569 const void * a, const void * b) {
3570
3571 return (((const struct global_vertex_reorder *)a)->global_id >
3572 ((const struct global_vertex_reorder *)b)->global_id) -
3573 (((const struct global_vertex_reorder *)a)->global_id <
3574 ((const struct global_vertex_reorder *)b)->global_id);
3575}
3576
3577static void add_field_data(
3578 struct yac_field_data * field_data, struct temp_field_data temp_field_data,
3579 void * reorder_idx, size_t reorder_idx_size,
3580 size_t old_count, size_t new_count) {
3581
3582 size_t add_count = new_count - old_count;
3583
3584 for (size_t i = 0; i < temp_field_data.masks_count; ++i) {
3585 int * temp_mask = temp_field_data.masks[i];
3586 int * mask =
3587 xrealloc(
3588 (void*)yac_field_data_get_mask_data(field_data, i),
3589 new_count * sizeof(*mask));
3590 yac_field_data_set_mask_data(field_data, i, mask);
3591 for (size_t i = 0, j = old_count; i < add_count; ++i, ++j) {
3592 size_t idx =
3593 *(size_t*)((unsigned char*)reorder_idx + i * reorder_idx_size);
3594 mask[j] = temp_mask[idx];
3595 }
3596 }
3597
3598 for (size_t i = 0; i < temp_field_data.coordinates_count; ++i) {
3600 yac_coordinate_pointer coordinates =
3601 xrealloc(
3602 (void*)yac_field_data_get_coordinates_data(field_data, i),
3603 new_count * sizeof(*coordinates));
3604 yac_field_data_set_coordinates_data(field_data, i, coordinates);
3605 for (size_t i = 0, j = old_count; i < add_count; ++i, ++j) {
3606 size_t idx =
3607 *(size_t*)((unsigned char*)reorder_idx + i * reorder_idx_size);
3608 coordinates[j][0] = temp_coordinates[idx][0];
3609 coordinates[j][1] = temp_coordinates[idx][1];
3610 coordinates[j][2] = temp_coordinates[idx][2];
3611 }
3612 }
3613}
3614
3616 struct remote_point_infos * point_infos) {
3617
3618 if (point_infos->count > 1) free(point_infos->data.multi);
3619}
3620
3622 struct yac_dist_grid * dist_grid, struct global_vertex_reorder * vertices,
3623 size_t count, size_t * idx,
3624 struct temp_field_data temp_vertex_field_data) {
3625
3626 if (count == 0) return;
3627
3628 // sort vertices global ids
3629 qsort(vertices, count, sizeof(*vertices),
3631
3632 yac_int * sorted_vertex_ids =
3633 dist_grid->sorted_ids[YAC_LOC_CORNER];
3634 size_t * sorted_vertex_reorder_idx =
3636
3637 yac_int prev_global_id = vertices[0].global_id - 1;
3638 size_t prev_idx = 0;
3639 size_t add_count = 0;
3640 size_t num_total_vertices = dist_grid->total_count[YAC_LOC_CORNER];
3641
3642 // determine which vertices need to be added to local data
3643 for (size_t i = 0, j = 0; i < count; ++i) {
3644
3645 yac_int curr_global_id = vertices[i].global_id;
3646 size_t curr_reorder_idx = vertices[i].reorder_idx;
3647
3648 // if the current global id is a duplicate
3649 if (prev_global_id == curr_global_id) {
3650 if (idx != NULL) idx[curr_reorder_idx] = prev_idx;
3652 continue;
3653 }
3654 prev_global_id = curr_global_id;
3655
3656 // check whether the current global id is already part of the local
3657 // grid data
3658 while ((j < num_total_vertices) && (sorted_vertex_ids[j] < curr_global_id))
3659 ++j;
3660
3661 // if we found a match in the local data
3662 if ((j < num_total_vertices) && (sorted_vertex_ids[j] == curr_global_id)) {
3663
3664 if (idx != NULL) idx[curr_reorder_idx] = sorted_vertex_reorder_idx[j];
3665 prev_idx = sorted_vertex_reorder_idx[j];
3667
3668 // if we need to add the current vertex to the local data
3669 } else {
3670
3671 if (idx != NULL) idx[curr_reorder_idx] = num_total_vertices + add_count;
3672 prev_idx = num_total_vertices + add_count;
3673 if (add_count != i) vertices[add_count] = vertices[i];
3674 ++add_count;
3675 }
3676 }
3677
3678 size_t new_num_total_vertices = num_total_vertices + add_count;
3679 yac_coordinate_pointer vertex_coordinates =
3680 xrealloc(dist_grid->vertex_coordinates, new_num_total_vertices *
3681 sizeof(*vertex_coordinates));
3682 yac_int * vertex_ids =
3683 xrealloc(dist_grid->ids[YAC_LOC_CORNER],
3684 new_num_total_vertices * sizeof(*vertex_ids));
3685 int * core_vertex_mask =
3686 xrealloc(dist_grid->core_mask[YAC_LOC_CORNER], new_num_total_vertices *
3687 sizeof(*core_vertex_mask));
3688 struct remote_point_infos * vertex_owners =
3689 xrealloc(dist_grid->owners[YAC_LOC_CORNER], new_num_total_vertices *
3690 sizeof(*vertex_owners));
3691 sorted_vertex_ids =
3692 xrealloc(
3693 sorted_vertex_ids, new_num_total_vertices * sizeof(*sorted_vertex_ids));
3694 sorted_vertex_reorder_idx =
3695 xrealloc(
3696 sorted_vertex_reorder_idx, new_num_total_vertices *
3697 sizeof(*sorted_vertex_reorder_idx));
3698
3699 // add the selected vertices to the local grid data
3700 for (size_t i = 0, j = num_total_vertices; i < add_count; ++i, ++j) {
3701
3702 vertex_coordinates[j][0] = vertices[i].coord[0];
3703 vertex_coordinates[j][1] = vertices[i].coord[1];
3704 vertex_coordinates[j][2] = vertices[i].coord[2];
3705 vertex_ids[j] = vertices[i].global_id;
3706 core_vertex_mask[j] = 0;
3707 vertex_owners[j] = vertices[i].owners;
3708 sorted_vertex_ids[j] = vertices[i].global_id;
3709 sorted_vertex_reorder_idx[j] = j;
3710 }
3711 // add field data
3714 temp_vertex_field_data, vertices, sizeof(*vertices),
3715 num_total_vertices, new_num_total_vertices);
3717 sorted_vertex_ids, new_num_total_vertices, sorted_vertex_reorder_idx);
3718
3719 dist_grid->vertex_coordinates = vertex_coordinates;
3720 dist_grid->ids[YAC_LOC_CORNER] = vertex_ids;
3721 dist_grid->core_mask[YAC_LOC_CORNER] = core_vertex_mask;
3722 dist_grid->owners[YAC_LOC_CORNER] = vertex_owners;
3723 dist_grid->sorted_ids[YAC_LOC_CORNER] = sorted_vertex_ids;
3724 dist_grid->sorted_reorder_idx[YAC_LOC_CORNER] = sorted_vertex_reorder_idx;
3725 dist_grid->total_count[YAC_LOC_CORNER] = new_num_total_vertices;
3726}
3727
3729 const void * a, const void * b) {
3730
3731 return (((const struct global_edge_reorder *)a)->global_id >
3732 ((const struct global_edge_reorder *)b)->global_id) -
3733 (((const struct global_edge_reorder *)a)->global_id <
3734 ((const struct global_edge_reorder *)b)->global_id);
3735}
3736
3738 struct yac_dist_grid * dist_grid, struct global_edge_reorder * edges,
3739 size_t count, size_t * idx, struct temp_field_data temp_edge_field_data) {
3740
3741 if (count == 0) return;
3742
3743 // sort edges global ids
3744 qsort(edges, count, sizeof(*edges), compare_global_edge_reorder_global_id);
3745
3746 yac_int * sorted_edge_ids = dist_grid->sorted_ids[YAC_LOC_EDGE];
3747 size_t * sorted_edge_reorder_idx = dist_grid->sorted_reorder_idx[YAC_LOC_EDGE];
3748
3749 yac_int prev_global_id = edges[0].global_id - 1;
3750 size_t prev_idx = 0;
3751 size_t add_count = 0;
3752 size_t num_total_edges = dist_grid->total_count[YAC_LOC_EDGE];
3753
3754 // determine which edges need to be added to local data
3755 for (size_t i = 0, j = 0; i < count; ++i) {
3756
3757 yac_int curr_global_id = edges[i].global_id;
3758 size_t curr_reorder_idx = edges[i].reorder_idx;
3759
3760 // if the current global id is a duplicate
3761 if (prev_global_id == curr_global_id) {
3762 if (idx != NULL) idx[curr_reorder_idx] = prev_idx;
3764 continue;
3765 }
3766 prev_global_id = curr_global_id;
3767
3768 // check whether the current global id is already part of the local
3769 // grid data
3770 while ((j < num_total_edges) && (sorted_edge_ids[j] < curr_global_id)) ++j;
3771
3772 // if we found a match in the local data
3773 if ((j < num_total_edges) && (sorted_edge_ids[j] == curr_global_id)) {
3774
3775 if (idx != NULL) idx[curr_reorder_idx] = sorted_edge_reorder_idx[j];
3776 prev_idx = sorted_edge_reorder_idx[j];
3778
3779 // if we need to add the current edge to the local data
3780 } else {
3781
3782 if (idx != NULL) idx[curr_reorder_idx] = num_total_edges + add_count;
3783 prev_idx = num_total_edges + add_count;
3784 if (add_count != i) edges[add_count] = edges[i];
3785 ++add_count;
3786 }
3787 }
3788
3789 size_t new_num_total_edges = num_total_edges + add_count;
3790 yac_int * edge_ids =
3791 xrealloc(dist_grid->ids[YAC_LOC_EDGE],
3792 new_num_total_edges * sizeof(*edge_ids));
3793 enum yac_edge_type * edge_type =
3794 xrealloc(dist_grid->edge_type,
3795 new_num_total_edges * sizeof(*edge_type));
3797 xrealloc(dist_grid->edge_to_vertex,
3798 new_num_total_edges * sizeof(*edge_to_vertex));
3799 struct remote_point_infos * edge_owners =
3800 xrealloc(dist_grid->owners[YAC_LOC_EDGE],
3801 new_num_total_edges * sizeof(*edge_owners));
3802 int * core_edge_mask =
3803 xrealloc(dist_grid->core_mask[YAC_LOC_EDGE], new_num_total_edges *
3804 sizeof(*core_edge_mask));
3805 sorted_edge_ids =
3806 xrealloc(
3807 sorted_edge_ids, new_num_total_edges * sizeof(*sorted_edge_ids));
3808 sorted_edge_reorder_idx =
3809 xrealloc(
3810 sorted_edge_reorder_idx, new_num_total_edges *
3811 sizeof(*sorted_edge_reorder_idx));
3812
3813 yac_int * vertex_ids = xmalloc(2 * add_count * sizeof(*vertex_ids));
3814 size_t * reorder = xmalloc(2 * add_count * sizeof(*reorder));
3815
3816 // add the selected edges to the local grid data
3817 for (size_t i = 0, j = num_total_edges; i < add_count; ++i, ++j) {
3818
3819 edge_ids[j] = edges[i].global_id;
3820 edge_type[j] = edges[i].edge_type;
3821 core_edge_mask[j] = 0;
3822 edge_owners[j] = edges[i].owners;
3823 sorted_edge_ids[j] = edges[i].global_id;
3824 sorted_edge_reorder_idx[j] = j;
3825
3826 vertex_ids[2 * i + 0] = edges[i].edge_to_vertex[0];
3827 vertex_ids[2 * i + 1] = edges[i].edge_to_vertex[1];
3828 reorder[2 * i + 0] = 2 * num_total_edges + 2 * i + 0;
3829 reorder[2 * i + 1] = 2 * num_total_edges + 2 * i + 1;
3830 }
3831 // add field data
3834 temp_edge_field_data, edges, sizeof(*edges),
3835 num_total_edges, new_num_total_edges);
3837 sorted_edge_ids, new_num_total_edges, sorted_edge_reorder_idx);
3838
3839 { // determine vertex indices for edge_to_vertex
3840 yac_quicksort_index_yac_int_size_t(vertex_ids, 2 * add_count, reorder);
3841 yac_int * sorted_vertex_ids = dist_grid->sorted_ids[YAC_LOC_CORNER];
3842 size_t * sorted_vertex_reorder_idx =
3844 size_t total_num_vertices = dist_grid->total_count[YAC_LOC_CORNER];
3845 size_t * edge_to_vertex_ = (size_t*)&(edge_to_vertex[0][0]);
3846 // lookup global ids
3847 for (size_t i = 0, j = 0; i < 2 * add_count; ++i) {
3848 yac_int curr_id = vertex_ids[i];
3849 while ((j < total_num_vertices) && (sorted_vertex_ids[j] < curr_id)) ++j;
3850 YAC_ASSERT(
3851 (j < total_num_vertices) && (sorted_vertex_ids[j] == curr_id),
3852 "ERROR(yac_dist_grid_add_edges): vertex id not found")
3853 edge_to_vertex_[reorder[i]] = sorted_vertex_reorder_idx[j];
3854 }
3855 }
3856
3857 free(vertex_ids);
3858 free(reorder);
3859
3860 dist_grid->ids[YAC_LOC_EDGE] = edge_ids;
3861 dist_grid->edge_type = edge_type;
3862 dist_grid->edge_to_vertex = edge_to_vertex;
3863 dist_grid->owners[YAC_LOC_EDGE] = edge_owners;
3864 dist_grid->core_mask[YAC_LOC_EDGE] = core_edge_mask;
3865 dist_grid->sorted_ids[YAC_LOC_EDGE] = sorted_edge_ids;
3866 dist_grid->sorted_reorder_idx[YAC_LOC_EDGE] = sorted_edge_reorder_idx;
3867 dist_grid->total_count[YAC_LOC_EDGE] = new_num_total_edges;
3868}
3869
3871 struct yac_dist_grid * dist_grid, yac_int * cell_ids,
3872 int * num_vertices_per_cell, struct bounding_circle * cell_bnd_circles,
3873 size_t count, size_t * cell_to_vertex, size_t * cell_to_edge,
3874 struct remote_point_infos * cell_owners,
3875 struct temp_field_data temp_cell_field_data) {
3876
3877 if (count == 0) return;
3878
3879 size_t * reorder_idx = xmalloc(count * sizeof(reorder_idx));
3880 for (size_t i = 0; i < count; ++i) reorder_idx[i] = i;
3881
3882 size_t * prescan = xmalloc(count * sizeof(*prescan));
3883 for (size_t i = 0, accu = 0; i < count;
3884 accu += (size_t)(num_vertices_per_cell[i++])) prescan[i] = accu;
3885
3886 // sort cells global ids
3887 yac_quicksort_index_yac_int_size_t(cell_ids, count, reorder_idx);
3888
3889 yac_int * sorted_cell_ids = dist_grid->sorted_ids[YAC_LOC_CELL];
3890 size_t * sorted_cell_reorder_idx =
3891 dist_grid->sorted_reorder_idx[YAC_LOC_CELL];
3892
3893 yac_int prev_global_id = cell_ids[0] - 1;
3894 size_t cell_add_count = 0;
3895 size_t relations_add_count = 0;
3896 size_t num_total_cells = dist_grid->total_count[YAC_LOC_CELL];
3897
3898 // determine which cells need to be added to local data
3899 for (size_t i = 0, j = 0; i < count; ++i) {
3900
3901 yac_int curr_global_id = cell_ids[i];
3902 size_t curr_reorder_idx = reorder_idx[i];
3903
3904 // if the current global id is a duplicate
3905 if (prev_global_id == curr_global_id) {
3906 yac_remote_point_infos_single_free(cell_owners + curr_reorder_idx);
3907 continue;
3908 }
3909 prev_global_id = curr_global_id;
3910
3911 // check whether the current global id is already part of the local
3912 // grid data
3913 while ((j < num_total_cells) && (sorted_cell_ids[j] < curr_global_id)) ++j;
3914
3915 // if we did not find a match in the local data
3916 if ((j >= num_total_cells) || (sorted_cell_ids[j] != curr_global_id)) {
3917
3918 if (cell_add_count != i) {
3919 cell_ids[cell_add_count] = curr_global_id;
3920 reorder_idx[cell_add_count] = curr_reorder_idx;
3921 }
3922 ++cell_add_count;
3923 relations_add_count += (size_t)(num_vertices_per_cell[curr_reorder_idx]);
3924 }
3925 }
3926
3927 size_t new_num_total_cells = num_total_cells + cell_add_count;
3928 size_t num_total_relations =
3929 (num_total_cells > 0)?
3930 (dist_grid->cell_to_vertex_offsets[num_total_cells-1] +
3931 (size_t)(dist_grid->num_vertices_per_cell[num_total_cells-1])):0;
3932 size_t new_num_total_relations = num_total_relations + relations_add_count;
3933 yac_int * new_cell_ids =
3934 xrealloc(dist_grid->ids[YAC_LOC_CELL],
3935 new_num_total_cells * sizeof(*new_cell_ids));
3936 int * new_num_vertices_per_cell =
3937 xrealloc(dist_grid->num_vertices_per_cell, new_num_total_cells *
3938 sizeof(*new_num_vertices_per_cell));
3939 size_t * new_cell_to_vertex =
3940 xrealloc(dist_grid->cell_to_vertex, new_num_total_relations *
3941 sizeof(*new_cell_to_vertex));
3942 size_t * cell_to_vertex_offsets =
3943 xrealloc(dist_grid->cell_to_vertex_offsets, new_num_total_cells *
3944 sizeof(*cell_to_vertex_offsets));
3945 size_t * new_cell_to_edge =
3946 xrealloc(dist_grid->cell_to_edge, new_num_total_relations *
3947 sizeof(*new_cell_to_edge));
3948 struct bounding_circle * new_cell_bnd_circles =
3949 xrealloc(dist_grid->cell_bnd_circles, new_num_total_cells *
3950 sizeof(*new_cell_bnd_circles));
3951 int * core_cell_mask =
3952 xrealloc(dist_grid->core_mask[YAC_LOC_CELL],
3953 new_num_total_cells * sizeof(*core_cell_mask));
3954 struct remote_point_infos * new_cell_owners =
3955 xrealloc(dist_grid->owners[YAC_LOC_CELL],
3956 new_num_total_cells * sizeof(*cell_owners));
3957 sorted_cell_ids =
3958 xrealloc(
3959 sorted_cell_ids, new_num_total_cells * sizeof(*sorted_cell_ids));
3960 sorted_cell_reorder_idx =
3961 xrealloc(
3962 sorted_cell_reorder_idx, new_num_total_cells *
3963 sizeof(*sorted_cell_reorder_idx));
3964
3965 // add the selected cells to the local grid data
3966 for (size_t i = 0, j = num_total_cells; i < cell_add_count;
3967 ++i, ++j) {
3968
3969 size_t curr_reorder_idx = reorder_idx[i];
3970 int curr_num_vertices = num_vertices_per_cell[curr_reorder_idx];
3971 size_t curr_relation_idx = prescan[curr_reorder_idx];
3972
3973 new_cell_ids[j] = cell_ids[i];
3974 new_num_vertices_per_cell[j] = curr_num_vertices;
3975 cell_to_vertex_offsets[j] = num_total_relations;
3976 for (int j = 0; j < curr_num_vertices;
3977 ++j, ++num_total_relations, ++curr_relation_idx) {
3978 new_cell_to_vertex[num_total_relations] =
3979 cell_to_vertex[curr_relation_idx];
3980 new_cell_to_edge[num_total_relations] = cell_to_edge[curr_relation_idx];
3981 }
3982 core_cell_mask[j] = 0;
3983 sorted_cell_ids[j] = cell_ids[i];
3984 sorted_cell_reorder_idx[j] = j;
3985 new_cell_bnd_circles[j] = cell_bnd_circles[curr_reorder_idx];
3986 new_cell_owners[j] = cell_owners[curr_reorder_idx];
3987 }
3988 // add field data
3991 temp_cell_field_data, reorder_idx, sizeof(*reorder_idx),
3992 num_total_cells, new_num_total_cells);
3994 sorted_cell_ids, new_num_total_cells, sorted_cell_reorder_idx);
3995
3996 dist_grid->ids[YAC_LOC_CELL] = new_cell_ids;
3997 dist_grid->num_vertices_per_cell = new_num_vertices_per_cell;
3998 dist_grid->cell_to_vertex = new_cell_to_vertex;
3999 dist_grid->cell_to_vertex_offsets = cell_to_vertex_offsets;
4000 dist_grid->cell_to_edge = new_cell_to_edge;
4001 dist_grid->cell_to_edge_offsets = cell_to_vertex_offsets;
4002 dist_grid->core_mask[YAC_LOC_CELL] = core_cell_mask;
4003 dist_grid->owners[YAC_LOC_CELL] = new_cell_owners;
4004 dist_grid->sorted_ids[YAC_LOC_CELL] = sorted_cell_ids;
4005 dist_grid->sorted_reorder_idx[YAC_LOC_CELL] = sorted_cell_reorder_idx;
4006 dist_grid->cell_bnd_circles = new_cell_bnd_circles;
4007 dist_grid->total_count[YAC_LOC_CELL] = new_num_total_cells;
4008
4009 free(prescan);
4010 free(reorder_idx);
4011}
4012
4014 struct temp_field_data * temp_field_data, size_t size) {
4015
4016 for (size_t i = 0; i < temp_field_data->masks_count; ++i)
4019 for (size_t i = 0; i < temp_field_data->coordinates_count; ++i)
4023}
4024
4026 struct yac_field_data * field_data, size_t count) {
4027
4029 size_t masks_count = yac_field_data_get_masks_count(field_data);
4031
4037 for (size_t i = 0; i < masks_count; ++i) {
4039 xmalloc(count * sizeof(**temp_field_data.masks));
4041 }
4042
4044 xmalloc(
4047 xmalloc(
4051 for (size_t i = 0; i < coordinates_count; ++i) {
4053 xmalloc(count * sizeof(**temp_field_data.coordinates));
4055 }
4056
4057 return temp_field_data;
4058}
4059
4061
4062 for (size_t i = 0; i < temp_field_data.masks_count; ++i)
4063 free(temp_field_data.masks[i]);
4064 free(temp_field_data.masks);
4066 for (size_t i = 0; i < temp_field_data.coordinates_count; ++i)
4070}
4071
4073 struct yac_dist_grid * dist_grid, size_t count, void * buffer,
4074 int buffer_size, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt,
4075 MPI_Comm comm) {
4076
4077 yac_int * cell_ids = xmalloc(count * sizeof(*cell_ids));
4078 int * num_vertices_per_cell = xmalloc(count * sizeof(*num_vertices_per_cell));
4079 struct bounding_circle * cell_bnd_circles =
4080 xmalloc(count * sizeof(*cell_bnd_circles));
4081 struct remote_point_infos * cell_owners =
4082 xmalloc(count * sizeof(*cell_owners));
4083
4084 struct global_vertex_reorder * vertices = NULL;
4085 size_t vertices_array_size = 0;
4086 size_t total_num_vertices = 0;
4087
4088 struct global_edge_reorder * edges = NULL;
4089 size_t edges_array_size = 0;
4090
4091 struct temp_field_data temp_cell_field_data =
4094 dist_grid->field_data, YAC_LOC_CELL), count);
4095 struct temp_field_data temp_vertex_field_data =
4098 dist_grid->field_data, YAC_LOC_CORNER), 3 * count);
4099 struct temp_field_data temp_edge_field_data =
4102 dist_grid->field_data, YAC_LOC_EDGE), 3 * count);
4103
4104 for (size_t i = 0, buffer_offset = 0; i < count; ++i) {
4105
4106 int position = 0;
4107 void * curr_buffer = (char*)buffer + buffer_offset;
4108 int num_vertices;
4109
4110 // cell id
4112 MPI_Unpack(curr_buffer, buffer_size, &position, cell_ids + i, 1,
4113 yac_int_dt, comm), comm);
4114 // unpack field data
4116 curr_buffer, buffer_size, &position, i, temp_cell_field_data, comm);
4117 // num vertices
4119 MPI_Unpack(curr_buffer, buffer_size, &position, &num_vertices, 1,
4120 MPI_INT, comm), comm);
4121 // bounding circle
4123 MPI_Unpack(curr_buffer, buffer_size, &position, cell_bnd_circles + i, 1,
4124 bnd_circle_dt, comm), comm);
4125 // cell owners
4127 curr_buffer, buffer_size, &position, cell_owners + i,
4128 point_info_dt, comm);
4129
4130 num_vertices_per_cell[i] = num_vertices;
4131
4133 vertices, vertices_array_size, total_num_vertices + (size_t)num_vertices);
4135 edges, edges_array_size, total_num_vertices + (size_t)num_vertices);
4137 &temp_vertex_field_data, total_num_vertices + (size_t)num_vertices);
4139 &temp_edge_field_data, total_num_vertices + (size_t)num_vertices);
4140
4141 for (int j = 0; j < num_vertices; ++j, ++total_num_vertices) {
4143 vertices, total_num_vertices, curr_buffer, buffer_size, &position,
4144 temp_vertex_field_data, point_info_dt, comm);
4146 edges, total_num_vertices, curr_buffer, buffer_size, &position,
4147 temp_edge_field_data, point_info_dt, comm);
4148 vertices[total_num_vertices].reorder_idx = total_num_vertices;
4149 edges[total_num_vertices].reorder_idx = total_num_vertices;
4150 }
4151
4152 buffer_offset += (size_t)position;
4153 buffer_size -= position;
4154 }
4155
4156 size_t * cell_to_vertex = xmalloc(total_num_vertices * sizeof(*cell_to_vertex));
4157 size_t * cell_to_edge = xmalloc(total_num_vertices * sizeof(*cell_to_edge));
4158
4160 dist_grid, vertices, total_num_vertices, cell_to_vertex,
4161 temp_vertex_field_data);
4163 dist_grid, edges, total_num_vertices, cell_to_edge,
4164 temp_edge_field_data);
4166 dist_grid, cell_ids, num_vertices_per_cell, cell_bnd_circles, count,
4167 cell_to_vertex, cell_to_edge, cell_owners, temp_cell_field_data);
4168
4169 temp_field_data_free(temp_cell_field_data);
4170 temp_field_data_free(temp_vertex_field_data);
4171 temp_field_data_free(temp_edge_field_data);
4172 free(cell_to_edge);
4173 free(cell_to_vertex);
4174 free(vertices);
4175 free(edges);
4176 free(cell_owners);
4177 free(cell_bnd_circles);
4178 free(num_vertices_per_cell);
4179 free(cell_ids);
4180}
4181
4183 struct yac_dist_grid * dist_grid, size_t count, void * buffer,
4184 int buffer_size, MPI_Datatype point_info_dt, MPI_Comm comm) {
4185
4186 struct global_vertex_reorder * vertices = xmalloc(count * sizeof(*vertices));
4187
4188 struct temp_field_data temp_vertex_field_data =
4191 count);
4192
4193 for (size_t i = 0, buffer_offset = 0; i < count; ++i) {
4194
4195 int position = 0;
4196 void * curr_buffer = (char*)buffer + buffer_offset;
4197
4199 vertices, i, curr_buffer, buffer_size, &position,
4200 temp_vertex_field_data, point_info_dt, comm);
4201 vertices[i].reorder_idx = i;
4202
4203 buffer_offset += (size_t)position;
4204 buffer_size -= position;
4205 }
4206
4208 dist_grid, vertices, count, NULL, temp_vertex_field_data);
4209
4210 temp_field_data_free(temp_vertex_field_data);
4211
4212 free(vertices);
4213}
4214
4216 struct yac_dist_grid * dist_grid, size_t count, void * buffer,
4217 int buffer_size, MPI_Datatype point_info_dt, MPI_Comm comm) {
4218
4219 struct global_edge_reorder * edges = xmalloc(count * sizeof(*edges));
4220 struct global_vertex_reorder * vertices =
4221 xmalloc(2 * count * sizeof(*vertices));
4222
4223 struct temp_field_data temp_edge_field_data =
4226 count);
4227 struct temp_field_data temp_vertex_field_data =
4230 2 * count);
4231
4232 for (size_t i = 0, buffer_offset = 0; i < count; ++i) {
4233
4234 int position = 0;
4235 void * curr_buffer = (char*)buffer + buffer_offset;
4236
4238 edges, i, curr_buffer, buffer_size, &position,
4239 temp_edge_field_data, point_info_dt, comm);
4240 edges[i].reorder_idx = i;
4241
4242 for (size_t j = 0; j < 2; ++j)
4244 vertices, 2 * i + j, curr_buffer, buffer_size, &position,
4245 temp_vertex_field_data, point_info_dt, comm);
4246
4247 buffer_offset += (size_t)position;
4248 buffer_size -= position;
4249 }
4250
4252 dist_grid, vertices, 2 * count, NULL, temp_vertex_field_data);
4254 dist_grid, edges, count, NULL, temp_edge_field_data);
4255
4256 temp_field_data_free(temp_vertex_field_data);
4257 temp_field_data_free(temp_edge_field_data);
4258
4259 free(vertices);
4260 free(edges);
4261}
4262
4264 struct yac_dist_grid * dist_grid, enum yac_location location, size_t count,
4265 void * buffer, int buffer_size, MPI_Datatype bnd_circle_dt,
4266 MPI_Datatype point_info_dt, MPI_Comm comm) {
4267
4268 YAC_ASSERT(
4269 (location == YAC_LOC_CELL) ||
4270 (location == YAC_LOC_CORNER) ||
4271 (location == YAC_LOC_EDGE),
4272 "ERROR(unpack_grid_data): invalid location")
4273
4274 switch(location) {
4275 default:
4276 case(YAC_LOC_CELL):
4278 dist_grid, count, buffer, buffer_size, bnd_circle_dt,
4279 point_info_dt, comm);
4280 break;
4281 case(YAC_LOC_CORNER):
4283 dist_grid, count, buffer, buffer_size, point_info_dt, comm);
4284 break;
4285 case(YAC_LOC_EDGE):
4287 dist_grid, count, buffer, buffer_size, point_info_dt, comm);
4288 break;
4289 };
4290}
4291
4293 const void * a, const void * b) {
4294
4295 return ((const struct single_remote_point_reorder *)a)->data.data.rank -
4296 ((const struct single_remote_point_reorder *)b)->data.data.rank;
4297}
4298
4300 struct yac_dist_grid * dist_grid, struct single_remote_point * ids,
4301 size_t count, enum yac_location location, size_t * idx) {
4302
4303 MPI_Comm comm = dist_grid->comm;
4304 int comm_rank, comm_size;
4305 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
4306 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
4307
4308 size_t remote_count = 0;
4309
4310 for (size_t i = 0; i < count; ++i) {
4311 if (ids[i].global_id == XT_INT_MAX) idx[i] = SIZE_MAX;
4312 else if (ids[i].data.rank != comm_rank) ++remote_count;
4313 else idx[i] = ids[i].data.orig_pos;
4314 }
4315
4316 struct single_remote_point_reorder * missing_ids =
4317 xmalloc(remote_count * sizeof(*missing_ids));
4318
4319 for (size_t i = 0, j = 0; i < count; ++i) {
4320 if ((ids[i].data.rank != comm_rank) &&
4321 (ids[i].global_id != XT_INT_MAX)) {
4322 missing_ids[j].data = ids[i];
4323 missing_ids[j].reorder_idx = i;
4324 ++j;
4325 }
4326 }
4327
4328 // check whether we already have some of the missing ids locally
4330 dist_grid, location, missing_ids, &remote_count, idx);
4331
4332 // sort data by owner
4333 qsort(missing_ids, remote_count, sizeof(*missing_ids),
4335
4336 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
4338 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
4339
4340 for (size_t i = 0; i < remote_count; ++i)
4341 sendcounts[missing_ids[i].data.data.rank]++;
4342
4344 1, sendcounts, recvcounts, sdispls, rdispls, comm);
4345
4346 size_t recv_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
4347
4348 uint64_t * uint64_t_buffer =
4349 xmalloc((remote_count + recv_count) * sizeof(*uint64_t_buffer));
4350 uint64_t * orig_pos_send_buffer = uint64_t_buffer;
4351 uint64_t * orig_pos_recv_buffer = uint64_t_buffer + remote_count;
4352
4353 // pack send buffer
4354 for (size_t i = 0; i < remote_count; ++i) {
4355 int rank = missing_ids[i].data.data.rank;
4356 if (rank != comm_rank)
4357 orig_pos_send_buffer[sdispls[rank+1]++] =
4358 (uint64_t)(missing_ids[i].data.data.orig_pos);
4359 }
4360
4361 // redistribute ids
4362 yac_alltoallv_uint64_p2p(
4363 orig_pos_send_buffer, sendcounts, sdispls,
4364 orig_pos_recv_buffer, recvcounts, rdispls, comm);
4365
4366 MPI_Datatype bnd_circle_dt = yac_get_bounding_circle_mpi_datatype(comm);
4367 yac_mpi_call(MPI_Type_commit(&bnd_circle_dt), comm);
4368 MPI_Datatype point_info_dt = yac_get_remote_point_info_mpi_datatype(comm);
4369 yac_mpi_call(MPI_Type_commit(&point_info_dt), comm);
4370
4371 void * packed_send_data = NULL;
4372 int * pack_sizes = xmalloc(recv_count * sizeof(*pack_sizes));
4373
4374 // pack all requested grid data
4376 dist_grid, location, orig_pos_recv_buffer, recv_count,
4377 &packed_send_data, pack_sizes,
4378 bnd_circle_dt, point_info_dt, comm);
4379 free(uint64_t_buffer);
4380
4381 memset(sendcounts, 0, (size_t)comm_size * sizeof(*sendcounts));
4382 for (int i = 0, k = 0; i < comm_size; ++i)
4383 for (size_t j = 0; j < recvcounts[i]; ++j, ++k)
4384 sendcounts[i] += (size_t)(pack_sizes[k]);
4385
4386 free(pack_sizes);
4387
4389 1, sendcounts, recvcounts, sdispls, rdispls, comm);
4390
4391 recv_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
4392
4393 void * packed_recv_data = xmalloc(recv_count);
4394
4395 // redistribute packed grid data
4396 yac_alltoallv_packed_p2p(
4397 packed_send_data, sendcounts, sdispls+1,
4398 packed_recv_data, recvcounts, rdispls, comm);
4399
4400 // unpack requested grid data
4402 dist_grid, location, remote_count, packed_recv_data, (int)recv_count,
4403 bnd_circle_dt, point_info_dt, comm);
4404
4405 yac_mpi_call(MPI_Type_free(&point_info_dt), comm);
4406 yac_mpi_call(MPI_Type_free(&bnd_circle_dt), comm);
4407
4408 // get the local ids for the remaining missing ids
4410 dist_grid, location, missing_ids, &remote_count, idx);
4411
4412 free(missing_ids);
4413 free(packed_recv_data);
4414 free(packed_send_data);
4415 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
4416}
4417
4419 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
4420 yac_coordinate_pointer search_coords, size_t count, size_t * cells,
4421 int (*coord_in_cell)(
4422 double coord[3], struct yac_dist_grid * dist_grid, size_t cell_idx,
4423 struct grid_cell * buffer_cell)) {
4424
4425 MPI_Comm comm = grid_pair->comm;
4426 int comm_rank, comm_size;
4427 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
4428 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
4429
4430 int * ranks = xmalloc(count * sizeof(ranks));
4431
4432 // search for every point in the process tree
4434 grid_pair->proc_sphere_part, search_coords, count, ranks);
4435
4436 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
4438 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
4439 for (size_t i = 0; i < count; ++i) sendcounts[ranks[i]]++;
4440
4441 size_t local_count = sendcounts[comm_rank];
4442 sendcounts[comm_rank] = 0;
4443
4445 1, sendcounts, recvcounts, sdispls, rdispls, comm);
4446
4447 size_t remote_count = sdispls[comm_size] + sendcounts[comm_size-1];
4448 size_t request_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
4449
4450 yac_coordinate_pointer coord_buffer =
4451 xmalloc((remote_count + request_count + local_count) *
4452 sizeof(*coord_buffer));
4453 yac_coordinate_pointer coord_send_buffer = coord_buffer + 0;
4454 yac_coordinate_pointer coord_recv_buffer = coord_buffer + remote_count;
4455 yac_coordinate_pointer coord_local_buffer =
4456 coord_buffer + remote_count + request_count;
4457
4458 // pack search coordinates
4459 for (size_t i = 0, k = 0; i < count; ++i) {
4460 if (ranks[i] == comm_rank) {
4461 coord_local_buffer[k][0] = search_coords[i][0];
4462 coord_local_buffer[k][1] = search_coords[i][1];
4463 coord_local_buffer[k][2] = search_coords[i][2];
4464 ++k;
4465 } else {
4466 size_t displ = sdispls[ranks[i]+1]++;
4467 coord_send_buffer[displ][0] = search_coords[i][0];
4468 coord_send_buffer[displ][1] = search_coords[i][1];
4469 coord_send_buffer[displ][2] = search_coords[i][2];
4470 }
4471 }
4472
4473 MPI_Datatype dt_coord;
4474 yac_mpi_call(MPI_Type_contiguous(3, MPI_DOUBLE, &dt_coord), comm);
4475 yac_mpi_call(MPI_Type_commit(&dt_coord), comm);
4476
4477 // redistribute search coordinates
4479 coord_send_buffer, sendcounts, sdispls,
4480 coord_recv_buffer, recvcounts, rdispls,
4481 sizeof(*coord_send_buffer), dt_coord, comm);
4482
4483 yac_mpi_call(MPI_Type_free(&dt_coord), comm);
4484
4485 size_t * local_cells =
4486 xmalloc((request_count + local_count) * sizeof(*local_cells));
4487
4488 // do local search
4490 grid_pair, grid_name, coord_recv_buffer, request_count + local_count,
4491 local_cells, coord_in_cell);
4492
4493 struct single_remote_point * single_remote_point_buffer =
4494 xmalloc((remote_count + request_count) *
4495 sizeof(*single_remote_point_buffer));
4496 struct single_remote_point * id_send_buffer = single_remote_point_buffer;
4497 struct single_remote_point * id_recv_buffer = single_remote_point_buffer +
4498 request_count;
4499
4500 struct yac_dist_grid * dist_grid =
4501 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
4502
4503 // pack global ids of found source cells
4504 for (size_t i = 0; i < request_count; ++i) {
4505 size_t cell_idx = local_cells[i];
4506 id_send_buffer[i].data.rank = comm_rank;
4507 if (cell_idx != SIZE_MAX) {
4508 id_send_buffer[i].global_id = dist_grid->ids[YAC_LOC_CELL][cell_idx];
4509 id_send_buffer[i].data.orig_pos = (uint64_t)cell_idx;
4510 } else {
4511 id_send_buffer[i].global_id = XT_INT_MAX;
4512 id_send_buffer[i].data.orig_pos = UINT64_MAX;
4513 }
4514 }
4515
4516 MPI_Datatype single_remote_point_dt =
4518
4519 // redistribute results (global ids of found source cells)
4521 id_send_buffer, recvcounts, rdispls, id_recv_buffer, sendcounts, sdispls,
4522 sizeof(*id_send_buffer), single_remote_point_dt, comm);
4523
4524 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
4525
4526 size_t * new_local_cells =
4527 xmalloc(remote_count * sizeof(*new_local_cells));
4528
4529 // convert all remote ids to local ones, extend local dist_grid data,
4530 // if necessary
4532 dist_grid, id_recv_buffer, remote_count, YAC_LOC_CELL, new_local_cells);
4533
4534 // extract results from local and remote search
4535 for (size_t i = 0, k = 0; i < count; ++i) {
4536 if (ranks[i] == comm_rank) {
4537 cells[i] = local_cells[request_count + k];
4538 ++k;
4539 } else {
4540 size_t displ = sdispls[ranks[i]]++;
4541 cells[i] = new_local_cells[displ];
4542 }
4543 }
4544
4545 free(new_local_cells);
4546 free(single_remote_point_buffer);
4547 free(local_cells);
4548 free(coord_buffer);
4549 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
4550 free(ranks);
4551}
4552
4554 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
4555 yac_coordinate_pointer search_coords, size_t count, size_t * cells) {
4556
4558 grid_pair, grid_name, search_coords, count, cells, coord_in_cell);
4559}
4560
4562 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
4563 yac_coordinate_pointer search_coords, size_t count, size_t * cells) {
4564
4566 grid_pair, grid_name, search_coords, count, cells, coord_in_cell_gc);
4567}
4568
4570 struct yac_dist_grid * dist_grid, struct yac_interp_field field) {
4571
4572 yac_const_coordinate_pointer field_coords =
4573 yac_dist_grid_get_field_coords(dist_grid, field);
4574 yac_int const * global_ids =
4575 yac_dist_grid_get_global_ids(dist_grid, field.location);
4576 int const * mask = yac_dist_grid_get_field_mask(dist_grid, field);
4577 size_t total_count = yac_dist_grid_get_count(dist_grid, field.location);
4578
4579 if (mask == NULL)
4580 return
4582 total_count, field_coords, global_ids);
4583 else
4584 return
4586 total_count, field_coords, global_ids, mask);
4587}
4588
4590 struct yac_dist_grid * dist_grid, struct yac_interp_field field,
4591 int comm_rank, size_t n, struct single_remote_point * points) {
4592
4593 size_t total_count = yac_dist_grid_get_count(dist_grid, field.location);
4594 int const * mask = yac_dist_grid_get_field_mask(dist_grid, field);
4595 int const * core_mask =
4596 yac_dist_grid_get_core_mask(dist_grid, field.location);
4597 yac_int const * global_ids =
4598 yac_dist_grid_get_global_ids(dist_grid, field.location);
4599
4600 if (mask == NULL) {
4601
4602 for (size_t i = 0, j = 0; i < total_count; ++i) {
4603 if (core_mask[i]) {
4604 points[j].global_id = global_ids[i];
4605 points[j].data.rank = comm_rank;
4606 points[j].data.orig_pos = i;
4607 if (n == ++j) return;
4608 }
4609 }
4610
4611 } else {
4612
4613 for (size_t i = 0, j = 0; i < total_count; ++i) {
4614 if (core_mask[i] && mask[i]) {
4615 points[j].global_id = global_ids[i];
4616 points[j].data.rank = comm_rank;
4617 points[j].data.orig_pos = i;
4618 if (n == ++j) return;
4619 }
4620 }
4621 }
4622}
4623
4625 size_t n, MPI_Comm comm) {
4626
4627 struct nnn_search_result dummy;
4628 MPI_Datatype single_remote_point_dt =
4630 single_nnn_search_result_dt_,
4631 nnn_search_result_dt;
4632 int array_of_blocklengths[] = {1, 1};
4633 const MPI_Aint array_of_displacements[] =
4634 {(MPI_Aint)(intptr_t)(const void *)&(dummy.point_info) -
4635 (MPI_Aint)(intptr_t)(const void *)&dummy,
4636 (MPI_Aint)(intptr_t)(const void *)&(dummy.cos_angle) -
4637 (MPI_Aint)(intptr_t)(const void *)&dummy};
4638 const MPI_Datatype array_of_types[] = {single_remote_point_dt, MPI_DOUBLE};
4640 MPI_Type_create_struct(
4641 2, array_of_blocklengths, array_of_displacements,
4642 array_of_types, &single_nnn_search_result_dt_), comm);
4643 MPI_Datatype single_nnn_search_result_dt =
4644 yac_create_resized(single_nnn_search_result_dt_, sizeof(dummy), comm);
4646 MPI_Type_contiguous(
4647 (int)n, single_nnn_search_result_dt, &nnn_search_result_dt), comm);
4648 yac_mpi_call(MPI_Type_commit(&nnn_search_result_dt), comm);
4649 yac_mpi_call(MPI_Type_free(&single_nnn_search_result_dt), comm);
4650 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
4651 return nnn_search_result_dt;
4652}
4653
4655 void const * a, void const * b) {
4656
4657 struct nnn_search_result const * result_a =
4658 (struct nnn_search_result const *)a;
4659 struct nnn_search_result const * result_b =
4660 (struct nnn_search_result const *)b;
4661
4662 int ret = (result_a->cos_angle < result_b->cos_angle) -
4663 (result_a->cos_angle > result_b->cos_angle);
4664 if (ret) return ret;
4665 return (result_a->point_info.global_id > result_b->point_info.global_id) -
4666 (result_a->point_info.global_id < result_b->point_info.global_id);
4667}
4668
4670 struct nnn_search_result * array, size_t array_size,
4671 struct nnn_search_result * insert, size_t insert_size) {
4672
4673 if (insert_size == 0) return;
4674
4675 // sort arrays first by cos_angle and second by global id
4676 qsort(array, array_size, sizeof(*array),
4678 qsort(insert, insert_size, sizeof(*insert),
4680
4681 struct nnn_search_result temp_results[array_size];
4682 memcpy(temp_results, array, array_size * sizeof(*array));
4683
4684 for (size_t i = 0, j = 0, k = 0; k < array_size; ++k) {
4685
4686 int cmp =
4687 (j < insert_size)?
4689 &temp_results[i], insert + j):(-1);
4690
4691 if (cmp <= 0) {
4692 if (k != i) array[k] = temp_results[i];
4693 ++i;
4694 } else {
4695 array[k] = insert[j];
4696 }
4697
4698 j += cmp >= 0;
4699 }
4700}
4701
4703 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
4704 yac_coordinate_pointer search_coords, size_t count, size_t * local_ids,
4705 size_t n, struct yac_interp_field field) {
4706
4707 MPI_Comm comm = grid_pair->comm;
4708 int comm_rank, comm_size;
4709 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
4710 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
4711
4712 struct yac_dist_grid * dist_grid =
4713 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
4714
4715 uint64_t unmasked_local_count =
4717
4718 uint64_t * unmasked_local_counts =
4719 xmalloc((size_t)comm_size * sizeof(*unmasked_local_counts));
4720
4721 // exchange number of local source points and target points
4723 MPI_Allgather(
4724 &unmasked_local_count, 1, MPI_UINT64_T,
4725 unmasked_local_counts, 1, MPI_UINT64_T, comm), comm);
4726
4727 // check whether there is a rank with too few source points
4728 int flag = 0;
4729 for (int i = 0; i < comm_size; ++i)
4730 flag |= unmasked_local_counts[i] < (uint64_t)n;
4731
4732 // if ranks with insufficient number of local source points
4733 if (flag) {
4734
4735 uint64_t global_num_unmasked_count = 0;
4736 for (int i = 0; i < comm_size; ++i)
4737 global_num_unmasked_count += unmasked_local_counts[i];
4738
4739 YAC_ASSERT(
4740 (size_t)global_num_unmasked_count >= n,
4741 "ERROR(yac_dist_grid_pair_do_nnn_search): insufficient number of "
4742 "unmasked points")
4743
4744 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
4746 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
4747
4748 // get ranks of processes that have additional data or require data in
4749 // order to have enough source points to do a initial nnn search
4750 int * flag_buffer = xcalloc(2 * (size_t)comm_size, sizeof(*flag_buffer));
4751 int * send_flags = flag_buffer;
4752 int * recv_flags = flag_buffer + comm_size;
4754 grid_pair->proc_sphere_part, unmasked_local_counts, (uint64_t)n,
4755 send_flags, recv_flags, comm_rank, comm_size);
4756 for (int i = 0; i < comm_size; ++i) {
4757 sendcounts[i] = (size_t)send_flags[i];
4758 recvcounts[i] = (size_t)recv_flags[i];
4759 }
4760 free(flag_buffer);
4761
4762 size_t local_send_count = (size_t)(MIN(unmasked_local_count, n));
4763
4764 size_t raccu = 0;
4765 for (int i = 0; i < comm_size; ++i) {
4766 sdispls[i] = 0;
4767 rdispls[i] = raccu;
4768 sendcounts[i] *= local_send_count;
4769 raccu += (recvcounts[i] *= (int)(MIN(unmasked_local_counts[i], n)));
4770 }
4771
4772 size_t recv_count = recvcounts[comm_size-1] + rdispls[comm_size-1];
4773
4774 struct single_remote_point * single_remote_point_buffer =
4775 xmalloc(
4776 (local_send_count + recv_count) * sizeof(*single_remote_point_buffer));
4777 struct single_remote_point * local_send_ids = single_remote_point_buffer;
4778 struct single_remote_point * recv_ids =
4779 single_remote_point_buffer + local_send_count;
4780
4781 // get local source points that can be sent to other processes
4783 dist_grid, field, comm_rank, local_send_count, local_send_ids);
4784
4785 MPI_Datatype single_remote_point_dt =
4787
4788 // exchange source points (integrate points into local data)
4790 local_send_ids, sendcounts, sdispls, recv_ids, recvcounts, rdispls,
4791 sizeof(*local_send_ids), single_remote_point_dt, comm);
4792
4793 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
4794
4795 size_t * dummy = xmalloc(recv_count * sizeof(*dummy));
4796
4797 // convert all remote ids to local ones, extend local dist_grid data,
4798 // if necessary
4800 dist_grid, recv_ids, recv_count, field.location, dummy);
4801
4802 free(dummy);
4803 free(single_remote_point_buffer);
4804 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
4805 }
4806 free(unmasked_local_counts);
4807
4808 struct point_sphere_part_search * sphere_part =
4809 yac_dist_grid_get_field_sphere_part(dist_grid, field);
4810
4811 double * cos_angles = NULL;
4812 size_t cos_angles_array_size = 0;
4813 yac_coordinate_pointer result_coords = NULL;
4814 size_t result_coords_array_size = 0;
4815 size_t * result_points = NULL;
4816 size_t result_points_array_size = 0;
4817 size_t * num_results = xcalloc(count, sizeof(*num_results));
4818
4819 // do local search
4821 sphere_part, count, search_coords, n, &cos_angles, &cos_angles_array_size,
4822 &result_coords, &result_coords_array_size, &result_points,
4823 &result_points_array_size, num_results);
4824
4825 size_t max_num_results = 0;
4826 for (size_t i = 0; i < count; ++i)
4827 if (max_num_results < num_results[i]) max_num_results = num_results[i];
4828
4829 // extract results (only the local core points)
4830 struct nnn_search_result * results = xmalloc(n * count * sizeof(*results));
4831 yac_int const * global_ids =
4832 yac_dist_grid_get_global_ids(dist_grid, field.location);
4833
4834 struct nnn_search_result * temp_results =
4835 xmalloc(max_num_results * sizeof(*temp_results));
4836
4837 for (size_t i = 0, k = 0; i < count; ++i) {
4838
4839 struct nnn_search_result * curr_results = results + i * n;
4840 for (size_t j = 0; j < n; ++j, ++k) {
4841 size_t curr_local_id = result_points[k];
4842 curr_results[j].point_info.global_id = global_ids[curr_local_id];
4843 curr_results[j].point_info.data.rank = comm_rank;
4844 curr_results[j].point_info.data.orig_pos = (uint64_t)curr_local_id;
4845 curr_results[j].cos_angle = cos_angles[k];
4846 }
4847
4848 for (size_t j = n; j < num_results[i]; ++j, ++k) {
4849 size_t curr_local_id = result_points[k];
4850 temp_results[j-n].point_info.global_id = global_ids[curr_local_id];
4851 temp_results[j-n].point_info.data.rank = comm_rank;
4852 temp_results[j-n].point_info.data.orig_pos = (uint64_t)curr_local_id;
4853 temp_results[j-n].cos_angle = cos_angles[k];
4854 }
4855 insert_nnn_result_points(curr_results, n, temp_results, num_results[i] - n);
4856 }
4857
4858 yac_const_coordinate_pointer field_coords =
4859 yac_dist_grid_get_field_coords(dist_grid, field);
4860 int * request_ranks = NULL;
4861 size_t request_ranks_array_size = 0;
4862 size_t num_request_ranks = 0;
4863 int * num_requests = xmalloc(count * sizeof(*num_requests));
4864
4865 // for all search points
4866 for (size_t i = 0; i < count; ++i) {
4867
4868 // generate bounding circles for all search points
4869 struct bounding_circle result_bnd_circle;
4870 memcpy(result_bnd_circle.base_vector, search_coords[i],
4871 3 * sizeof(search_coords[0][0]));
4872 result_bnd_circle.inc_angle =
4874 search_coords[i],
4875 field_coords[results[(i + 1) * n - 1].point_info.data.orig_pos]);
4876
4877 ENSURE_ARRAY_SIZE(request_ranks, request_ranks_array_size,
4878 num_request_ranks + (size_t)comm_size);
4879
4880 // search for processes that might be able to contribute to the search
4881 // results
4882 int * curr_request_ranks = request_ranks + num_request_ranks;
4884 grid_pair->proc_sphere_part, result_bnd_circle,
4885 curr_request_ranks, num_requests + i);
4886
4887 // remove requests for local process
4888 int new_num_requests = 0;
4889 for (int j = 0; j < num_requests[i]; ++j) {
4890 if (curr_request_ranks[j] == comm_rank) continue;
4891 if (new_num_requests != j)
4892 curr_request_ranks[new_num_requests] = curr_request_ranks[j];
4893 ++new_num_requests;
4894 }
4895
4896 num_request_ranks += (size_t)(num_requests[i] = new_num_requests);
4897 }
4898
4899 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
4901 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
4902
4903 for (size_t i = 0; i < num_request_ranks; ++i) sendcounts[request_ranks[i]]++;
4904
4906 1, sendcounts, recvcounts, sdispls, rdispls, comm);
4907
4908 size_t recv_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
4909
4910 yac_coordinate_pointer coord_buffer =
4911 xmalloc((num_request_ranks + recv_count) * sizeof(*coord_buffer));
4912 yac_coordinate_pointer send_request_coords = coord_buffer;
4913 yac_coordinate_pointer recv_request_coords = coord_buffer + num_request_ranks;
4914
4915 // pack bounding circles
4916 for (size_t i = 0, k = 0; i < count; ++i)
4917 for (size_t j = 0; j < num_requests[i]; ++j, ++k)
4918 memcpy(send_request_coords[sdispls[request_ranks[k]+1]++],
4919 search_coords[i], 3 * sizeof(double));
4920
4921 MPI_Datatype coord_dt = yac_get_coordinate_mpi_datatype(comm);
4922
4923 // exchange requests to other processes
4925 send_request_coords, sendcounts, sdispls,
4926 recv_request_coords, recvcounts, rdispls,
4927 sizeof(*send_request_coords), coord_dt, comm);
4928
4929 yac_mpi_call(MPI_Type_free(&coord_dt), comm);
4930
4931 num_results = xrealloc(num_results, recv_count * sizeof(*num_results));
4932 memset(num_results, 0, recv_count * sizeof(*num_results));
4933
4934 // do local search for requests
4936 sphere_part, recv_count, recv_request_coords, n, &cos_angles,
4937 &cos_angles_array_size, &result_coords, &result_coords_array_size,
4938 &result_points, &result_points_array_size, num_results);
4940 free(coord_buffer);
4941
4942 for (size_t i = 0; i < recv_count; ++i)
4943 if (max_num_results < num_results[i]) max_num_results = num_results[i];
4944 temp_results =
4945 xrealloc(temp_results, max_num_results * sizeof(*temp_results));
4946
4947 // extract results (only the ones, that are local core points)
4948 struct nnn_search_result * request_results =
4949 xmalloc(n * (num_request_ranks + recv_count) * sizeof(*request_results));
4950 struct nnn_search_result * send_request_results = request_results;
4951 struct nnn_search_result * recv_request_results =
4952 request_results + n * recv_count;
4953
4954 for (size_t i = 0, k = 0; i < recv_count; ++i) {
4955
4956 struct nnn_search_result * curr_results = send_request_results + i * n;
4957 for (size_t j = 0; j < n; ++j, ++k) {
4958 size_t curr_local_id = result_points[k];
4959 curr_results[j].point_info.global_id = global_ids[curr_local_id];
4960 curr_results[j].point_info.data.rank = comm_rank;
4961 curr_results[j].point_info.data.orig_pos = (uint64_t)curr_local_id;
4962 curr_results[j].cos_angle = cos_angles[k];
4963 }
4964
4965 for (size_t j = n; j < num_results[i]; ++j, ++k) {
4966 size_t curr_local_id = result_points[k];
4967 temp_results[j-n].point_info.global_id = global_ids[curr_local_id];
4968 temp_results[j-n].point_info.data.rank = comm_rank;
4969 temp_results[j-n].point_info.data.orig_pos = (uint64_t)curr_local_id;
4970 temp_results[j-n].cos_angle = cos_angles[k];
4971 }
4972 insert_nnn_result_points(curr_results, n, temp_results, num_results[i]-n);
4973 }
4974
4975 free(cos_angles);
4976 free(result_coords);
4977 free(result_points);
4978 free(num_results);
4979
4980 MPI_Datatype nnn_search_result_dt =
4982
4983 // return results
4985 send_request_results, recvcounts, rdispls,
4986 recv_request_results, sendcounts, sdispls,
4987 n * sizeof(*send_request_results), nnn_search_result_dt, comm);
4988
4989 yac_mpi_call(MPI_Type_free(&nnn_search_result_dt), comm);
4990
4991 // unpack results of remote search and integrate them into local results
4992 for (size_t i = 0, k = 0; i < count; ++i) {
4993 struct nnn_search_result * curr_results = results + n * i;
4994 for (size_t j = 0; j < num_requests[i]; ++k, ++j) {
4995 size_t pos = (size_t)(sdispls[request_ranks[k]]++);
4996 struct nnn_search_result * curr_request_results =
4997 recv_request_results + n * pos;
4998 insert_nnn_result_points(curr_results, n, curr_request_results, n);
4999 }
5000 }
5001 free(request_ranks);
5002 free(request_results);
5003 free(num_requests);
5004 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
5005
5006 size_t remote_count = 0;
5007 for (size_t i = 0; i < n * count; ++i)
5008 if (results[i].point_info.data.rank != comm_rank) ++remote_count;
5009
5010 // gather remote points from search results
5012 xmalloc(remote_count * sizeof(*remote_points));
5013 for (size_t i = 0, k = 0; i < n * count; ++i)
5014 if (results[i].point_info.data.rank != comm_rank)
5015 remote_points[k++] = results[i].point_info;
5016
5017 // convert all remote ids to local ones, extend local dist_grid data,
5018 // if necessary
5020 dist_grid, remote_points, remote_count, field.location,
5021 local_ids + n * count - remote_count);
5022
5023 free(remote_points);
5024
5025 // gather final result
5026 for (size_t i = 0, offset = n * count - remote_count; i < n * count; ++i) {
5027 if (results[i].point_info.data.rank == comm_rank)
5028 local_ids[i] = (size_t)(results[i].point_info.data.orig_pos);
5029 else local_ids[i] = local_ids[offset++];
5030 }
5031 free(temp_results);
5032 free(results);
5033}
5034
5036 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
5037 const_bounding_circle_pointer bnd_circles, size_t count, size_t ** cells,
5038 size_t * num_results_per_bnd_circle, struct yac_interp_field field) {
5039
5040 MPI_Comm comm = grid_pair->comm;
5041 int comm_rank, comm_size;
5042 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
5043 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
5044
5045 struct yac_dist_grid * dist_grid =
5046 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
5047
5048 int * num_ranks = xcalloc(count, sizeof(*num_ranks));
5049 int * rank_buffer = NULL;
5050 size_t rank_buffer_size = 0;
5051 size_t rank_buffer_array_size = 0;
5052
5053 for (size_t i = 0; i < count; ++i) {
5054
5055 ENSURE_ARRAY_SIZE(rank_buffer, rank_buffer_array_size,
5056 rank_buffer_size + (size_t)comm_size);
5057
5058 // finds all processes whose core area overlaps with the bounding circle
5059 // of the current cell
5060 // beware: even if the core are of a process does not overlap with the
5061 // bounding circle, it may have core cells that overlap nevertheless
5063 grid_pair->proc_sphere_part, bnd_circles[i],
5064 rank_buffer + rank_buffer_size, num_ranks + i);
5065 rank_buffer_size += (size_t)(num_ranks[i]);
5066 }
5067
5068 size_t * size_t_buffer =
5069 xmalloc(4 * (size_t)comm_size * sizeof(*size_t_buffer));
5070 size_t * result_sendcounts = size_t_buffer + 0 * comm_size;
5071 size_t * result_recvcounts = size_t_buffer + 1 * comm_size;
5072 size_t * result_sdispls = size_t_buffer + 2 * comm_size;
5073 size_t * result_rdispls = size_t_buffer + 3 * comm_size;
5074
5075 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
5077 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
5078
5079 for (size_t i = 0, offset = 0; i < count; ++i) {
5080 int curr_num_ranks = num_ranks[i];
5081 int * ranks = rank_buffer + offset;
5082 offset += (size_t)curr_num_ranks;
5083 for (int j = 0; j < curr_num_ranks; ++j) sendcounts[ranks[j]]++;
5084 }
5085
5086 // local overlaps do not need to be send around
5087 size_t local_count = sendcounts[comm_rank];
5088 sendcounts[comm_rank] = 0;
5089
5091 1, sendcounts, recvcounts, sdispls, rdispls, comm);
5092
5093 size_t send_count = sdispls[comm_size] + sendcounts[comm_size-1];
5094 size_t recv_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
5095
5096 struct bounding_circle * bnd_circle_buffer =
5097 xmalloc((send_count + recv_count + local_count) *
5098 sizeof(*bnd_circle_buffer));
5099 struct bounding_circle * send_buffer = bnd_circle_buffer;
5100 struct bounding_circle * recv_buffer = bnd_circle_buffer + send_count;
5101 struct bounding_circle * local_buffer =
5102 bnd_circle_buffer + send_count + recv_count;
5103
5104 // pack bounding circles
5105 for (size_t i = 0, offset = 0, local_offset = 0; i < count; ++i) {
5106 int curr_num_ranks = num_ranks[i];
5107 int * ranks = rank_buffer + offset;
5108 offset += (size_t)curr_num_ranks;
5109 for (int j = 0; j < curr_num_ranks; ++j) {
5110 int rank = ranks[j];
5111 if (rank == comm_rank)
5112 local_buffer[local_offset++] = bnd_circles[i];
5113 else
5114 send_buffer[sdispls[rank + 1]++] = bnd_circles[i];
5115 }
5116 }
5117
5118 MPI_Datatype bnd_circle_dt = yac_get_bounding_circle_mpi_datatype(comm);
5119 yac_mpi_call(MPI_Type_commit(&bnd_circle_dt), comm);
5120
5121 // exchange bounding circles
5123 send_buffer, sendcounts, sdispls, recv_buffer, recvcounts, rdispls,
5124 sizeof(*send_buffer), bnd_circle_dt, comm);
5125
5126 yac_mpi_call(MPI_Type_free(&bnd_circle_dt), comm);
5127
5128 struct bnd_sphere_part_search * cell_sphere_part =
5129 dist_grid_pair_get_cell_sphere_part(grid_pair, grid_name);
5130
5131 size_t * local_cells = NULL;
5132 size_t * num_local_cells_per_bnd_circle =
5133 xmalloc((recv_count + local_count) *
5134 sizeof(*num_local_cells_per_bnd_circle));
5135
5136 uint64_t * uint64_t_buffer =
5137 xmalloc((send_count + recv_count + local_count) *
5138 sizeof(*uint64_t_buffer));
5139 uint64_t * num_local_cells_per_bnd_circle_uint64_t = uint64_t_buffer;
5140 uint64_t * num_remote_cells_per_bnd_circle =
5141 uint64_t_buffer + recv_count + local_count;
5142
5143 // search for received bounding circles in local data
5145 cell_sphere_part, recv_buffer, recv_count + local_count, &local_cells,
5146 num_local_cells_per_bnd_circle);
5147
5148 int const * field_mask =
5149 (field.location == YAC_LOC_CELL)?
5150 yac_dist_grid_get_field_mask(dist_grid, field):NULL;
5151
5152 struct bounding_circle * cell_bnd_circles = dist_grid->cell_bnd_circles;
5153
5154 // check field mask and actual overlap of bounding circles
5155 for (size_t i = 0, offset = 0, new_offset = 0;
5156 i < recv_count + local_count; ++i) {
5157
5158 struct bounding_circle * curr_bnd_circle = recv_buffer + i;
5159 size_t curr_num_results = num_local_cells_per_bnd_circle[i];
5160
5161 // remove cells whose bounding circle do not overlap with the current one
5162 uint64_t new_num_results = 0;
5163 for (size_t j = 0; j < curr_num_results; ++j, ++offset) {
5164 size_t local_cell_id = local_cells[offset];
5165 if (!yac_extents_overlap(curr_bnd_circle,
5166 cell_bnd_circles + local_cell_id)) continue;
5167 if ((field_mask == NULL) || (field_mask[local_cell_id])) {
5168 if (offset != new_offset) local_cells[new_offset] = local_cell_id;
5169 new_num_results++;
5170 new_offset++;
5171 }
5172 }
5173 num_local_cells_per_bnd_circle_uint64_t[i] = new_num_results;
5174 }
5175 free(num_local_cells_per_bnd_circle);
5176 free(bnd_circle_buffer);
5177
5178 // exchange number of results per bounding circle
5180 num_local_cells_per_bnd_circle_uint64_t, recvcounts, rdispls,
5181 num_remote_cells_per_bnd_circle, sendcounts, sdispls,
5182 sizeof(*num_local_cells_per_bnd_circle_uint64_t), MPI_UINT64_T, comm);
5183
5184 size_t saccu = 0, raccu = 0, soffset = 0, roffset = 0;
5185 for (int i = 0; i < comm_size; ++i) {
5186
5187 result_sdispls[i] = saccu;
5188 result_rdispls[i] = raccu;
5189
5190 size_t sendcount = recvcounts[i];
5191 size_t recvcount = sendcounts[i];
5192
5193 result_sendcounts[i] = 0;
5194 result_recvcounts[i] = 0;
5195 for (size_t j = 0; j < sendcount; ++j, ++soffset)
5196 result_sendcounts[i] +=
5197 (size_t)(num_local_cells_per_bnd_circle_uint64_t[soffset]);
5198 for (size_t j = 0; j < recvcount; ++j, ++roffset)
5199 result_recvcounts[i] +=
5200 (size_t)(num_remote_cells_per_bnd_circle[roffset]);
5201
5202 saccu += result_sendcounts[i];
5203 raccu += result_recvcounts[i];
5204 }
5205
5206 // count the number of results for bounding circles, which had a match with#
5207 // their original process
5208 size_t result_local_count = 0;
5209 for (size_t i = recv_count; i < recv_count + local_count; ++i)
5210 result_local_count += (size_t)(num_local_cells_per_bnd_circle_uint64_t[i]);
5211
5212 size_t result_send_count = (size_t)(result_sdispls[comm_size-1]) +
5213 (size_t)(result_sendcounts[comm_size-1]);
5214 size_t result_recv_count = (size_t)(result_rdispls[comm_size-1]) +
5215 (size_t)(result_recvcounts[comm_size-1]);
5216
5217 struct single_remote_point * single_remote_point_buffer =
5218 xmalloc((result_recv_count + result_send_count) *
5219 sizeof(*single_remote_point_buffer));
5220 struct single_remote_point * id_send_buffer = single_remote_point_buffer;
5221 struct single_remote_point * id_recv_buffer = single_remote_point_buffer +
5222 result_send_count;
5223
5224 yac_int * cell_ids = dist_grid->ids[YAC_LOC_CELL];
5225
5226 for (size_t i = 0; i < result_send_count; ++i) {
5227 size_t local_cell_id = local_cells[i];
5228 id_send_buffer[i].global_id = cell_ids[local_cell_id];
5229 id_send_buffer[i].data.rank = comm_rank;
5230 id_send_buffer[i].data.orig_pos = local_cell_id;
5231 }
5232
5233 MPI_Datatype single_remote_point_dt =
5235
5236 // redistribute results (global ids of found source cells)
5238 id_send_buffer, result_sendcounts, result_sdispls,
5239 id_recv_buffer, result_recvcounts, result_rdispls,
5240 sizeof(*id_send_buffer), single_remote_point_dt, comm);
5241
5242 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
5243
5244 size_t * new_local_cells =
5245 xmalloc((result_recv_count + result_local_count) *
5246 sizeof(*new_local_cells));
5247
5248 memcpy(new_local_cells + result_recv_count,
5249 local_cells + result_send_count,
5250 result_local_count * sizeof(*new_local_cells));
5251 free(local_cells);
5252
5253 // convert all remote ids to local ones, extend local dist_grid data,
5254 // if necessary
5256 dist_grid, id_recv_buffer, result_recv_count, YAC_LOC_CELL, new_local_cells);
5257
5258 free(single_remote_point_buffer);
5259
5260 size_t * reorder_idx =
5261 xmalloc((result_recv_count + result_local_count) * sizeof(*reorder_idx));
5262
5263 memset(
5264 num_results_per_bnd_circle, 0, count * sizeof(*num_results_per_bnd_circle));
5265
5266 for (size_t i = 0, offset = 0, reorder = 0, local_search_idx = recv_count,
5267 local_offset = result_recv_count; i < count; ++i) {
5268 int curr_num_ranks = num_ranks[i];
5269 int * ranks = rank_buffer + offset;
5270 offset += (size_t)curr_num_ranks;
5271 for (int j = 0; j < curr_num_ranks; ++j) {
5272 int rank = ranks[j];
5273 if (rank == comm_rank) {
5274 uint64_t curr_num_results =
5275 num_local_cells_per_bnd_circle_uint64_t[local_search_idx++];
5276 num_results_per_bnd_circle[i] += (size_t)curr_num_results;
5277 for (uint64_t k = 0; k < curr_num_results; ++k, ++reorder)
5278 reorder_idx[local_offset++] = reorder;
5279 } else {
5280 size_t rank_pos = sdispls[rank]++;
5281 uint64_t curr_num_results = num_remote_cells_per_bnd_circle[rank_pos];
5282 num_results_per_bnd_circle[i] += (size_t)curr_num_results;
5283 for (uint64_t k = 0; k < curr_num_results; ++k, ++reorder)
5284 reorder_idx[result_rdispls[rank]++] = reorder;
5285 }
5286 }
5287 }
5288 free(uint64_t_buffer);
5289 free(num_ranks);
5290 free(rank_buffer);
5291 free(size_t_buffer);
5292 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
5293
5295 reorder_idx, result_recv_count + result_local_count, new_local_cells);
5296 free(reorder_idx);
5297
5298 // remove duplicated results
5299 for (size_t i = 0, offset = 0, new_offset = 0; i < count; ++i) {
5300
5301 size_t * curr_local_cells = new_local_cells + offset;
5302 size_t curr_num_results_per_bnd_circle = num_results_per_bnd_circle[i];
5303 size_t new_num_results_per_bnd_circle = 0;
5304 size_t prev_cell = SIZE_MAX;
5305 offset += curr_num_results_per_bnd_circle;
5306
5308 curr_local_cells, curr_num_results_per_bnd_circle, NULL);
5309
5310 for (size_t j = 0; j < curr_num_results_per_bnd_circle; ++j) {
5311 size_t curr_cell = curr_local_cells[j];
5312 if (curr_cell != prev_cell) {
5313 new_local_cells[new_offset++] = (prev_cell = curr_cell);
5314 ++new_num_results_per_bnd_circle;
5315 }
5316 }
5317 num_results_per_bnd_circle[i] = new_num_results_per_bnd_circle;
5318 }
5319
5320 *cells = new_local_cells;
5321}
5322
5324 struct yac_dist_grid_pair * grid_pair,
5325 char const * search_grid_name, char const * result_grid_name,
5326 size_t * search_cells, size_t count, size_t ** result_cells,
5327 size_t * num_results_per_search_cell, struct yac_interp_field result_field) {
5328
5329 struct bounding_circle * search_bnd_circles =
5330 xmalloc(count * sizeof(*search_bnd_circles));
5331
5332 struct yac_dist_grid * search_dist_grid =
5333 yac_dist_grid_pair_get_dist_grid(grid_pair, search_grid_name);
5334 struct yac_dist_grid * result_dist_grid =
5335 yac_dist_grid_pair_get_dist_grid(grid_pair, result_grid_name);
5336
5337 const_bounding_circle_pointer search_grid_cell_bnd_circles =
5338 search_dist_grid->cell_bnd_circles;
5339
5340 for (size_t i = 0; i < count; ++i)
5341 search_bnd_circles[i] = search_grid_cell_bnd_circles[search_cells[i]];
5342
5344 grid_pair, result_grid_name, search_bnd_circles, count, result_cells,
5345 num_results_per_search_cell, result_field);
5346
5347 size_t total_num_result_cells = 0;
5348
5349 // struct grid_cell search_cell, result_cell;
5350 // yac_init_grid_cell(&search_cell);
5351 // yac_init_grid_cell(&result_cell);
5352
5353 // filter out obvious mismachtes
5354 // (currently only the bounding circles are checked)
5355 for (size_t i = 0, offset = 0; i < count; ++i) {
5356
5357 size_t curr_num_results_per_bnd_circle = num_results_per_search_cell[i];
5358 size_t new_num_results_per_search_cell = 0;
5359 size_t * curr_result_cells = *result_cells + offset;
5360 offset += curr_num_results_per_bnd_circle;
5361
5362 // yac_const_basic_grid_data_get_grid_cell(
5363 // (struct yac_const_basic_grid_data *)search_dist_grid,
5364 // search_cells[i], &search_cell);
5365
5366 for (size_t j = 0; j < curr_num_results_per_bnd_circle; ++j) {
5367
5368 size_t curr_result_cell = curr_result_cells[j];
5369
5370 // yac_const_basic_grid_data_get_grid_cell(
5371 // (struct yac_const_basic_grid_data *)result_dist_grid,
5372 // curr_result_cell, &result_cell);
5373
5374 // if (yac_check_overlap_cells2(
5375 // search_cell, search_dist_grid->cell_bnd_circles[search_cells[i]],
5376 // result_cell, result_dist_grid->cell_bnd_circles[curr_result_cell])) {
5378 search_bnd_circles + i,
5379 result_dist_grid->cell_bnd_circles + curr_result_cell)) {
5380
5381 (*result_cells)[total_num_result_cells++] = curr_result_cell;
5382 ++new_num_results_per_search_cell;
5383 }
5384 }
5385
5386 num_results_per_search_cell[i] = new_num_results_per_search_cell;
5387 }
5388
5389 // yac_free_grid_cell(&result_cell);
5390 // yac_free_grid_cell(&search_cell);
5391
5392 // *result_cells =
5393 // xrealloc(*result_cells, total_num_result_cells * sizeof(**result_cells));
5394 free(search_bnd_circles);
5395}
5396
5398 struct yac_dist_grid * dist_grid, size_t edge_id) {
5399
5400 struct bounding_circle bnd_circle;
5401
5402 size_t * edge_to_vertex = &(dist_grid->edge_to_vertex[edge_id][0]);
5403 double * vertices[2] =
5404 {&(dist_grid->vertex_coordinates[edge_to_vertex[0]][0]),
5405 &(dist_grid->vertex_coordinates[edge_to_vertex[1]][0])};
5406
5407 bnd_circle.base_vector[0] = vertices[0][0] + vertices[1][0];
5408 bnd_circle.base_vector[1] = vertices[0][1] + vertices[1][1];
5409 bnd_circle.base_vector[2] = vertices[0][2] + vertices[1][2];
5410 normalise_vector(bnd_circle.base_vector);
5411 bnd_circle.inc_angle =
5412 half_angle(get_vector_angle_2(vertices[0], vertices[1]));
5413 bnd_circle.sq_crd = DBL_MAX;
5414
5415 return bnd_circle;
5416}
5417
5419 struct yac_dist_grid * dist_grid,
5420 struct proc_sphere_part_node * proc_sphere_part,
5421 size_t * cells, size_t count, size_t * neighbours) {
5422
5423 // generate edge to cell
5424 yac_size_t_2_pointer edge_to_cell =
5426 dist_grid->cell_to_edge, dist_grid->num_vertices_per_cell,
5427 NULL, dist_grid->total_count[YAC_LOC_CELL],
5428 dist_grid->total_count[YAC_LOC_EDGE]);
5429
5430 // get maximum number of edges per cell
5431 size_t max_num_edges_per_cell = 0;
5432 for (size_t i = 0; i < dist_grid->total_count[YAC_LOC_CELL]; ++i)
5433 if (max_num_edges_per_cell < dist_grid->num_vertices_per_cell[i])
5434 max_num_edges_per_cell = dist_grid->num_vertices_per_cell[i];
5435
5436 yac_size_t_2_pointer edge_vertices =
5437 xmalloc(max_num_edges_per_cell * sizeof(*edge_vertices));
5438
5439 size_t neigh_idx = 0;
5440
5442 size_t missing_edge_neighbour_array_size = 0;
5443 size_t num_missing_neighbours = 0;
5444
5445 // for each cell
5446 for (size_t i = 0; i < count; ++i) {
5447
5448 size_t curr_cell = cells[i];
5449
5450 // get all edges
5451 size_t curr_num_edges = dist_grid->num_vertices_per_cell[curr_cell];
5452 size_t const * cell_edges =
5453 dist_grid->cell_to_edge + dist_grid->cell_to_edge_offsets[curr_cell];
5454 for (size_t j = 0; j < curr_num_edges; ++j) {
5455 size_t const * curr_edge_to_vertex =
5456 dist_grid->edge_to_vertex[cell_edges[j]];
5457 edge_vertices[j][0] = curr_edge_to_vertex[0];
5458 edge_vertices[j][1] = curr_edge_to_vertex[1];
5459 }
5460
5462 missing_edge_neighbour, missing_edge_neighbour_array_size,
5463 num_missing_neighbours + curr_num_edges);
5464
5465 // get the neighbour cells by following the edges and vertices around
5466 // the cell
5467 size_t prev_vertex = edge_vertices[0][0];
5468 for (size_t j = 0, edge_idx = 0; j < curr_num_edges; ++j, ++neigh_idx) {
5469
5470 // get the neighbour cell associated with the current edge
5471 size_t curr_edge = cell_edges[edge_idx];
5472 size_t * curr_edge_cells = edge_to_cell[curr_edge];
5473 size_t other_cell = curr_edge_cells[curr_edge_cells[0] == curr_cell];
5474 neighbours[neigh_idx] = other_cell;
5475
5476 if (other_cell == SIZE_MAX) {
5477 struct missing_edge_neighbour * curr_miss_neigh =
5478 missing_edge_neighbour + num_missing_neighbours++;
5479 curr_miss_neigh->edge.local_id = curr_edge;
5480 curr_miss_neigh->edge.global_id =
5481 dist_grid->ids[YAC_LOC_EDGE][curr_edge];
5482 curr_miss_neigh->cell.local_id = curr_cell;
5483 curr_miss_neigh->cell.global_id =
5484 dist_grid->ids[YAC_LOC_CELL][curr_cell];
5485 curr_miss_neigh->neigh_idx = neigh_idx;
5486 }
5487
5488 // get an edge that shares a vertex with the current edge
5489 size_t new_edge_idx = SIZE_MAX;
5490 for (size_t k = 0; k < curr_num_edges; ++k) {
5491 if (k == edge_idx) continue;
5492 else if (edge_vertices[k][0] == prev_vertex) {
5493 new_edge_idx = k;
5494 prev_vertex = edge_vertices[k][1];
5495 break;
5496 } else if (edge_vertices[k][1] == prev_vertex) {
5497 new_edge_idx = k;
5498 prev_vertex = edge_vertices[k][0];
5499 break;
5500 }
5501 }
5502 YAC_ASSERT(
5503 new_edge_idx < SIZE_MAX,
5504 "ERROR(yac_basic_grid_data_get_cell_neighbours): "
5505 "inconsistent cell_to_edge/edge_to_vertex data")
5506 edge_idx = new_edge_idx;
5507 }
5508
5509 // check whether we went once completely around the cell
5510 YAC_ASSERT(
5511 prev_vertex == edge_vertices[0][0],
5512 "ERROR(yac_basic_grid_data_get_cell_neighbours): "
5513 "inconsistent cell_to_edge/edge_to_vertex data")
5514 }
5515
5516 { // get the missing neighbours
5517 MPI_Comm comm = dist_grid->comm;
5518 int comm_rank, comm_size;
5519 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
5520 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
5521
5522 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
5524 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
5525 int * int_buffer =
5526 xmalloc(
5527 ((size_t)comm_size + num_missing_neighbours) * sizeof(*int_buffer));
5528 int * temp_ranks = int_buffer;
5529 int * num_ranks = int_buffer + comm_size;
5530 memset(num_ranks, 0, num_missing_neighbours * sizeof(*num_ranks));
5531
5532 int * rank_buffer = NULL;
5533 size_t rank_buffer_array_size = 0;
5534 size_t rank_buffer_size = 0;
5535
5536 for (size_t i = 0; i < num_missing_neighbours; ++i) {
5537
5538 // alternatively get the dist owner ranks for all cell vertices
5539 int curr_num_ranks;
5541 proc_sphere_part,
5543 temp_ranks, &curr_num_ranks);
5544
5545 ENSURE_ARRAY_SIZE(rank_buffer, rank_buffer_array_size,
5546 rank_buffer_size + (size_t)curr_num_ranks);
5547
5548 for (int j = 0; j < curr_num_ranks; ++j) {
5549 int curr_rank = temp_ranks[j];
5550 if (curr_rank != comm_rank) {
5551 sendcounts[curr_rank] += 2;
5552 num_ranks[i]++;
5553 rank_buffer[rank_buffer_size++] = curr_rank;
5554 }
5555 }
5556 }
5557
5559 1, sendcounts, recvcounts, sdispls, rdispls, comm);
5560
5561 size_t send_count =
5562 (sdispls[comm_size] + sendcounts[comm_size-1])/2;
5563 size_t recv_count =
5564 (rdispls[comm_size-1] + recvcounts[comm_size-1])/2;
5565
5566 yac_int * yac_int_buffer =
5567 xmalloc(2 * (send_count + recv_count) * sizeof(*yac_int_buffer));
5568 yac_int * send_buffer = yac_int_buffer;
5569 yac_int * recv_buffer = yac_int_buffer + 2 * send_count;
5570 size_t * result_reorder_idx =
5571 xmalloc(send_count * sizeof(*result_reorder_idx));
5572
5573 // pack send buffer
5574 for (size_t i = 0, k = 0, rank_offset = 0; i < num_missing_neighbours; ++i) {
5575
5576 int * curr_rank_buffer = rank_buffer + rank_offset;
5577 int curr_num_ranks = num_ranks[i];
5578 rank_offset += (size_t)curr_num_ranks;
5579
5580 for (int j = 0; j < curr_num_ranks; ++j, ++k) {
5581
5582 int rank = curr_rank_buffer[j];
5583
5584 if (rank == comm_rank) continue;
5585
5586 size_t pos = sdispls[rank + 1];
5587 sdispls[rank + 1] += 2;
5588
5589 send_buffer[pos + 0] = missing_edge_neighbour[i].edge.global_id;
5590 send_buffer[pos + 1] = missing_edge_neighbour[i].cell.global_id;
5591 result_reorder_idx[pos / 2] = missing_edge_neighbour[i].neigh_idx;
5592 }
5593 }
5594 free(rank_buffer);
5596
5597 // redistribute requested global ids and remote points of core points
5598 yac_alltoallv_yac_int_p2p(
5599 send_buffer, sendcounts, sdispls,
5600 recv_buffer, recvcounts, rdispls, comm);
5601
5602 yac_int * request_edge_ids =
5603 xmalloc(recv_count * sizeof(*request_edge_ids));
5604 size_t * reorder_idx = xmalloc(recv_count * sizeof(*reorder_idx));
5605 struct single_remote_point * point_info_buffer =
5606 xmalloc(
5607 (send_count + recv_count) * sizeof(*point_info_buffer));
5608 struct single_remote_point * point_send_buffer = point_info_buffer;
5609 struct single_remote_point * point_recv_buffer =
5610 point_info_buffer + recv_count;
5611 for (size_t i = 0; i < recv_count; ++i) {
5612 request_edge_ids[i] = recv_buffer[2 * i + 0];
5613 reorder_idx[i] = i;
5614 }
5615
5617 request_edge_ids, recv_count, reorder_idx);
5618 yac_int * sorted_edge_ids = dist_grid->sorted_ids[YAC_LOC_EDGE];
5619 size_t * sorted_edge_reorder_idx =
5620 dist_grid->sorted_reorder_idx[YAC_LOC_EDGE];
5621 size_t num_edges = dist_grid->total_count[YAC_LOC_EDGE];
5622 yac_int * cell_ids = dist_grid->ids[YAC_LOC_CELL];
5623
5624 // lookup the requested edge locally
5625 for (size_t i = 0, j = 0; i < recv_count; ++i) {
5626
5627 yac_int curr_edge_id = request_edge_ids[i];
5628 size_t curr_reorder_idx = reorder_idx[i];
5629
5630 while ((j < num_edges) && (sorted_edge_ids[j] < curr_edge_id)) ++j;
5631
5632 // if the edge is not available locally
5633 if ((j >= num_edges) || (sorted_edge_ids[j] != curr_edge_id)) {
5634 point_send_buffer[curr_reorder_idx] =
5635 (struct single_remote_point)
5636 {.global_id = XT_INT_MAX,
5637 .data = {.rank = comm_rank, .orig_pos = UINT64_MAX}};
5638 continue;
5639 }
5640
5641 // id of the cell that is available on the other process
5642 yac_int available_edge_cell_id = recv_buffer[2 * curr_reorder_idx + 1];
5643
5644 size_t * local_edge_cell_ids = edge_to_cell[sorted_edge_reorder_idx[j]];
5645 yac_int global_edge_cell_ids[2];
5646 for (int k = 0; k < 2; ++k)
5647 global_edge_cell_ids[k] =
5648 (local_edge_cell_ids[k] == SIZE_MAX)?
5649 XT_INT_MAX:cell_ids[local_edge_cell_ids[k]];
5650
5651 int missing_idx = global_edge_cell_ids[0] == available_edge_cell_id;
5652
5653 // consistency check
5654 YAC_ASSERT(
5655 (global_edge_cell_ids[missing_idx^1] == available_edge_cell_id) ||
5656 (global_edge_cell_ids[missing_idx^1] == XT_INT_MAX),
5657 "ERROR(yac_dist_grid_get_cell_neighbours): "
5658 "inconsistent cell edge grid data")
5659
5660 point_send_buffer[curr_reorder_idx].global_id =
5661 global_edge_cell_ids[missing_idx];
5662 point_send_buffer[curr_reorder_idx].data.rank = comm_rank;
5663 point_send_buffer[curr_reorder_idx].data.orig_pos =
5664 (local_edge_cell_ids[missing_idx] == SIZE_MAX)?
5665 (uint64_t)UINT64_MAX:local_edge_cell_ids[missing_idx];
5666 }
5667 free(reorder_idx);
5668 free(request_edge_ids);
5669 free(yac_int_buffer);
5670
5671 for (int i = 0; i < comm_size; ++i) {
5672 sdispls[i] /= 2;
5673 rdispls[i] /= 2;
5674 sendcounts[i] /= 2;
5675 recvcounts[i] /= 2;
5676 }
5677
5678 MPI_Datatype single_remote_point_dt =
5680
5682 point_send_buffer, recvcounts, rdispls,
5683 point_recv_buffer, sendcounts, sdispls,
5684 sizeof(*point_send_buffer), single_remote_point_dt, comm);
5685
5686 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
5687
5688 struct single_remote_point_reorder * results =
5689 xmalloc(send_count * sizeof(*results));
5690
5691 for (size_t i = 0; i < send_count; ++i) {
5692 results[i].data = point_recv_buffer[i];
5693 results[i].reorder_idx = result_reorder_idx[i];
5694 }
5695
5696 qsort(results, send_count, sizeof(*results),
5698
5699 // remove duplicated results
5700 size_t result_count = 0;
5701 yac_int prev_global_id = XT_INT_MAX;
5702 for (size_t i = 0, prev_reorder_idx = SIZE_MAX; i < send_count; ++i) {
5703
5704 // if the current result does not contain useful data
5705 yac_int curr_global_id = results[i].data.global_id;
5706 if (curr_global_id == XT_INT_MAX) continue;
5707
5708 size_t curr_reorder_idx = results[i].reorder_idx;
5709 if (curr_reorder_idx != prev_reorder_idx){
5710
5711 results[result_count++] = results[i];
5712 prev_reorder_idx = curr_reorder_idx;
5713 prev_global_id = curr_global_id;
5714
5715 } else {
5716
5717 YAC_ASSERT(
5718 prev_global_id == curr_global_id,
5719 "ERROR(yac_dist_grid_get_cell_neighbours): "
5720 "inconsistent cell edge data")
5721 }
5722 }
5723 for (size_t i = 0; i < result_count; ++i) {
5724 point_send_buffer[i] = results[i].data;
5725 result_reorder_idx[i] = results[i].reorder_idx;
5726 }
5727 free(results);
5728
5729 size_t * local_ids = xmalloc(result_count * sizeof(*local_ids));
5730
5732 dist_grid, point_send_buffer, result_count, YAC_LOC_CELL, local_ids);
5733
5734 for (size_t i = 0; i < result_count; ++i)
5735 neighbours[result_reorder_idx[i]] = local_ids[i];
5736
5737 free(local_ids);
5738 free(result_reorder_idx);
5739 free(point_send_buffer);
5740 free(int_buffer);
5741 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
5742 }
5743
5744 free(edge_vertices);
5745 free(edge_to_cell);
5746}
5747
5749 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
5750 size_t * cells, size_t count, size_t * neighbours) {
5751
5753 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name),
5754 grid_pair->proc_sphere_part, cells, count, neighbours);
5755}
5756
5758 struct yac_dist_grid * dist_grid, enum yac_location location,
5759 size_t * points, size_t count) {
5760
5761 struct remote_point * remote_points = xmalloc(count * sizeof(*remote_points));
5762
5763 YAC_ASSERT(
5764 (location == YAC_LOC_CELL) ||
5765 (location == YAC_LOC_CORNER) ||
5766 (location == YAC_LOC_EDGE),
5767 "ERROR(yac_dist_grid_get_remote_points): invalid location")
5768 yac_int * global_ids = dist_grid->ids[location];
5769 struct remote_point_infos * point_infos = dist_grid->owners[location];
5770
5771 for (size_t i = 0; i < count; ++i) {
5772 remote_points[i].global_id = global_ids[points[i]];
5773 remote_points[i].data = point_infos[points[i]];
5774 }
5775
5776 return remote_points;
5777}
5778
5779static inline int
5781 return (int)(value / 128) % comm_size;
5782}
5783
5784static int get_global_id_pack_size(MPI_Comm comm) {
5785
5786 int global_id_pack_size;
5787
5789 MPI_Pack_size(1, yac_int_dt, comm, &global_id_pack_size), comm);
5790
5791 return global_id_pack_size;
5792}
5793
5794static void pack_global_id(
5795 yac_int global_id, void * buffer, int buffer_size, int * position,
5796 MPI_Comm comm) {
5797
5799 MPI_Pack(&global_id, 1, yac_int_dt, buffer,
5800 buffer_size, position, comm), comm);
5801}
5802
5804 void * buffer, int buffer_size, int * position, yac_int * global_id,
5805 MPI_Comm comm) {
5806
5808 MPI_Unpack(buffer, buffer_size, position, global_id, 1,
5809 yac_int_dt, comm), comm);
5810}
5811
5813 MPI_Datatype single_remote_point_dt, MPI_Comm comm) {
5814
5815 int pack_size;
5816
5818 MPI_Pack_size(1, single_remote_point_dt, comm, &pack_size), comm);
5819
5820 return pack_size;
5821}
5822
5824 struct single_remote_point * point,
5825 void * buffer, int buffer_size, int * position,
5826 MPI_Datatype single_remote_point_dt, MPI_Comm comm) {
5827
5829 MPI_Pack(point, 1, single_remote_point_dt, buffer,
5830 buffer_size, position, comm), comm);
5831}
5832
5834 void * buffer, int buffer_size, int * position,
5835 struct single_remote_point * point, MPI_Datatype single_remote_point_dt,
5836 MPI_Comm comm) {
5837
5839 MPI_Unpack(buffer, buffer_size, position, point, 1,
5840 single_remote_point_dt, comm), comm);
5841}
5842
5844 struct yac_dist_grid * dist_grid, enum yac_location location,
5845 yac_int * global_ids, size_t count, size_t * local_ids) {
5846
5847 MPI_Comm comm = dist_grid->comm;
5848 int comm_rank, comm_size;
5849 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
5850 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
5851
5852 size_t * size_t_buffer =
5853 xmalloc((8 * (size_t)comm_size + 1) * sizeof(*size_t_buffer));
5854 size_t * sendcounts = size_t_buffer + 0 * comm_size;
5855 size_t * recvcounts = size_t_buffer + 2 * comm_size;
5856 size_t * sdispls = size_t_buffer + 4 * comm_size;
5857 size_t * rdispls = size_t_buffer + 5 * comm_size + 1;
5858 size_t * total_sendcounts = size_t_buffer + 6 * comm_size + 1;
5859 size_t * total_recvcounts = size_t_buffer + 7 * comm_size + 1;
5860 memset(sendcounts, 0, 2 * (size_t)comm_size * sizeof(*sendcounts));
5861
5862 size_t * core_points, core_count;
5863 struct yac_interp_field dummy_interp_field =
5864 {.location = location,
5865 .coordinates_idx = SIZE_MAX,
5866 .masks_idx = SIZE_MAX};
5868 dist_grid, dummy_interp_field, &core_points, &core_count);
5869 yac_int const * grid_global_ids =
5871
5872 int * rank_buffer = xmalloc((count + core_count) * sizeof(*rank_buffer));
5873 int * core_point_ranks = rank_buffer;
5874 int * global_id_ranks = rank_buffer + core_count;
5875
5876 size_t * global_id_reorder_idx =
5877 xmalloc(count * sizeof(*global_id_reorder_idx));
5878
5879 for (size_t i = 0; i < count; ++i) {
5880 int rank =
5881 (global_id_ranks[i] = compute_bucket(global_ids[i], comm_size));
5882 sendcounts[2 * rank + 0]++;
5883 global_id_reorder_idx[i] = i;
5884 }
5885
5886 yac_quicksort_index_int_size_t(global_id_ranks, count, global_id_reorder_idx);
5887
5888 for (size_t i = 0; i < core_count; ++i) {
5889 size_t point_idx = core_points[i];
5890 int rank =
5891 (core_point_ranks[i] =
5892 compute_bucket(grid_global_ids[point_idx], comm_size));
5893 sendcounts[2 * rank + 1]++;
5894 }
5895
5896 // sort core points by rank
5897 yac_quicksort_index_int_size_t(core_point_ranks, core_count, core_points);
5898
5899 // exchange number of requsted global ids, number of core points in dist_grid
5900 // and total pack size
5901 yac_mpi_call(MPI_Alltoall(sendcounts, 2, YAC_MPI_SIZE_T,
5902 recvcounts, 2, YAC_MPI_SIZE_T, comm), comm);
5903
5904 size_t recv_core_count = 0;
5905 for (int i = 0; i < comm_size; ++i)
5906 recv_core_count += recvcounts[2*i+1];
5907
5908 MPI_Datatype single_remote_point_dt =
5910 int global_id_pack_size = get_global_id_pack_size(comm);
5911 int core_point_pack_size =
5912 get_single_remote_point_pack_size(single_remote_point_dt, comm);
5913
5914 for (int i = 0; i < comm_size; ++i) {
5915 total_sendcounts[i] = sendcounts[2*i+0] * (size_t)global_id_pack_size +
5916 sendcounts[2*i+1] * (size_t)core_point_pack_size;
5917 total_recvcounts[i] = recvcounts[2*i+0] * (size_t)global_id_pack_size +
5918 recvcounts[2*i+1] * (size_t)core_point_pack_size;
5919 }
5920
5921 size_t saccu = 0, raccu = 0;
5922 sdispls[0] = 0;
5923 for (int i = 0; i < comm_size; ++i) {
5924 sdispls[i+1] = saccu;
5925 rdispls[i] = raccu;
5926 saccu += total_sendcounts[i];
5927 raccu += total_recvcounts[i];
5928 }
5929
5930 size_t send_size = sdispls[comm_size] + total_sendcounts[comm_size-1];
5931 size_t recv_size = rdispls[comm_size-1] + total_recvcounts[comm_size-1];
5932 void * pack_buffer = xmalloc(send_size + recv_size);
5933 void * send_buffer = pack_buffer;
5934 void * recv_buffer = (void*)((unsigned char *)pack_buffer + send_size);
5935
5936 // pack data
5937 for (size_t i = 0; i < count; ++i) {
5938 yac_int curr_global_id = global_ids[global_id_reorder_idx[i]];
5939 int rank = global_id_ranks[i];
5940 size_t pos = sdispls[rank + 1];
5941 int position = 0;
5943 curr_global_id, (void*)((unsigned char*)send_buffer + pos),
5944 global_id_pack_size, &position, comm);
5945 sdispls[rank + 1] += global_id_pack_size;
5946 }
5947 for (size_t i = 0; i < core_count; ++i) {
5948 size_t point_idx = core_points[i];
5949 int rank = core_point_ranks[i];
5950 size_t pos = sdispls[rank + 1];
5951 struct single_remote_point curr_core_point;
5952 curr_core_point.global_id = grid_global_ids[point_idx];
5953 curr_core_point.data.rank = comm_rank;
5954 curr_core_point.data.orig_pos = point_idx;
5955 int position = 0;
5957 &curr_core_point,
5958 (void*)((unsigned char*)send_buffer + pos),
5959 core_point_pack_size, &position, single_remote_point_dt, comm);
5960 sdispls[rank + 1] += core_point_pack_size;
5961 }
5962 free(rank_buffer);
5963 free(core_points);
5964
5965 // redistribute requested global ids and remote points of core points
5966 yac_alltoallv_packed_p2p(
5967 send_buffer, total_sendcounts, sdispls,
5968 recv_buffer, total_recvcounts, rdispls, comm);
5969
5970 size_t num_requested_ids = 0;
5971 for(int i = 0; i < comm_size; ++i)
5972 num_requested_ids += recvcounts[2*i+0];
5973
5974 yac_int * request_global_ids =
5975 xmalloc(num_requested_ids * sizeof(*request_global_ids));
5976 size_t * reorder_idx =
5977 xmalloc(num_requested_ids * sizeof(*reorder_idx));
5978 struct single_remote_point * point_info_buffer =
5979 xmalloc((recv_core_count + num_requested_ids + count) *
5980 sizeof(*point_info_buffer));
5981 struct single_remote_point * recv_core_points = point_info_buffer;
5982 struct single_remote_point * send_point_info =
5983 point_info_buffer + recv_core_count;
5984 struct single_remote_point * recv_point_info =
5985 point_info_buffer + recv_core_count + num_requested_ids;
5986
5987 // unpack data
5988 num_requested_ids = 0;
5989 recv_core_count = 0;
5990 for (int i = 0; i < comm_size; ++i) {
5991
5992 size_t curr_num_requested_ids = recvcounts[2*i+0];
5993 size_t curr_num_core_points = recvcounts[2*i+1];
5994
5995 for (size_t j = 0; j < curr_num_requested_ids; ++j, ++num_requested_ids) {
5996
5997 int position = 0;
5999 recv_buffer, global_id_pack_size, &position,
6000 request_global_ids + num_requested_ids, comm);
6001 reorder_idx[num_requested_ids] = num_requested_ids;
6002 recv_buffer = (void*)((unsigned char*)recv_buffer + global_id_pack_size);
6003 }
6004 for (size_t j = 0; j < curr_num_core_points; ++j, ++recv_core_count) {
6005
6006 int position = 0;
6008 recv_buffer, core_point_pack_size, &position,
6009 recv_core_points + recv_core_count, single_remote_point_dt, comm);
6010 recv_buffer = (void*)((unsigned char*)recv_buffer + core_point_pack_size);
6011 }
6012 }
6013 free(pack_buffer);
6014
6015 // sort the requested global ids
6017 request_global_ids, num_requested_ids, reorder_idx);
6018
6019 // sort the received core remote_points
6020 qsort(recv_core_points, recv_core_count, sizeof(*recv_core_points),
6022
6023 // match request global ids with remote_points
6024 for (size_t i = 0, j = 0; i < num_requested_ids; ++i) {
6025
6026 yac_int curr_global_id = request_global_ids[i];
6027 while ((j < recv_core_count) &&
6028 (recv_core_points[j].global_id < curr_global_id)) ++j;
6029
6031 (j < recv_core_count) &&
6032 (recv_core_points[j].global_id == curr_global_id),
6033 "ERROR(yac_dist_grid_global_to_local): "
6034 "no matching core point found for global id %zu",
6035 (size_t)curr_global_id)
6036
6037 send_point_info[reorder_idx[i]] = recv_core_points[j];
6038 }
6039 free(reorder_idx);
6040 free(request_global_ids);
6041
6042 saccu = 0, raccu = 0;
6043 for (int i = 0; i < comm_size; ++i) {
6044
6045 sdispls[i] = saccu;
6046 rdispls[i] = raccu;
6047 int recvcount = sendcounts[2*i+0];
6048 int sendcount = recvcounts[2*i+0];
6049 saccu += (sendcounts[i] = sendcount);
6050 raccu += (recvcounts[i] = recvcount);
6051 }
6052
6053 // redistribute remote_point_infos
6055 send_point_info, sendcounts, sdispls,
6056 recv_point_info, recvcounts, rdispls,
6057 sizeof(*send_point_info), single_remote_point_dt, comm);
6058
6059 free(size_t_buffer);
6060 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
6061
6063 dist_grid, recv_point_info, count, location, local_ids);
6064
6065 yac_quicksort_index_size_t_size_t(global_id_reorder_idx, count, local_ids);
6066
6067 free(global_id_reorder_idx);
6068 free(point_info_buffer);
6069}
6070
6072 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6073 size_t * vertices, size_t count, size_t ** cells,
6074 size_t * num_cells_per_vertex, struct yac_interp_field field) {
6075
6076 struct yac_dist_grid * dist_grid =
6077 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6078
6079 // generate small bounding circle for all vertices
6080 struct bounding_circle * vertex_bnd_circles =
6081 xmalloc(count * sizeof(*vertex_bnd_circles));
6082
6083 struct sin_cos_angle sin_cos_high_tol =
6084 {yac_angle_tol*100.0, cos(yac_angle_tol*100.0)};
6085
6086 for (size_t i = 0; i < count; ++i) {
6087 memcpy(vertex_bnd_circles[i].base_vector,
6088 dist_grid->vertex_coordinates[vertices[i]], 3 * sizeof(double));
6089 vertex_bnd_circles[i].inc_angle = sin_cos_high_tol;
6090 vertex_bnd_circles[i].sq_crd = DBL_MAX;
6091 }
6092
6093 // do bounding circle search
6095 grid_pair, grid_name, vertex_bnd_circles, count,
6096 cells, num_cells_per_vertex, field);
6097 free(vertex_bnd_circles);
6098
6099 // for all vertices
6100 size_t total_num_cells = 0;
6101 for (size_t i = 0, k = 0; i < count; ++i) {
6102
6103 size_t curr_vertex = vertices[i];
6104 size_t curr_num_cells_per_vertex = num_cells_per_vertex[i];
6105
6106 size_t new_num_cells_per_vertex = 0;
6107
6108 // remove all cells that do not contain the current vertex
6109 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j, ++k) {
6110
6111 size_t curr_cell = (*cells)[k];
6112 size_t * curr_cell_vertices =
6113 dist_grid->cell_to_vertex +
6114 dist_grid->cell_to_vertex_offsets[curr_cell];
6115 size_t curr_cell_size = dist_grid->num_vertices_per_cell[curr_cell];
6116
6117 size_t vertex_idx = 0;
6118 for (; vertex_idx < curr_cell_size; ++vertex_idx)
6119 if (curr_cell_vertices[vertex_idx] == curr_vertex) break;
6120
6121 // if the current cell is not linked to the current vertex
6122 if (vertex_idx == curr_cell_size) continue;
6123
6124 if (total_num_cells != k)
6125 (*cells)[total_num_cells] = curr_cell;
6126 ++new_num_cells_per_vertex;
6127 ++total_num_cells;
6128 }
6129
6130 num_cells_per_vertex[i] = new_num_cells_per_vertex;
6131 }
6132
6133 *cells = xrealloc(*cells, total_num_cells * sizeof(**cells));
6134}
6135
6158 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6159 size_t * vertices, size_t count, size_t ** cells,
6160 int * num_cells_per_vertex, struct yac_interp_field field) {
6161
6162 struct yac_dist_grid * dist_grid =
6163 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6164
6165 // get all cells connected to the provided vertices
6166 size_t * result_cells;
6167 size_t * num_result_per_vertex =
6168 xmalloc(count * sizeof(*num_result_per_vertex));
6170 grid_pair, grid_name, vertices, count,
6171 &result_cells, num_result_per_vertex, field);
6172
6173 size_t max_num_cell_per_vertex = 0;
6174 for (size_t i = 0; i < count; ++i)
6175 if (num_result_per_vertex[i] > max_num_cell_per_vertex)
6176 max_num_cell_per_vertex = num_result_per_vertex[i];
6177 size_t (*neigh_vertices)[2] =
6178 xmalloc(max_num_cell_per_vertex * sizeof(*neigh_vertices));
6179 size_t * temp_vertex_cell =
6180 xmalloc(max_num_cell_per_vertex * sizeof(*temp_vertex_cell));
6181 yac_int * global_cell_ids =
6182 xmalloc(max_num_cell_per_vertex * sizeof(*global_cell_ids));
6183
6184 // for all vertices
6185 for (size_t i = 0, offset = 0, new_offset = 0; i < count; ++i) {
6186
6187 size_t curr_vertex = vertices[i];
6188 size_t * curr_cells = result_cells + offset;
6189 size_t curr_num_cells_per_vertex = num_result_per_vertex[i];
6190
6191 // remove all cells that do not contain the current vertex
6192 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j) {
6193
6194 size_t curr_cell = curr_cells[j];
6195 size_t * curr_cell_vertices =
6196 dist_grid->cell_to_vertex + dist_grid->cell_to_vertex_offsets[curr_cell];
6197 size_t curr_cell_size = dist_grid->num_vertices_per_cell[curr_cell];
6198
6199 size_t vertex_idx = 0;
6200 for (; vertex_idx < curr_cell_size; ++vertex_idx)
6201 if (curr_cell_vertices[vertex_idx] == curr_vertex) break;
6202
6203 // get the vertex adjacent to the current vertex
6204 neigh_vertices[j][0] =
6205 curr_cell_vertices[((vertex_idx + curr_cell_size) - 1)%curr_cell_size];
6206 neigh_vertices[j][1] =
6207 curr_cell_vertices[(vertex_idx + 1)%curr_cell_size];
6208
6209 if (new_offset != offset) result_cells[new_offset + j] = curr_cell;
6210 }
6211
6212 offset += curr_num_cells_per_vertex;
6213 curr_cells = result_cells + new_offset;
6214
6215 // determine order of cell around the current vertex
6216 temp_vertex_cell[0] = curr_cells[0];
6217 size_t start_neigh_vertex = neigh_vertices[0][0];
6218 size_t prev_vertex = neigh_vertices[0][1];
6219 for (size_t j = 1, prev_cell_idx = 0; j < curr_num_cells_per_vertex; ++j) {
6220
6221 size_t k;
6222 for (k = 0; k < curr_num_cells_per_vertex; ++k) {
6223
6224 if (k == prev_cell_idx) continue;
6225
6226 int flag = neigh_vertices[k][0] == prev_vertex;
6227 if (flag || (neigh_vertices[k][1] == prev_vertex)) {
6228 temp_vertex_cell[j] = curr_cells[k];
6229 prev_cell_idx = k;
6230 prev_vertex = neigh_vertices[k][flag];
6231 break;
6232 }
6233 }
6234
6235 // if we could not find the next neighbour
6236 // (vertex is at an edge of the grid)
6237 if (k == curr_num_cells_per_vertex) {
6238 curr_num_cells_per_vertex = 0;
6239 break;
6240 }
6241 }
6242 if ((prev_vertex != start_neigh_vertex) ||
6243 (curr_num_cells_per_vertex < 3))
6244 curr_num_cells_per_vertex = 0;
6245
6246 new_offset += curr_num_cells_per_vertex;
6247 num_cells_per_vertex[i] = (int)curr_num_cells_per_vertex;
6248
6249 if (curr_num_cells_per_vertex == 0) continue;
6250
6251 // get global ids of all cells
6252 yac_int min_global_cell_id = XT_INT_MAX;
6253 size_t min_global_cell_id_idx = SIZE_MAX;
6254 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j) {
6255 yac_int curr_global_cell_id =
6256 ((global_cell_ids[j] =
6257 dist_grid->ids[YAC_LOC_CELL][temp_vertex_cell[j]]));
6258 if (curr_global_cell_id < min_global_cell_id) {
6259 min_global_cell_id = curr_global_cell_id;
6260 min_global_cell_id_idx = j;
6261 }
6262 }
6263
6264 // determine order in which to store the cells
6265 int order =
6266 (global_cell_ids[
6267 ((min_global_cell_id_idx + curr_num_cells_per_vertex) - 1)%
6268 curr_num_cells_per_vertex] >
6269 global_cell_ids[
6270 (min_global_cell_id_idx + 1)%curr_num_cells_per_vertex])?-1:1;
6271
6272 // store cells in a partition-independent order
6273 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j)
6274 curr_cells[j] =
6275 temp_vertex_cell[
6276 ((int)(min_global_cell_id_idx + curr_num_cells_per_vertex) +
6277 (int)j * order)%(int)curr_num_cells_per_vertex];
6278 }
6279
6280 *cells = result_cells;
6281 free(num_result_per_vertex);
6282 free(global_cell_ids);
6283 free(temp_vertex_cell);
6284 free(neigh_vertices);
6285}
6286
6287static inline int compare_size_t(const void * a, const void * b) {
6288
6289 size_t const * a_ = a, * b_ = b;
6290
6291 return (*a_ > *b_) - (*b_ > *a_);
6292}
6293
6295 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6296 size_t * vertices, size_t count, size_t ** neigh_vertices_,
6297 int * num_neighs_per_vertex, struct yac_interp_field field) {
6298
6299 struct yac_dist_grid * dist_grid =
6300 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6301
6302 size_t * result_cells;
6303 size_t * num_result_per_vertex =
6304 xmalloc(count * sizeof(*num_result_per_vertex));
6306 grid_pair, grid_name, vertices, count, &result_cells,
6307 num_result_per_vertex, field);
6308
6309 size_t total_num_neigh = 0;
6310 size_t max_num_neigh = 0;
6311 for (size_t i = 0; i < count; ++i) {
6312 total_num_neigh += num_result_per_vertex[i];
6313 if (num_result_per_vertex[i] > max_num_neigh)
6314 max_num_neigh = num_result_per_vertex[i];
6315 }
6316
6317 int const * vertex_mask = NULL;
6318 if (field.location == YAC_LOC_CORNER)
6319 vertex_mask = yac_dist_grid_get_field_mask(dist_grid, field);
6320
6321 size_t * neigh_vertices =
6322 xmalloc(total_num_neigh * sizeof(*neigh_vertices));
6323 size_t * temp_neigh_vertices =
6324 xmalloc(2 * max_num_neigh * sizeof(*temp_neigh_vertices));
6325 total_num_neigh = 0;
6326
6327 // for all vertices
6328 for (size_t i = 0, offset = 0; i < count; ++i) {
6329
6330 size_t curr_vertex = vertices[i];
6331 size_t * curr_cells = result_cells + offset;
6332 size_t curr_num_cells_per_vertex = num_result_per_vertex[i];
6333
6334 size_t curr_num_neigh_vertices = 0;
6335
6336 // remove all cells that do not contain the current vertex
6337 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j) {
6338
6339 size_t curr_cell = curr_cells[j];
6340 size_t * curr_cell_vertices =
6341 dist_grid->cell_to_vertex +
6342 dist_grid->cell_to_vertex_offsets[curr_cell];
6343 size_t curr_cell_size = dist_grid->num_vertices_per_cell[curr_cell];
6344
6345 size_t vertex_idx = 0;
6346 for (; vertex_idx < curr_cell_size; ++vertex_idx)
6347 if (curr_cell_vertices[vertex_idx] == curr_vertex) break;
6348
6349 // get the vertex adjacent to the current vertex
6350 size_t neigh_vertex_idx =
6351 curr_cell_vertices[((vertex_idx + curr_cell_size) - 1)%curr_cell_size];
6352 if ((vertex_mask != NULL) && (vertex_mask[neigh_vertex_idx]))
6353 temp_neigh_vertices[curr_num_neigh_vertices++] = neigh_vertex_idx;
6354 neigh_vertex_idx =
6355 curr_cell_vertices[(vertex_idx + 1)%curr_cell_size];
6356 if ((vertex_mask != NULL) && (vertex_mask[neigh_vertex_idx]))
6357 temp_neigh_vertices[curr_num_neigh_vertices++] = neigh_vertex_idx;
6358 }
6359
6360 qsort(temp_neigh_vertices, curr_num_neigh_vertices,
6361 sizeof(*temp_neigh_vertices), compare_size_t);
6363 temp_neigh_vertices, &curr_num_neigh_vertices);
6364 memcpy(neigh_vertices + total_num_neigh, temp_neigh_vertices,
6365 curr_num_neigh_vertices * sizeof(*neigh_vertices));
6366
6367 total_num_neigh += curr_num_neigh_vertices;
6368 num_neighs_per_vertex[i] = curr_num_neigh_vertices;
6369
6370 offset += curr_num_cells_per_vertex;
6371 }
6372 free(temp_neigh_vertices);
6373
6374 free(result_cells);
6375 free(num_result_per_vertex);
6376
6377 *neigh_vertices_ = neigh_vertices;
6378}
6379
6381 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6382 size_t * vertices, size_t count, size_t ** vertex_to_cell,
6383 size_t * num_cells_per_vertex) {
6384
6385 struct yac_dist_grid * dist_grid =
6386 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6387
6388 // get for each vertex all cells surrounding it
6389 struct yac_interp_field dummy_interp_field =
6391 .coordinates_idx = SIZE_MAX,
6392 .masks_idx = SIZE_MAX};
6394 grid_pair, grid_name, vertices, count, vertex_to_cell,
6395 num_cells_per_vertex, dummy_interp_field);
6396
6397 size_t max_num_cells_per_vertex = 0;
6398 for (size_t i = 0; i < count; ++i)
6399 if (num_cells_per_vertex[i] > max_num_cells_per_vertex)
6400 max_num_cells_per_vertex = num_cells_per_vertex[i];
6401
6402 yac_int * global_id_buffer =
6403 xmalloc(max_num_cells_per_vertex * sizeof(*global_id_buffer));
6404
6405 yac_int const * global_cell_ids = dist_grid->ids[YAC_LOC_CELL];
6406
6407 YAC_ASSERT(
6408 (count == 0) || (global_cell_ids != NULL),
6409 "ERROR(yac_dist_grid_pair_get_corner_cells): no global cell ids")
6410
6411 // for all vertices
6412 for (size_t i = 0, offset = 0; i < count; ++i) {
6413
6414 size_t curr_num_cells_per_vertex = num_cells_per_vertex[i];
6415 size_t * curr_vertex_to_cell = *vertex_to_cell + offset;
6416 offset += curr_num_cells_per_vertex;
6417
6418 // get global ids of all cells surrounding the current vertex
6419 for (size_t j = 0; j < curr_num_cells_per_vertex; ++j)
6420 global_id_buffer[j] = global_cell_ids[curr_vertex_to_cell[j]];
6421
6422 // sort cells by their global ids
6424 global_id_buffer, curr_num_cells_per_vertex, curr_vertex_to_cell);
6425 }
6426
6427 free(global_id_buffer);
6428}
6429
6431 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6432 size_t * cells, size_t count,
6433 size_t ** vertex_to_cell, size_t ** vertex_to_cell_offsets_,
6434 int ** num_cells_per_vertex_, struct yac_interp_field field) {
6435
6436 struct yac_dist_grid * dist_grid =
6437 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6438
6439 // determine required vertices
6440 size_t * temp_cells = xmalloc(count * sizeof(*temp_cells));
6441 int * required_vertices =
6442 xcalloc(dist_grid->total_count[YAC_LOC_CORNER], sizeof(*required_vertices));
6443 memcpy(temp_cells, cells, count * sizeof(*cells));
6444 qsort(temp_cells, count, sizeof(*temp_cells), compare_size_t);
6445 for (size_t i = 0, prev_cell = SIZE_MAX; i < count; ++i) {
6446 size_t curr_cell = temp_cells[i];
6447 if (curr_cell == SIZE_MAX) break;
6448 if (curr_cell != prev_cell) {
6449 prev_cell = curr_cell;
6450 size_t curr_num_vertices = dist_grid->num_vertices_per_cell[curr_cell];
6451 size_t const * curr_vertices =
6452 dist_grid->cell_to_vertex + dist_grid->cell_to_vertex_offsets[curr_cell];
6453 for (size_t j = 0; j < curr_num_vertices; ++j)
6454 required_vertices[curr_vertices[j]] = 1;
6455 }
6456 }
6457 free(temp_cells);
6458
6459 // generate list of all required vertices
6460 size_t num_unique_vertices = 0;
6461 for (size_t i = 0; i < dist_grid->total_count[YAC_LOC_CORNER]; ++i)
6462 if (required_vertices[i]) ++num_unique_vertices;
6463 size_t * unique_vertices =
6464 xmalloc(num_unique_vertices * sizeof(*unique_vertices));
6465 for (size_t i = 0, j = 0; i < dist_grid->total_count[YAC_LOC_CORNER]; ++i)
6466 if (required_vertices[i]) unique_vertices[j++] = i;
6467 free(required_vertices);
6468
6469 // get aux cells for all unique vertices
6470 int * num_cells_per_vertex =
6471 xcalloc(num_unique_vertices, sizeof(*num_cells_per_vertex));
6473 grid_pair, grid_name, unique_vertices, num_unique_vertices,
6474 vertex_to_cell, num_cells_per_vertex, field);
6475
6476 int * grid_num_cells_per_vertex =
6477 xcalloc(
6478 dist_grid->total_count[YAC_LOC_CORNER],
6479 sizeof(*grid_num_cells_per_vertex));
6480
6481 for (size_t i = 0; i < num_unique_vertices; ++i)
6482 grid_num_cells_per_vertex[unique_vertices[i]] =
6483 num_cells_per_vertex[i];
6484 free(num_cells_per_vertex);
6485 free(unique_vertices);
6486
6487 size_t * vertex_to_cell_offsets =
6488 xmalloc(
6489 dist_grid->total_count[YAC_LOC_CORNER] *
6490 sizeof(*vertex_to_cell_offsets));
6491 for (size_t i = 0, offset = 0; i < dist_grid->total_count[YAC_LOC_CORNER];
6492 ++i) {
6493 vertex_to_cell_offsets[i] = offset;
6494 offset += grid_num_cells_per_vertex[i];
6495 }
6496
6497 *vertex_to_cell_offsets_ = vertex_to_cell_offsets;
6498 *num_cells_per_vertex_ = grid_num_cells_per_vertex;
6499}
6500
6502 size_t ** points, size_t * reorder_idx, int * ranks, size_t count,
6503 enum yac_location location, size_t local_count, size_t recv_count,
6504 struct single_remote_point * id_send_buffer,
6505 struct single_remote_point * id_recv_buffer,
6506 size_t * sendcounts, size_t * sdispls, size_t * recvcounts, size_t * rdispls,
6507 MPI_Datatype single_remote_point_dt, MPI_Comm comm,
6508 struct yac_dist_grid * dist_grid) {
6509
6510 yac_int const * global_ids =
6511 yac_dist_grid_get_global_ids(dist_grid, location);
6512
6513 int comm_rank;
6514 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
6515
6516 size_t * old_points = *points;
6517 size_t * new_points =
6518 xmalloc((local_count + recv_count) * sizeof(*new_points));
6519
6520 for (size_t i = 0, j = 0, k = 0; i < count; ++i) {
6521 size_t idx = reorder_idx[i];
6522 size_t curr_point = old_points[idx];
6523 int curr_rank = ranks[i];
6524 if (curr_rank == comm_rank) {
6525 new_points[j++] = curr_point;
6526 } else {
6527 id_send_buffer[k].global_id = global_ids[curr_point];
6528 id_send_buffer[k].data.rank = comm_rank;
6529 id_send_buffer[k].data.orig_pos = curr_point;
6530 ++k;
6531 }
6532 }
6533
6534 // redistribute points
6536 id_send_buffer, sendcounts, sdispls,
6537 id_recv_buffer, recvcounts, rdispls,
6538 sizeof(*id_send_buffer), single_remote_point_dt, comm);
6539
6540 // convert all remote ids to local ones, extend local dist_grid data,
6541 // if necessary
6543 dist_grid, id_recv_buffer, recv_count, location,
6544 new_points + local_count);
6545
6546 *points = new_points;
6547 free(old_points);
6548}
6549
6551 double ** weights, size_t * reorder_idx, int * ranks, size_t count,
6552 size_t send_count, size_t local_count, size_t recv_count,
6553 size_t * sendcounts, size_t * sdispls, size_t * recvcounts, size_t * rdispls,
6554 MPI_Comm comm) {
6555
6556 int comm_rank;
6557 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
6558
6559 double * old_weights = *weights;
6560 double * send_buffer = xmalloc(send_count * sizeof(*send_buffer));
6561 double * recv_buffer =
6562 xmalloc((local_count + recv_count) * sizeof(*recv_buffer));
6563
6564 for (size_t i = 0, j = 0, k = 0; i < count; ++i) {
6565 size_t idx = reorder_idx[i];
6566 double curr_weight = old_weights[idx];
6567 int curr_rank = ranks[i];
6568 if (curr_rank == comm_rank) recv_buffer[j++] = curr_weight;
6569 else send_buffer[k++] = curr_weight;
6570 }
6571
6572 // redistribute points
6574 send_buffer, sendcounts, sdispls,
6575 recv_buffer + local_count, recvcounts, rdispls,
6576 sizeof(*send_buffer), MPI_DOUBLE, comm);
6577
6578 free(old_weights);
6579 *weights = recv_buffer;
6580 free(send_buffer);
6581}
6582
6584 struct yac_dist_grid * dist_grid,
6585 struct proc_sphere_part_node * proc_sphere_part,
6586 size_t * vertices, size_t count, int * ranks) {
6587
6588 size_t * reorder_idx = xmalloc(count * sizeof(*reorder_idx));
6589 for (size_t i = 0; i < count; ++i) reorder_idx[i] = i;
6590 yac_quicksort_index_size_t_size_t(vertices, count, reorder_idx);
6591
6592 size_t valid_count;
6593 for (valid_count = 0;
6594 (valid_count < count) && (vertices[valid_count] != SIZE_MAX);
6595 ++valid_count);
6596
6597 for (size_t i = valid_count; i < count; ++i) ranks[reorder_idx[i]] = 0;
6598
6599 size_t unique_count = 0;
6600 size_t prev_vertex = SIZE_MAX;
6601 for (size_t i = 0; i < valid_count; ++i) {
6602 size_t curr_vertex = vertices[i];
6603 if (curr_vertex != prev_vertex) {
6604 prev_vertex = curr_vertex;
6605 ++unique_count;
6606 }
6607 }
6608
6609 yac_coordinate_pointer grid_coords = dist_grid->vertex_coordinates;
6610 yac_coordinate_pointer search_coords =
6611 xmalloc(unique_count * sizeof(*search_coords));
6612
6613 prev_vertex = SIZE_MAX;
6614 for (size_t i = 0, j = 0; i < valid_count; ++i) {
6615 size_t curr_vertex = vertices[i];
6616 if (curr_vertex != prev_vertex) {
6617 prev_vertex = curr_vertex;
6618 memcpy(
6619 search_coords[j++], grid_coords[curr_vertex], 3 * sizeof(double));
6620 }
6621 }
6622
6623 int * temp_ranks = xmalloc(unique_count * sizeof(*temp_ranks));
6625 proc_sphere_part, search_coords, unique_count, temp_ranks);
6626
6627 prev_vertex = SIZE_MAX;
6628 for (size_t i = 0, j = 0; i < valid_count; ++i) {
6629 size_t curr_vertex = vertices[i];
6630 if (curr_vertex != prev_vertex) {
6631 prev_vertex = curr_vertex;
6632 ++j;
6633 }
6634 ranks[reorder_idx[i]] = temp_ranks[j-1];
6635 }
6636
6637 yac_quicksort_index_size_t_size_t(reorder_idx, count, vertices);
6638 free(temp_ranks);
6639 free(search_coords);
6640 free(reorder_idx);
6641}
6642
6644 struct yac_dist_grid * dist_grid,
6645 struct proc_sphere_part_node * proc_sphere_part,
6646 size_t * indices, size_t count, int * ranks,
6647 size_t (*get_ce_reference_vertex)(struct yac_dist_grid *, size_t)) {
6648
6649 size_t * reorder_idx = xmalloc(count * sizeof(*reorder_idx));
6650 for (size_t i = 0; i < count; ++i) reorder_idx[i] = i;
6651 yac_quicksort_index_size_t_size_t(indices, count, reorder_idx);
6652
6653 size_t unique_count = 0;
6654 size_t prev_index = SIZE_MAX;
6655 for (size_t i = 0; i < count; ++i) {
6656 size_t curr_index = indices[i];
6657 if (curr_index != prev_index) {
6658 prev_index = curr_index;
6659 ++unique_count;
6660 }
6661 }
6662
6663 size_t * ref_vertices = xmalloc(unique_count * sizeof(*ref_vertices));
6664 prev_index = SIZE_MAX;
6665 for (size_t i = 0, j = 0; i < count; ++i) {
6666 size_t curr_index = indices[i];
6667 if (curr_index != prev_index) {
6668 prev_index = curr_index;
6669 ref_vertices[j++] =
6670 get_ce_reference_vertex(dist_grid, curr_index);
6671 }
6672 }
6673
6674 int * temp_ranks = xmalloc(unique_count * sizeof(*temp_ranks));
6676 dist_grid, proc_sphere_part, ref_vertices, unique_count, temp_ranks);
6677 free(ref_vertices);
6678
6679 prev_index = SIZE_MAX;
6680 for (size_t i = 0, j = 0; i < count; ++i) {
6681 size_t curr_index = indices[i];
6682 if (curr_index != prev_index) {
6683 prev_index = curr_index;
6684 ++j;
6685 }
6686 ranks[reorder_idx[i]] = temp_ranks[j-1];
6687 }
6688
6689 yac_quicksort_index_size_t_size_t(reorder_idx, count, indices);
6690 free(temp_ranks);
6691 free(reorder_idx);
6692}
6693
6695 struct yac_dist_grid * dist_grid,
6696 struct proc_sphere_part_node * proc_sphere_part,
6697 size_t * cells, size_t count, int * ranks) {
6698
6700 dist_grid, proc_sphere_part, cells, count, ranks,
6702}
6703
6705 struct yac_dist_grid * dist_grid,
6706 struct proc_sphere_part_node * proc_sphere_part,
6707 size_t * edges, size_t count, int * ranks) {
6708
6710 dist_grid, proc_sphere_part, edges, count, ranks,
6712}
6713
6715 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6716 size_t * points, size_t count, enum yac_location location, int * ranks) {
6717
6718 struct yac_dist_grid * dist_grid =
6719 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6720
6721 YAC_ASSERT(
6722 (location == YAC_LOC_CELL) ||
6723 (location == YAC_LOC_CORNER) ||
6724 (location == YAC_LOC_EDGE),
6725 "ERROR(yac_dist_grid_pair_determine_dist_owner): invalid location")
6726
6727 void (*determine_dist_owner[3])(
6728 struct yac_dist_grid * dist_grid,
6729 struct proc_sphere_part_node * proc_sphere_part,
6730 size_t * cells, size_t count, int * ranks) =
6734 determine_dist_owner[location](
6735 dist_grid, grid_pair->proc_sphere_part, points, count, ranks);
6736}
6737
6739 struct yac_dist_grid_pair * grid_pair, char const * grid_name,
6740 size_t * points, size_t count, enum yac_location location, int * ranks) {
6741
6742 struct yac_dist_grid * dist_grid =
6743 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name);
6744
6745 struct remote_point_infos * orig_owners;
6746
6747 YAC_ASSERT(
6748 (location == YAC_LOC_CELL) ||
6749 (location == YAC_LOC_CORNER) ||
6750 (location == YAC_LOC_EDGE),
6751 "ERROR(yac_dist_grid_pair_determine_orig_owner): invalid location");
6752 orig_owners = dist_grid->owners[location];
6753
6754 for (size_t i = 0; i < count; ++i) {
6755
6756 struct remote_point_infos * curr_orig_owner = orig_owners + points[i];
6757
6758 int min_rank;
6759 int curr_count = curr_orig_owner->count;
6760 if (curr_count == 1) {
6761 min_rank = curr_orig_owner->data.single.rank;
6762 } else {
6763 min_rank = curr_orig_owner->data.multi[0].rank;
6764 for (int j = 1; j < curr_count; ++j) {
6765 int curr_rank = curr_orig_owner->data.multi[j].rank;
6766 if (min_rank > curr_rank) min_rank = curr_rank;
6767 }
6768 }
6769 ranks[i] = min_rank;
6770 }
6771}
6772
6774 struct yac_dist_grid_pair * grid_pair, int a_is_ref, int to_dist_owner,
6775 char const * grid_name_a, size_t ** points_a, enum yac_location location_a,
6776 char const * grid_name_b, size_t ** points_b, enum yac_location location_b,
6777 double ** weights, size_t * count) {
6778
6779 size_t count_ = *count;
6780
6781 MPI_Comm comm = grid_pair->comm;
6782 int comm_rank, comm_size;
6783 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
6784 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
6785
6786 // check whether we have to exchange weights
6787 int weight_flag_local =
6788 (count_ > 0) && (weights != NULL) && (*weights != NULL);
6789 int weight_flag;
6790 yac_mpi_call(MPI_Allreduce(&weight_flag_local, &weight_flag, 1,
6791 MPI_INT, MPI_MAX, comm), comm);
6792
6793 // if there are points defined locally for the current grid
6794 YAC_ASSERT(
6795 (count_ <= 0) || weight_flag_local || !weight_flag,
6796 "ERROR(yac_dist_grid_pair_relocate_point_pairs): weights")
6797
6798 // get the owner ranks for the reference points
6799 int * ranks = xmalloc(count_ * sizeof(ranks));
6800 size_t * reorder_idx = xmalloc(count_ * sizeof(reorder_idx));
6801 {
6802 char const * grid_name = (a_is_ref)?grid_name_a:grid_name_b;
6803 size_t * points = (a_is_ref)?*points_a:*points_b;
6804 enum yac_location location = (a_is_ref)?location_a:location_b;
6805 if (to_dist_owner)
6807 grid_pair, grid_name, points, count_, location, ranks);
6808 else
6810 grid_pair, grid_name, points, count_, location, ranks);
6811 }
6812 for (size_t i = 0; i < count_; ++i) reorder_idx[i] = i;
6813 yac_quicksort_index_int_size_t(ranks, count_, reorder_idx);
6814
6815 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
6817 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
6818 for (size_t i = 0; i < count_; ++i) sendcounts[ranks[i]]++;
6819
6820 size_t local_count = sendcounts[comm_rank];
6821 sendcounts[comm_rank] = 0;
6822
6824 1, sendcounts, recvcounts, sdispls, rdispls, comm);
6825
6826 size_t send_count = sdispls[comm_size] + sendcounts[comm_size-1];
6827 size_t recv_count = rdispls[comm_size-1] + recvcounts[comm_size-1];
6828
6829 struct single_remote_point * single_remote_point_buffer =
6830 xmalloc((send_count + recv_count) *
6831 sizeof(*single_remote_point_buffer));
6832 struct single_remote_point * id_send_buffer = single_remote_point_buffer;
6833 struct single_remote_point * id_recv_buffer = single_remote_point_buffer +
6834 send_count;
6835
6836 MPI_Datatype single_remote_point_dt =
6838
6840 points_a, reorder_idx, ranks, count_, location_a,
6841 local_count, recv_count, id_send_buffer, id_recv_buffer,
6842 sendcounts, sdispls + 1, recvcounts, rdispls,
6843 single_remote_point_dt, comm,
6844 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name_a));
6846 points_b, reorder_idx, ranks, count_, location_b,
6847 local_count, recv_count, id_send_buffer, id_recv_buffer,
6848 sendcounts, sdispls + 1, recvcounts, rdispls,
6849 single_remote_point_dt, comm,
6850 yac_dist_grid_pair_get_dist_grid(grid_pair, grid_name_b));
6851 yac_mpi_call(MPI_Type_free(&single_remote_point_dt), comm);
6852
6853 if (weight_flag)
6855 weights, reorder_idx, ranks, count_,
6856 send_count, local_count, recv_count,
6857 sendcounts, sdispls + 1, recvcounts, rdispls, comm);
6858
6859 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
6860 free(single_remote_point_buffer);
6861 free(reorder_idx);
6862 free(ranks);
6863
6864 *count = local_count + recv_count;
6865}
struct yac_field_data * yac_basic_grid_get_field_data(struct yac_basic_grid *grid, enum yac_location location)
Definition basic_grid.c:304
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:132
char const * yac_basic_grid_get_name(struct yac_basic_grid *grid)
Definition basic_grid.c:123
void yac_get_cell_bounding_circle(struct grid_cell cell, struct bounding_circle *bnd_circle)
Definition bnd_circle.c:160
int yac_extents_overlap(struct bounding_circle *extent_a, struct bounding_circle *extent_b)
Definition bnd_circle.c:204
int yac_point_in_cell2(double point_coords[3], struct grid_cell cell, struct bounding_circle bnd_circle)
#define UNUSED(x)
Definition core.h:71
static void yac_remote_point_infos_get_pack_sizes(struct remote_point_infos **infos, size_t count, int *pack_sizes, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:416
static int compare_n_ids_reorder_ids(const void *a, const void *b)
Definition dist_grid.c:991
static void generate_xmap_pack_remote_point_info(void *data, size_t count, size_t *sdispls, int *dst_pos_buffer, int *send_pos_buffer)
Definition dist_grid.c:2116
void yac_dist_grid_pair_do_point_search_gc(struct yac_dist_grid_pair *grid_pair, char const *grid_name, yac_coordinate_pointer search_coords, size_t count, size_t *cells)
Definition dist_grid.c:4561
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2957
yac_const_coordinate_pointer yac_dist_grid_get_field_coords(struct yac_dist_grid *dist_grid, struct yac_interp_field field)
Definition dist_grid.c:2895
void yac_dist_grid_determine_dist_ce_owner(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, size_t *indices, size_t count, int *ranks, size_t(*get_ce_reference_vertex)(struct yac_dist_grid *, size_t))
Definition dist_grid.c:6643
static int get_pack_size_base_cell(struct yac_field_data *cell_field_data, MPI_Datatype bnd_circle_dt, MPI_Comm comm)
Definition dist_grid.c:3155
static int compare_single_remote_point_reorder_global_id(const void *a, const void *b)
Definition dist_grid.c:2142
static void lookup_remote_points(yac_int *requested_ids, struct remote_point_infos **results, size_t *reorder_buffer, size_t request_count, struct remote_points *local_remote_data)
Definition dist_grid.c:376
static void generate_sorted_ids(yac_int *ids, size_t count, yac_int **sorted_ids, size_t **reorder_idx)
Definition dist_grid.c:1974
static void unpack_global_id(void *buffer, int buffer_size, int *position, yac_int *global_id, MPI_Comm comm)
Definition dist_grid.c:5803
size_t yac_dist_grid_get_unmasked_local_count(struct yac_dist_grid *dist_grid, struct yac_interp_field field)
Definition dist_grid.c:2911
static struct point_sphere_part_search * yac_dist_grid_get_field_sphere_part(struct yac_dist_grid *dist_grid, struct yac_interp_field field)
Definition dist_grid.c:4569
void yac_const_basic_grid_data_get_grid_cell(struct yac_const_basic_grid_data *grid_data, size_t cell_idx, struct grid_cell *buffer_cell)
Definition dist_grid.c:2996
static void pack_grid_data_vertex(struct yac_dist_grid *dist_grid, size_t idx, void *buffer, int buffer_size, int *position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3346
static void ensure_temp_field_data_sizes(struct temp_field_data *temp_field_data, size_t size)
Definition dist_grid.c:4013
void yac_remote_point_pack(struct remote_point *point, void *buffer, int buffer_size, int *position, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:536
static void yac_dist_grid_get_cell_neighbours(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, size_t *cells, size_t count, size_t *neighbours)
Definition dist_grid.c:5418
static int get_pack_size_base_edge(struct yac_field_data *edge_field_data, MPI_Comm comm)
Definition dist_grid.c:3190
static MPI_Datatype yac_get_id_reorder_coord_coord_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:1099
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:6714
void yac_dist_grid_get_local_unmasked_points(struct yac_dist_grid *dist_grid, struct yac_interp_field field, size_t **indices, size_t *count)
Definition dist_grid.c:2850
void yac_dist_grid_pair_do_point_search(struct yac_dist_grid_pair *grid_pair, char const *grid_name, yac_coordinate_pointer search_coords, size_t count, size_t *cells)
Definition dist_grid.c:4553
size_t yac_dist_grid_get_local_count(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2802
static void generate_ce_ids(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid_data *grid, int *vertex_ranks, MPI_Comm comm)
Definition dist_grid.c:1305
void yac_remote_point_unpack(void *buffer, int buffer_size, int *position, struct remote_point *point, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:548
static void insert_nnn_result_points(struct nnn_search_result *array, size_t array_size, struct nnn_search_result *insert, size_t insert_size)
Definition dist_grid.c:4669
static int yac_remote_point_infos_get_pack_size(struct remote_point_infos const *infos, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:402
static int compare_size_t(const void *a, const void *b)
Definition dist_grid.c:6287
static void temp_field_data_free(struct temp_field_data temp_field_data)
Definition dist_grid.c:4060
void yac_dist_grid_pair_get_vertex_neighbours(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *vertices, size_t count, size_t **neigh_vertices_, int *num_neighs_per_vertex, struct yac_interp_field field)
Definition dist_grid.c:6294
static struct yac_field_data * field_data_init(struct yac_field_data *orig_field_data, size_t dist_size, Xt_redist redist_mask, Xt_redist redist_coords, MPI_Comm comm)
Definition dist_grid.c:2217
static struct remote_points ** generate_dist_remote_points(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid_data *grid, MPI_Comm comm)
Definition dist_grid.c:1731
static struct yac_dist_grid generate_dist_grid(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid *grid, MPI_Comm comm)
Definition dist_grid.c:2331
static int compare_id_reorder_coord_coord(const void *a, const void *b)
Definition dist_grid.c:1129
static int coord_in_cell(double coord[3], struct yac_dist_grid *dist_grid, size_t cell_idx, struct grid_cell *buffer_cell)
Definition dist_grid.c:2972
static int compare_single_remote_point_reorder_reorder_idx(const void *a, const void *b)
Definition dist_grid.c:2151
void yac_dist_grid_determine_dist_cell_owner(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, size_t *cells, size_t count, int *ranks)
Definition dist_grid.c:6694
static void unpack_field_data(void *buffer, int buffer_size, int *position, size_t idx, struct temp_field_data temp_field_data, MPI_Comm comm)
Definition dist_grid.c:3501
static void dist_grid_pair_do_point_search_local(struct yac_dist_grid_pair *grid_pair, char const *grid_name, yac_coordinate_pointer search_coords, size_t count, size_t *cells, int(*coord_in_cell)(double coord[3], struct yac_dist_grid *dist_grid, size_t cell_idx, struct grid_cell *buffer_cell))
Definition dist_grid.c:3042
static yac_size_t_2_pointer generate_edge_to_cell(const_size_t_pointer cell_to_edge, const_int_pointer num_edges_per_cell, int *core_cell_mask, size_t num_cells, size_t num_edges)
Definition dist_grid.c:1620
static int get_pack_size_field_data(struct yac_field_data *field_data, MPI_Comm comm)
Definition dist_grid.c:3137
static struct remote_point_infos copy_remote_point_infos(struct remote_point_infos point_infos)
Definition dist_grid.c:340
static MPI_Datatype yac_get_coordinate_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:2209
static int compute_bucket(yac_int value, int comm_size)
Definition dist_grid.c:5780
static size_t yac_dist_grid_get_count(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2817
static void add_field_data(struct yac_field_data *field_data, struct temp_field_data temp_field_data, void *reorder_idx, size_t reorder_idx_size, size_t old_count, size_t new_count)
Definition dist_grid.c:3577
static int get_single_remote_point_pack_size(MPI_Datatype single_remote_point_dt, MPI_Comm comm)
Definition dist_grid.c:5812
static void get_pack_sizes_edge(struct yac_dist_grid *dist_grid, uint64_t *pos, size_t count, int *pack_sizes, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3266
static void yac_remote_point_infos_unpack(void *buffer, int buffer_size, int *position, struct remote_point_infos *infos, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:455
static void generate_xmap_set_sendcounts_remote_points(void *data, size_t count, size_t *sendcounts)
Definition dist_grid.c:2064
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:2784
static struct remote_point_infos * generate_remote_point_infos(yac_int *sorted_ids, size_t *reorder_idx, size_t count, struct remote_points *points)
Definition dist_grid.c:352
static int compare_single_remote_point_reorder_owner(const void *a, const void *b)
Definition dist_grid.c:4292
static int * determine_edge_core_mask(struct yac_dist_grid *dist_grid, int *vertex_owner_mask)
Definition dist_grid.c:211
static void insert_global_id(yac_int *ids, size_t n, yac_int id)
Definition dist_grid.c:964
static void generate_dist_grid_remote_point_infos(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, struct remote_points **dist_owner)
Definition dist_grid.c:638
static void get_vertex_cells(void *grid, size_t vertex_idx, size_t **cells, int *num_cells)
Definition dist_grid.c:1663
static int * determine_cell_core_mask(struct yac_dist_grid *dist_grid, int is_root, int *vertex_owner_mask)
Definition dist_grid.c:180
static void get_pack_sizes_vertex(struct yac_dist_grid *dist_grid, uint64_t *pos, size_t count, int *pack_sizes, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3251
static void relocate_weights(double **weights, size_t *reorder_idx, int *ranks, size_t count, size_t send_count, size_t local_count, size_t recv_count, size_t *sendcounts, size_t *sdispls, size_t *recvcounts, size_t *rdispls, MPI_Comm comm)
Definition dist_grid.c:6550
static void get_grid_cells(struct yac_basic_grid *grid, struct dist_cell *cells, MPI_Comm comm)
Definition dist_grid.c:2664
static void setup_search_data(struct yac_dist_grid_pair *dist_grid_pair)
Definition dist_grid.c:2644
static void generate_global_ids(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid_data *grid, MPI_Comm comm)
Definition dist_grid.c:1606
static struct temp_field_data temp_field_data_init(struct yac_field_data *field_data, size_t count)
Definition dist_grid.c:4025
static void get_ve_ranks(int **rank_buffer, size_t *rank_buffer_size, size_t *rank_buffer_array_size, int *num_ve_ranks, int *core_mask, size_t count, void(*get_cells)(void *ve_to_cell_data, size_t idx, size_t **cells, int *num_cells), void *ve_to_cell_data, int *num_cell_ranks, size_t *dist_cell_rank_offsets)
Definition dist_grid.c:1680
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:2714
int const * yac_dist_grid_get_field_mask(struct yac_dist_grid *dist_grid, struct yac_interp_field field)
Definition dist_grid.c:2883
static void relocate_points(size_t **points, size_t *reorder_idx, int *ranks, size_t count, enum yac_location location, size_t local_count, size_t recv_count, struct single_remote_point *id_send_buffer, struct single_remote_point *id_recv_buffer, size_t *sendcounts, size_t *sdispls, size_t *recvcounts, size_t *rdispls, MPI_Datatype single_remote_point_dt, MPI_Comm comm, struct yac_dist_grid *dist_grid)
Definition dist_grid.c:6501
static void get_pack_sizes_cell(struct yac_dist_grid *dist_grid, uint64_t *pos, size_t count, int *pack_sizes, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3208
static int compare_single_remote_point_global_id(const void *a, const void *b)
Definition dist_grid.c:295
static void yac_dist_grid_add_vertices(struct yac_dist_grid *dist_grid, struct global_vertex_reorder *vertices, size_t count, size_t *idx, struct temp_field_data temp_vertex_field_data)
Definition dist_grid.c:3621
static int get_global_id_pack_size(MPI_Comm comm)
Definition dist_grid.c:5784
void yac_remote_points_pack(struct remote_points *points, void *buffer, int buffer_size, int *position, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:592
void yac_dist_grid_determine_dist_vertex_owner(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, size_t *vertices, size_t count, int *ranks)
Definition dist_grid.c:6583
static int * generate_vertex_ids(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid_data *grid, MPI_Comm comm)
Definition dist_grid.c:1148
void yac_remote_points_unpack(void *buffer, int buffer_size, int *position, struct remote_points **points, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:611
static MPI_Datatype yac_get_n_single_remote_point_reorder_mpi_datatype(int n, MPI_Comm comm)
Definition dist_grid.c:278
static void unpack_grid_data_edge(struct global_edge_reorder *edge, size_t idx, void *buffer, int buffer_size, int *position, struct temp_field_data temp_edge_field_data, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3539
static int get_pack_size_base_vertex(struct yac_field_data *vertex_field_data, MPI_Comm comm)
Definition dist_grid.c:3175
int yac_remote_points_get_pack_size(struct remote_points *points, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:574
static void yac_dist_grid_get_n_unmasked_local_points(struct yac_dist_grid *dist_grid, struct yac_interp_field field, int comm_rank, size_t n, struct single_remote_point *points)
Definition dist_grid.c:4589
static void generate_core_masks(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, int comm_rank)
Definition dist_grid.c:228
struct yac_dist_grid_pair * yac_dist_grid_pair_new_f2c(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Fint comm)
Definition dist_grid.c:2771
static int coord_in_cell_gc(double coord[3], struct yac_dist_grid *dist_grid, size_t cell_idx, struct grid_cell *buffer_cell)
Definition dist_grid.c:2983
static void compute_basic_ve_data(size_t max_num_cell_ve, size_t num_cells, int *num_ve_per_cell, struct single_remote_point_reorder *cell_ve_point_data, yac_int **ids, size_t *num_ids, size_t **cell_to_ve, Xt_xmap *xmap, MPI_Comm comm)
Definition dist_grid.c:2160
static size_t get_cell_reference_vertex(struct yac_dist_grid *dist_grid, size_t cell_idx)
Definition dist_grid.c:156
static void yac_single_remote_point_unpack(void *buffer, int buffer_size, int *position, struct single_remote_point *point, MPI_Datatype single_remote_point_dt, MPI_Comm comm)
Definition dist_grid.c:5833
void yac_dist_grid_pair_get_cell_neighbours(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *cells, size_t count, size_t *neighbours)
Definition dist_grid.c:5748
MPI_Datatype yac_get_remote_point_info_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:322
static void yac_remote_point_infos_single_free(struct remote_point_infos *point_infos)
Definition dist_grid.c:3615
void yac_dist_grid_determine_dist_edge_owner(struct yac_dist_grid *dist_grid, struct proc_sphere_part_node *proc_sphere_part, size_t *edges, size_t count, int *ranks)
Definition dist_grid.c:6704
static void get_dist_vertex_cells(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *vertices, size_t count, size_t **cells, size_t *num_cells_per_vertex, struct yac_interp_field field)
Definition dist_grid.c:6071
struct remote_point * yac_dist_grid_get_remote_points(struct yac_dist_grid *dist_grid, enum yac_location location, size_t *points, size_t count)
Definition dist_grid.c:5757
struct yac_const_basic_grid_data * yac_dist_grid_get_basic_grid_data(struct yac_dist_grid *dist_grid)
Definition dist_grid.c:2796
void yac_dist_grid_pair_relocate_point_pairs(struct yac_dist_grid_pair *grid_pair, int a_is_ref, int to_dist_owner, char const *grid_name_a, size_t **points_a, enum yac_location location_a, char const *grid_name_b, size_t **points_b, enum yac_location location_b, double **weights, size_t *count)
Definition dist_grid.c:6773
static MPI_Datatype yac_get_id_reorder_coord_id_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:1114
static int const * yac_dist_grid_get_core_mask(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2828
static void pack_grid_data_edge(struct yac_dist_grid *dist_grid, size_t idx, void *buffer, int buffer_size, int *position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3407
static int compare_remote_point(const void *a, const void *b)
Definition dist_grid.c:957
static size_t get_edge_reference_vertex(struct yac_dist_grid *dist_grid, size_t edge_idx)
Definition dist_grid.c:199
static void insert_rank(int *ranks, int *count, int rank)
Definition dist_grid.c:975
static void yac_remote_point_infos_pack_single(struct remote_point_infos const *infos, void *buffer, int buffer_size, int *position, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:520
static void pack_field_data(size_t idx, void *buffer, int buffer_size, int *position, struct yac_field_data *field_data, MPI_Comm comm)
Definition dist_grid.c:3322
static void yac_dist_grid_add_cells(struct yac_dist_grid *dist_grid, yac_int *cell_ids, int *num_vertices_per_cell, struct bounding_circle *cell_bnd_circles, size_t count, size_t *cell_to_vertex, size_t *cell_to_edge, struct remote_point_infos *cell_owners, struct temp_field_data temp_cell_field_data)
Definition dist_grid.c:3870
void yac_dist_grid_pair_do_bnd_circle_search(struct yac_dist_grid_pair *grid_pair, char const *grid_name, const_bounding_circle_pointer bnd_circles, size_t count, size_t **cells, size_t *num_results_per_bnd_circle, struct yac_interp_field field)
Definition dist_grid.c:5035
static void get_edge_cells(void *edge_to_cell, size_t edge_idx, size_t **cells, int *num_cells)
Definition dist_grid.c:1673
void yac_dist_grid_pair_do_cell_search(struct yac_dist_grid_pair *grid_pair, char const *search_grid_name, char const *result_grid_name, size_t *search_cells, size_t count, size_t **result_cells, size_t *num_results_per_search_cell, struct yac_interp_field result_field)
Definition dist_grid.c:5323
static int compare_n_ids_reorder_reorder(const void *a, const void *b)
Definition dist_grid.c:1004
static MPI_Datatype yac_get_id_pos_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:304
static void pack_grid_data(struct yac_dist_grid *dist_grid, enum yac_location location, uint64_t *pos, size_t count, void **pack_data, int *pack_sizes, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3464
static void determine_dist_cell_ranks(struct proc_sphere_part_node *proc_sphere_part, struct yac_basic_grid_data *grid, MPI_Comm comm, int **dist_cell_ranks, int *dist_cell_rank_counts, size_t *dist_cell_rank_offsets)
Definition dist_grid.c:1016
static void yac_remote_point_infos_unpack_info_buffer(void *buffer, int buffer_size, int *position, struct remote_point_info *info_buffer, size_t *info_buffer_position, struct remote_point_infos *infos, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:482
void yac_remote_point_unpack_info_buffer(void *buffer, int buffer_size, int *position, struct remote_point_info *info_buffer, size_t *info_buffer_position, struct remote_point *point, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:560
MPI_Comm yac_dist_grid_pair_get_MPI_Comm(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2779
static void pack_global_id(yac_int global_id, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition dist_grid.c:5794
static void yac_dist_grid_pair_get_aux_grid_cells(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *vertices, size_t count, size_t **cells, int *num_cells_per_vertex, struct yac_interp_field field)
Definition dist_grid.c:6157
static int compare_global_vertex_reorder_global_id(const void *a, const void *b)
Definition dist_grid.c:3568
static yac_int const * yac_dist_grid_get_global_ids(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2839
static Xt_xmap generate_xmap_data(void *data, size_t count, MPI_Comm comm, void(*set_sendcounts)(void *, size_t, size_t *), void(*pack)(void *, size_t, size_t *, int *, int *))
Definition dist_grid.c:1989
static void pack_grid_data_cell(struct yac_dist_grid *dist_grid, size_t idx, void *buffer, int buffer_size, int *position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3423
static void unpack_grid_data_vertex(struct global_vertex_reorder *vertex, size_t idx, void *buffer, int buffer_size, int *position, struct temp_field_data temp_vertex_field_data, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3517
static void unpack_grid_data(struct yac_dist_grid *dist_grid, enum yac_location location, size_t count, void *buffer, int buffer_size, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:4263
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:5843
static void unpack_grid_data_vertices(struct yac_dist_grid *dist_grid, size_t count, void *buffer, int buffer_size, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:4182
static void yac_remote_point_infos_free(struct remote_point_infos *point_infos, size_t count)
Definition dist_grid.c:2929
static struct proc_sphere_part_node * generate_dist_grid_decomposition(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
Definition dist_grid.c:2691
static int compare_id_reorder_coord_reorder_idx(const void *a, const void *b)
Definition dist_grid.c:1136
static int compare_nnn_search_results_cos_angle(void const *a, void const *b)
Definition dist_grid.c:4654
static void yac_remote_point_infos_pack(struct remote_point_infos **infos, int *pack_sizes, size_t count, void *buffer, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:432
void yac_dist_grid_pair_determine_orig_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:6738
void yac_dist_grid_pair_get_aux_grid(struct yac_dist_grid_pair *grid_pair, char const *grid_name, size_t *cells, size_t count, size_t **vertex_to_cell, size_t **vertex_to_cell_offsets_, int **num_cells_per_vertex_, struct yac_interp_field field)
Definition dist_grid.c:6430
static MPI_Datatype yac_get_nnn_search_result_mpi_datatype(size_t n, MPI_Comm comm)
Definition dist_grid.c:4624
static void generate_xmap_pack_remote_points(void *data, size_t count, size_t *sdispls, int *dst_pos_buffer, int *send_pos_buffer)
Definition dist_grid.c:2078
static void unpack_grid_data_cells(struct yac_dist_grid *dist_grid, size_t count, void *buffer, int buffer_size, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:4072
void yac_dist_grid_pair_do_point_search_(struct yac_dist_grid_pair *grid_pair, char const *grid_name, yac_coordinate_pointer search_coords, size_t count, size_t *cells, int(*coord_in_cell)(double coord[3], struct yac_dist_grid *dist_grid, size_t cell_idx, struct grid_cell *buffer_cell))
Definition dist_grid.c:4418
static void yac_dist_grid_add_edges(struct yac_dist_grid *dist_grid, struct global_edge_reorder *edges, size_t count, size_t *idx, struct temp_field_data temp_edge_field_data)
Definition dist_grid.c:3737
static void yac_dist_grid_single_remote_point_to_local(struct yac_dist_grid *dist_grid, struct single_remote_point *ids, size_t count, enum yac_location location, size_t *idx)
Definition dist_grid.c:4299
static struct bounding_circle compute_edge_bnd_circle(struct yac_dist_grid *dist_grid, size_t edge_id)
Definition dist_grid.c:5397
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:6380
static int compare_global_edge_reorder_global_id(const void *a, const void *b)
Definition dist_grid.c:3728
static void id2idx(yac_int *ids, size_t *idx, size_t num_ids, yac_int *ref_sorted_ids, size_t num_sorted_ids)
Definition dist_grid.c:133
static Xt_xmap generate_xmap_from_remote_point_info(struct remote_point_info *point_infos, size_t count, MPI_Comm comm)
Definition dist_grid.c:2133
static Xt_xmap generate_xmap_from_remote_points(struct remote_point *remote_point_data, size_t count, MPI_Comm comm)
Definition dist_grid.c:2099
int yac_remote_point_get_pack_size(struct remote_point *point, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:507
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)
Definition dist_grid.c:4702
static void unpack_grid_data_edges(struct yac_dist_grid *dist_grid, size_t count, void *buffer, int buffer_size, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:4215
static void generate_xmap_set_sendcounts_remote_point_info(void *data, size_t count, size_t *sendcounts)
Definition dist_grid.c:2108
static struct yac_field_data * yac_dist_grid_get_field_data(struct yac_dist_grid *dist_grid, enum yac_location location)
Definition dist_grid.c:2876
static void get_pack_sizes(struct yac_dist_grid *dist_grid, enum yac_location location, uint64_t *pos, size_t count, int *pack_sizes, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3294
static void yac_single_remote_point_pack(struct single_remote_point *point, void *buffer, int buffer_size, int *position, MPI_Datatype single_remote_point_dt, MPI_Comm comm)
Definition dist_grid.c:5823
static MPI_Datatype yac_get_single_remote_point_mpi_datatype(MPI_Comm comm)
Definition dist_grid.c:258
static struct bnd_sphere_part_search * dist_grid_pair_get_cell_sphere_part(struct yac_dist_grid_pair *grid_pair, char const *grid_name)
Definition dist_grid.c:3028
static void pack_grid_data_edge_(struct yac_dist_grid *dist_grid, size_t idx, void *buffer, int buffer_size, int *position, MPI_Datatype bnd_circle_dt, MPI_Datatype point_info_dt, MPI_Comm comm)
Definition dist_grid.c:3371
static void yac_dist_grid_free(struct yac_dist_grid grid)
Definition dist_grid.c:2937
static void lookup_single_remote_point_reorder_locally(struct yac_dist_grid *dist_grid, enum yac_location location, struct single_remote_point_reorder *ids, size_t *count, size_t *idx)
Definition dist_grid.c:3102
struct bounding_circle const *const const_bounding_circle_pointer
size_t const *const const_size_t_pointer
int const *const const_int_pointer
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
size_t yac_field_data_get_masks_count(struct yac_field_data *field_data)
Definition field_data.c:57
void yac_field_data_set_mask_data(struct yac_field_data *field_data, size_t mask_idx, int *mask_data)
Definition field_data.c:72
size_t yac_field_data_get_coordinates_count(struct yac_field_data *field_data)
Definition field_data.c:92
yac_const_coordinate_pointer yac_field_data_get_coordinates_data(struct yac_field_data *field_data, size_t coordinates_idx)
Definition field_data.c:97
int const * yac_field_data_get_mask_data(struct yac_field_data *field_data, size_t mask_idx)
Definition field_data.c:62
char const * yac_field_data_get_mask_name(struct yac_field_data *field_data, size_t mask_idx)
Definition field_data.c:82
void yac_field_data_set_coordinates_data(struct yac_field_data *field_data, size_t coordinates_idx, yac_coordinate_pointer coordinates_data)
Definition field_data.c:108
size_t yac_field_data_add_mask_nocpy(struct yac_field_data *field_data, int const *mask, char const *mask_name)
Definition field_data.c:30
struct yac_field_data * yac_field_data_empty_new()
Definition field_data.c:20
size_t yac_field_data_add_coordinates_nocpy(struct yac_field_data *field_data, yac_coordinate_pointer coordinates)
Definition field_data.c:44
struct yac_field_data_set * yac_field_data_set_new(struct yac_field_data *cell_field_data, struct yac_field_data *vertex_field_data, struct yac_field_data *edge_field_data)
void yac_field_data_set_delete(struct yac_field_data_set *field_data_set)
struct yac_field_data * yac_field_data_set_get_field_data(struct yac_field_data_set *field_data_set, enum yac_location location)
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
Definition geometry.h:415
static int compare_coords(double const *a, double const *b)
Definition geometry.h:662
static const struct sin_cos_angle SIN_COS_ZERO
Definition geometry.h:44
#define yac_angle_tol
Definition geometry.h:34
static void normalise_vector(double v[])
Definition geometry.h:689
static struct sin_cos_angle half_angle(struct sin_cos_angle angle)
Definition geometry.h:600
void yac_init_grid_cell(struct grid_cell *cell)
Definition grid_cell.c:14
void yac_free_grid_cell(struct grid_cell *cell)
Definition grid_cell.c:44
yac_edge_type
Definition grid_cell.h:10
@ GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:11
struct @8::@9 value
yac_location
Definition location.h:10
@ YAC_LOC_CORNER
Definition location.h:13
@ YAC_LOC_EDGE
Definition location.h:14
@ YAC_LOC_CELL
Definition location.h:12
#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
void yac_proc_sphere_part_get_neigh_ranks(struct proc_sphere_part_node *node, uint64_t *leaf_sizes, uint64_t min_size, int *send_flags, int *recv_flags, int comm_rank, int comm_size)
void yac_proc_sphere_part_do_bnd_circle_search(struct proc_sphere_part_node *node, struct bounding_circle bnd_circle, int *ranks, int *rank_count)
void yac_proc_sphere_part_do_point_search(struct proc_sphere_part_node *node, yac_coordinate_pointer search_coords, size_t count, int *ranks)
void yac_proc_sphere_part_node_delete(struct proc_sphere_part_node *node)
struct proc_sphere_part_node * yac_redistribute_cells(struct dist_cell **cells, size_t *num_cells, MPI_Comm comm)
void yac_bnd_sphere_part_search_do_bnd_circle_search(struct bnd_sphere_part_search *search, struct bounding_circle *bnd_circles, size_t count, size_t **cells, size_t *num_cells_per_bnd_circle)
struct bnd_sphere_part_search * yac_bnd_sphere_part_search_new(struct bounding_circle *circles, size_t num_circles)
void yac_delete_point_sphere_part_search(struct point_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_mask_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids, int const *mask)
void yac_bnd_sphere_part_search_delete(struct bnd_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids)
void yac_bnd_sphere_part_search_do_point_search(struct bnd_sphere_part_search *search, yac_coordinate_pointer coordinates_xyz, size_t count, size_t **cells, size_t *num_cells_per_coordinate)
void yac_point_sphere_part_search_NNN(struct point_sphere_part_search *search, size_t num_points, double(*coordinates_xyz)[3], size_t n, double **cos_angles, size_t *cos_angles_array_size, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
algorithm for searching cells and points on a grid
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:61
double base_vector[3]
Definition geometry.h:59
double sq_crd
Definition geometry.h:64
double coord[3]
enum yac_edge_type edge_type
Definition dist_grid.c:54
struct remote_point_infos owners
Definition dist_grid.c:56
yac_int edge_to_vertex[2]
Definition dist_grid.c:55
struct remote_point_infos owners
Definition dist_grid.c:47
double(* coordinates_xyz)[3]
Definition grid_cell.h:17
enum yac_edge_type * edge_type
Definition grid_cell.h:18
size_t array_size
Definition grid_cell.h:20
size_t num_corners
Definition grid_cell.h:19
uint64_t orig_pos
Definition dist_grid.c:61
yac_int global_id
Definition dist_grid.c:60
double coord[3]
Definition dist_grid.c:75
size_t reorder_idx
Definition dist_grid.c:74
yac_int global_id
Definition dist_grid.c:73
struct missing_edge_neighbour::@0 cell
struct missing_edge_neighbour::@0 edge
size_t reorder_idx
Definition dist_grid.c:68
yac_int * ids
Definition dist_grid.c:67
yac_int global_id
Definition dist_grid.c:69
struct single_remote_point point_info
Definition dist_grid.c:120
struct remote_point_info single
struct remote_point_info * multi
union remote_point_infos::@1 data
struct remote_point data
Definition dist_grid.c:38
struct remote_point_infos data
struct remote_point_info buffer[]
struct remote_point * data
double cos
Definition geometry.h:41
struct single_remote_point data
Definition dist_grid.c:33
struct remote_point_info data
Definition dist_grid.c:29
yac_coordinate_pointer * coordinates
Definition dist_grid.c:82
size_t masks_count
Definition dist_grid.c:81
size_t * masks_array_sizes
Definition dist_grid.c:80
size_t * coordinates_array_sizes
Definition dist_grid.c:83
size_t coordinates_count
Definition dist_grid.c:84
yac_coordinate_pointer vertex_coordinates
yac_size_t_2_pointer edge_to_vertex
enum yac_edge_type * edge_type
size_t * cell_to_vertex_offsets
const_int_pointer num_vertices_per_cell
const_size_t_pointer cell_to_vertex_offsets
const_size_t_pointer cell_to_vertex
const_size_t_pointer cell_to_edge
const_size_t_pointer cell_to_edge_offsets
const_yac_edge_type_pointer edge_type
yac_const_coordinate_pointer vertex_coordinates
struct point_sphere_part_search * vertex_sphere_part[2]
Definition dist_grid.c:114
struct proc_sphere_part_node * proc_sphere_part
Definition dist_grid.c:113
struct yac_dist_grid dist_grid[2]
Definition dist_grid.c:111
struct bnd_sphere_part_search * cell_sphere_part[2]
Definition dist_grid.c:115
char * grid_names[2]
Definition dist_grid.c:112
int * core_mask[3]
Definition dist_grid.c:103
MPI_Comm comm
Definition dist_grid.c:107
size_t count[3]
Definition dist_grid.c:102
size_t * cell_to_edge
Definition dist_grid.c:95
size_t * sorted_reorder_idx[3]
Definition dist_grid.c:105
struct yac_field_data_set * field_data
Definition dist_grid.c:106
yac_int * ids[3]
Definition dist_grid.c:91
size_t * cell_to_vertex
Definition dist_grid.c:93
struct bounding_circle * cell_bnd_circles
Definition dist_grid.c:98
struct remote_point_infos * owners[3]
Definition dist_grid.c:100
enum yac_edge_type * edge_type
Definition dist_grid.c:99
yac_coordinate_pointer vertex_coordinates
Definition dist_grid.c:90
size_t * cell_to_edge_offsets
Definition dist_grid.c:96
yac_int * sorted_ids[3]
Definition dist_grid.c:104
size_t * cell_to_vertex_offsets
Definition dist_grid.c:94
yac_size_t_2_pointer edge_to_vertex
Definition dist_grid.c:97
int * num_vertices_per_cell
Definition dist_grid.c:92
size_t total_count[3]
Definition dist_grid.c:101
enum yac_location location
Definition basic_grid.h:16
size_t coordinates_idx
Definition basic_grid.h:17
#define MIN(a, b)
#define YAC_ASSERT_F(exp, format,...)
#define MAX(a, b)
#define YAC_ASSERT(exp, msg)
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)
static void yac_remove_duplicates_size_t(size_t *array, size_t *n)
Definition utils_core.h:108
void yac_quicksort_index_size_t_size_t(size_t *a, size_t n, size_t *idx)
static struct user_input_data_points ** points
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
Definition yac_mpi.c:569
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:624
MPI_Datatype yac_get_bounding_circle_mpi_datatype(MPI_Comm comm)
Definition yac_mpi.c:528
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
Definition yac_mpi.c:593
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:548
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm)
Definition yac_mpi.c:129
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T
Xt_int yac_int
Definition yac_types.h:11
size_t(* yac_size_t_2_pointer)[2]
Definition yac_types.h:19
#define yac_int_dt
Definition yac_types.h:12
double const (*const yac_const_coordinate_pointer)[3]
Definition yac_types.h:16
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:15