14#ifdef SCOREP_USER_ENABLE
15#include "scorep/SCOREP_User.h"
91 MPI_Pack_size(3, MPI_DOUBLE, comm, &vec_pack_size), comm);
93 return vec_pack_size +
102 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
104 int data_size = int_pack_size;
106 data_size += int_pack_size;
116 int pack_buffer_size,
int * position, MPI_Comm comm);
120 int pack_buffer_size,
int * position, MPI_Comm comm) {
123 pack_buffer_size, position, comm), comm);
125 node->U, pack_buffer, pack_buffer_size, position, comm);
127 node->
T, pack_buffer, pack_buffer_size, position, comm);
132 int pack_buffer_size,
int * position, MPI_Comm comm) {
135 pack_buffer_size, position, comm), comm);
139 pack_buffer_size, position, comm), comm);
142 pack_buffer_size, position, comm);
146 void * pack_buffer,
int pack_buffer_size,
int * position,
150 void * pack_buffer,
int pack_buffer_size,
int * position,
156 MPI_Unpack(pack_buffer, pack_buffer_size, position,
168 void * pack_buffer,
int pack_buffer_size,
int * position,
174 MPI_Unpack(pack_buffer, pack_buffer_size, position,
175 &(node_data.
is_leaf), 1, MPI_INT, comm), comm);
179 MPI_Unpack(pack_buffer, pack_buffer_size, position,
180 &(node_data.
data.
rank), 1, MPI_INT, comm), comm);
184 pack_buffer, pack_buffer_size, position, comm);
195 MPI_Comm comm = local_group_comm.comm;
201 int order = local_group_comm.start < remote_group_comm.start;
203 for (
int i = 0; i < 2; ++i) {
208 &data_size, 1, MPI_INT, remote_group_comm.start, local_group_comm);
211 remote_group_comm.start, local_group_comm);
214 if (comm_rank == local_group_comm.start) {
217 int pack_buffer_size =
219 void * pack_buffer =
xmalloc((
size_t)pack_buffer_size);
222 local_data, pack_buffer, pack_buffer_size, &position, comm);
226 &position, 1, MPI_INT, local_group_comm.start, remote_group_comm);
230 local_group_comm.start, remote_group_comm);
247 int comm_rank,
int split_rank,
int comm_size,
248 size_t global_sizes[2],
size_t (*all_bucket_sizes)[2],
249 int * counts,
int * displs,
size_t * recv_count) {
251 int color = comm_rank >= split_rank;
260 size_t global_size = global_sizes[color];
261 size_t local_interval_start =
266 size_t local_interval_end =
272 *recv_count = (size_t)(local_interval_end - local_interval_start);
274 size_t start_idx = 0;
275 for (
int i = 0; i < comm_size; ++i) {
277 size_t next_start_idx = start_idx + all_bucket_sizes[i][color];
278 size_t interval_start =
MAX(start_idx, local_interval_start);
279 size_t interval_end =
MIN(next_start_idx, local_interval_end);
281 if (interval_start < interval_end) {
283 size_t count = interval_end - interval_start;
284 size_t disp = interval_start - local_interval_start;
287 (count <= INT_MAX) && (disp <= INT_MAX),
288 "ERROR(compute_redist_recvcounts_rdispls): invalid interval")
290 counts[i] = (int)count;
291 displs[i] = (int)disp;
297 start_idx = next_start_idx;
302 int comm_rank,
int split_rank,
int comm_size,
303 size_t global_sizes[2],
size_t (*all_bucket_sizes)[2],
304 int * counts,
int * displs) {
306 size_t U_size = all_bucket_sizes[comm_rank][0];
308 size_t local_interval_start[2] = {0, 0};
309 size_t local_interval_end[2];
310 for (
int i = 0; i < comm_rank; ++i)
311 for (
int j = 0; j < 2; ++j)
312 local_interval_start[j] += all_bucket_sizes[i][j];
313 for (
int j = 0; j < 2; ++j)
314 local_interval_end[j] =
315 local_interval_start[j] + all_bucket_sizes[comm_rank][j];
317 int comm_sizes[2] = {split_rank, comm_size - split_rank};
319 size_t start_idx[2] = {0,0};
320 for (
int i = 0; i < comm_size; ++i) {
322 int color = i >= split_rank;
323 size_t global_size = global_sizes[color];
326 size_t next_start_idx =
331 size_t interval_start =
MAX(start_idx[color], local_interval_start[color]);
332 size_t interval_end =
MIN(next_start_idx, local_interval_end[color]);
334 if (interval_start < interval_end) {
336 size_t count = interval_end - interval_start;
337 size_t disp = interval_start - local_interval_start[color] +
338 ((color)?(U_size):(0));
341 (count <= INT_MAX) && (disp <= INT_MAX),
342 "ERROR(compute_redist_sendcounts_sdispls): invalid interval")
344 counts[i] = (int)count;
345 displs[i] = (int)disp;
351 start_idx[color] = next_start_idx;
362 for (
size_t i = 0; i < count; ++i) {
364 if (reorder_idx[i] != i) {
371 size_t swap = reorder_idx[j];
394 if (((
const struct dist_vertex *)a)->global_id != YAC_INT_MAX)
408 struct dist_vertex * vertices,
size_t * num_vertices,
410 size_t ** owners_reorder_idx,
size_t * owners_reorder_idx_array_size) {
412 if (*num_vertices == 0)
return;
415 *owners_reorder_idx, *owners_reorder_idx_array_size,
num_owners);
420 for (
size_t i = 0; i < *num_vertices; ++i) {
426 "ERROR(remove_duplicated_vertices): internal error "
427 "(owner_offset != num_owners)");
435 size_t old_num_vertices = *num_vertices;
436 size_t new_num_vertices = 0;
440 size_t * owners_reorder_idx_ = *owners_reorder_idx;
441 for (
size_t i = 0, reorder_idx = 0; i < old_num_vertices;
442 ++i, ++curr_vertex) {
448 prev_vertex = vertices + new_num_vertices;
450 if (prev_vertex != curr_vertex) *prev_vertex = *curr_vertex;
455 *num_vertices = new_num_vertices;
462 struct dist_vertex ** vertices,
size_t * num_vertices,
464 size_t global_bucket_sizes[2],
size_t (*all_bucket_sizes)[2],
466 size_t ** owners_reorder_idx,
size_t * owners_reorder_idx_array_size,
467 MPI_Datatype dist_vertex_dt, MPI_Datatype remote_point_info_dt,
470#ifdef SCOREP_USER_ENABLE
471SCOREP_USER_REGION_DEFINE( redist_data_region )
472SCOREP_USER_REGION_BEGIN(
473 redist_data_region,
"data redistribution", SCOREP_USER_REGION_TYPE_COMMON )
482 group_rank, split_rank, group_size, global_bucket_sizes, all_bucket_sizes,
484 size_t new_num_vertices;
486 group_rank, split_rank, group_size, global_bucket_sizes, all_bucket_sizes,
491 xmalloc(new_num_vertices *
sizeof(*new_vertices));
495 sizeof(**vertices), dist_vertex_dt, group_comm);
498 size_t new_num_owners;
500 size_t saccu = 0, raccu = 0, send_vertex_idx = 0, recv_vertex_idx = 0;
501 for (
int i = 0; i < group_size; ++i) {
502 size_t send_count = 0, recv_count = 0;
504 send_count += (
size_t)((*vertices)[send_vertex_idx].num_owners);
506 recv_count += (
size_t)(new_vertices[recv_vertex_idx].
num_owners);
508 (saccu <= INT_MAX) && (raccu <= INT_MAX),
509 "ERROR(redistribute_dist_vertices): displacement exceeds INT_MAX");
511 (send_count <= INT_MAX) && (recv_count <= INT_MAX),
512 "ERROR(redistribute_dist_vertices): counts exceeds INT_MAX");
522 "ERROR(redistribute_dist_vertices): inconsistent owner count");
523 new_num_owners = raccu;
528 xmalloc(new_num_owners *
sizeof(*new_owners));
532 sizeof(**owners), remote_point_info_dt, group_comm);
536 *vertices = new_vertices;
537 *num_vertices = new_num_vertices;
538 *owners = new_owners;
539 *num_owners = new_num_owners;
544 *vertices, num_vertices, *owners, *num_owners,
545 owners_reorder_idx, owners_reorder_idx_array_size);
547#ifdef SCOREP_USER_ENABLE
548SCOREP_USER_REGION_END( redist_data_region )
572 double const * restrict gc_norm_vector,
573 double const * restrict vertex_coord) {
581 struct dist_vertex ** vertices,
size_t * num_vertices,
584 size_t ** reorder_idx,
size_t * reorder_idx_array_size,
585 int ** list_flag_,
size_t * list_flag_array_size,
586 MPI_Datatype dist_vertex_dt, MPI_Datatype remote_point_info_dt,
587 struct yac_group_comm group_comm,
double prev_gc_norm_vector[3]) {
589#ifdef SCOREP_USER_ENABLE
590SCOREP_USER_REGION_DEFINE( local_balance_point_region )
591SCOREP_USER_REGION_DEFINE( global_balance_point_region )
592SCOREP_USER_REGION_DEFINE( splitting_region )
593SCOREP_USER_REGION_DEFINE( comm_split_region )
603#ifdef SCOREP_USER_ENABLE
604SCOREP_USER_REGION_BEGIN(
605 local_balance_point_region,
"local balance point",
606 SCOREP_USER_REGION_TYPE_COMMON )
609 double balance_point[3] = {0.0, 0.0, 0.0};
610 for (
size_t i = 0; i < *num_vertices; ++i) {
611 double * vertex_coord = (*vertices)[i].coord;
612 for (
int j = 0; j < 3; ++j) balance_point[j] += vertex_coord[j];
614#ifdef SCOREP_USER_ENABLE
615SCOREP_USER_REGION_END( local_balance_point_region )
616SCOREP_USER_REGION_BEGIN(
617 global_balance_point_region,
"global balance point",
618 SCOREP_USER_REGION_TYPE_COMMON )
627 if ((fabs(balance_point[0]) > 1e-9) ||
628 (fabs(balance_point[1]) > 1e-9) ||
629 (fabs(balance_point[2]) > 1e-9)) {
632 balance_point[0] = prev_gc_norm_vector[2];
633 balance_point[1] = prev_gc_norm_vector[0];
634 balance_point[2] = prev_gc_norm_vector[1];
653#ifdef SCOREP_USER_ENABLE
654SCOREP_USER_REGION_END( global_balance_point_region )
661#ifdef SCOREP_USER_ENABLE
662SCOREP_USER_REGION_BEGIN( splitting_region,
"splitting data", SCOREP_USER_REGION_TYPE_COMMON )
666 int * list_flag = *list_flag_;
670 size_t num_vertices_ = *num_vertices;
674 for (
size_t i = 0; i < num_vertices_; ++i) {
679 size_t U_size = 0, T_size = 0;
680 for (
size_t i = 0; i < num_vertices_; ++i) {
681 if (list_flag[i]) ++U_size;
686 for (
size_t i = 0,
owner_offset = 0; i < num_vertices_; ++i) {
697 for (
size_t i = 0, j = U_size; i < U_size; ++i) {
701 for (;!list_flag[j];++j);
703 vertices_[i] = vertices_[j];
704 vertices_[j] = temp_vertex;
711 size_t * reorder_idx_ = *reorder_idx;
712 for (
size_t i = 0, k = 0; i < num_vertices_; ++i) {
715 for (
int j = 0; j <
num_owners; ++j, ++k, ++offset) {
716 reorder_idx_[offset] = k;
721#ifdef SCOREP_USER_ENABLE
722SCOREP_USER_REGION_END( splitting_region )
725 size_t bucket_sizes[2] = {U_size, T_size};
729 &(bucket_sizes[0]), &(all_bucket_sizes[0][0]), 2, group_comm);
732 size_t global_bucket_sizes[2] = {0, 0};
733 for (
int i = 0; i < group_size; ++i)
734 for (
int j = 0; j < 2; ++j)
735 global_bucket_sizes[j] += all_bucket_sizes[i][j];
736 size_t global_num_vertices =
737 global_bucket_sizes[0] + global_bucket_sizes[1];
742#ifdef SCOREP_USER_ENABLE
743SCOREP_USER_REGION_BEGIN(
744 comm_split_region,
"creating splitcomm", SCOREP_USER_REGION_TYPE_COMMON )
750 (((
unsigned long long)global_bucket_sizes[0] *
751 (
unsigned long long)group_size +
752 (
unsigned long long)(global_num_vertices / 2)) /
753 (
unsigned long long)global_num_vertices), 1),
759 group_comm, split_rank, &local_group_comm, &remote_group_comm);
761#ifdef SCOREP_USER_ENABLE
762SCOREP_USER_REGION_END( comm_split_region )
770 vertices, num_vertices, owners, num_owners,
771 global_bucket_sizes, all_bucket_sizes, split_rank,
comm_buffers,
772 reorder_idx, reorder_idx_array_size, dist_vertex_dt, remote_point_info_dt,
785 vertices, num_vertices, owners, num_owners,
786 all_bucket_sizes,
comm_buffers, reorder_idx, reorder_idx_array_size,
787 list_flag_, list_flag_array_size, dist_vertex_dt, remote_point_info_dt,
788 local_group_comm, gc_norm_vector);
802 if (group_rank < split_rank) {
803 node->U = local_data;
804 node->
T = remote_data;
806 node->U = remote_data;
807 node->
T = local_data;
817 MPI_Datatype dist_vertex_dt;
818 enum {NUM_MEMBERS = 4};
819 int array_of_blocklengths[NUM_MEMBERS] = {3, 1, 1, 1};
820 const MPI_Aint array_of_displacements[NUM_MEMBERS] =
821 {(MPI_Aint)(intptr_t)(
const void *)&(dummy.
coord[0]) -
822 (MPI_Aint)(intptr_t)(
const void *)&dummy,
823 (MPI_Aint)(intptr_t)(
const void *)&(dummy.
grid_idx) -
824 (MPI_Aint)(intptr_t)(
const void *)&dummy,
825 (MPI_Aint)(intptr_t)(
const void *)&(dummy.
global_id) -
826 (MPI_Aint)(intptr_t)(
const void *)&dummy,
827 (MPI_Aint)(intptr_t)(
const void *)&(dummy.
num_owners) -
828 (MPI_Aint)(intptr_t)(
const void *)&dummy};
829 const MPI_Datatype array_of_types[NUM_MEMBERS] =
832 MPI_Type_create_struct(NUM_MEMBERS, array_of_blocklengths,
833 array_of_displacements, array_of_types,
834 &dist_vertex_dt), comm);
839 struct dist_vertex * dist_vertices,
size_t num_dist_vertices,
841 size_t ** reorder_idx,
size_t * reorder_idx_array_size,
842 yac_int **global_vertex_ids[2],
int * global_ids_missing,
843 int **vertex_ranks[2],
size_t * num_vertices, MPI_Comm comm) {
849 int comm_rank, comm_size;
854 size_t num_vertices_per_grid[2] = {0, 0};
855 size_t num_owners_per_grid[2] = {0, 0};
856 for (
size_t i = 0; i < num_dist_vertices; ++i) {
857 num_vertices_per_grid[dist_vertices[i].
grid_idx]++;
858 num_owners_per_grid[dist_vertices[i].grid_idx] +=
862 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
864 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
867 *reorder_idx, *reorder_idx_array_size,
868 MAX((num_owners_per_grid[0] + num_vertices[0]),
869 (num_owners_per_grid[1] + num_vertices[1])));
870 yac_int * global_vertex_ids_buffer =
873 (global_ids_missing[0]?(num_owners_per_grid[0] + num_vertices[0]):0),
874 (global_ids_missing[1]?(num_owners_per_grid[1] + num_vertices[1]):0)) *
875 sizeof(*global_vertex_ids_buffer));
881 dist_vertices + ((
grid_idx == 0)?0:num_vertices_per_grid[0]);
883 dist_owners + ((
grid_idx == 0)?0:num_owners_per_grid[0]);
890 num_vertices_per_grid[
grid_idx] <= (
size_t)YAC_INT_MAX,
891 "ERROR(inform_dist_vertex_owners): global_id out of bounds");
897 MPI_SUM, comm), comm);
898 if (comm_rank == 0) id_offset = 0;
901 ((
size_t)id_offset + num_vertices_per_grid[
grid_idx]) <=
903 "ERROR(inform_dist_vertex_owners): global_id out of bounds")
906 memset(sendcounts, 0, (
size_t)(comm_size + 1) *
sizeof(*sendcounts));
909 for (
size_t i = 0; i < num_owners_per_grid[
grid_idx]; ++i)
910 sendcounts[dist_grid_owners[i].
rank]++;
912 1, sendcounts, recvcounts, sdispls, rdispls, comm);
914 size_t * send_reorder_idx = *reorder_idx;
915 size_t * recv_reorder_idx = *reorder_idx + num_owners_per_grid[
grid_idx];
916 yac_int * send_global_vertex_ids = global_vertex_ids_buffer;
917 yac_int * recv_global_vertex_ids = global_vertex_ids_buffer +
920 for (
size_t i = 0, k = 0; i < num_vertices_per_grid[
grid_idx]; ++i) {
922 int num_vertex_owners = dist_grid_vertices[i].
num_owners;
924 for (
int j = 0; j < num_vertex_owners; ++j, ++k) {
926 size_t pos = sdispls[dist_grid_owners[k].
rank + 1]++;
927 send_reorder_idx[pos] = dist_grid_owners[k].orig_pos;
929 send_global_vertex_ids[pos] = id_offset + (
yac_int)i;
935 send_reorder_idx, sendcounts, sdispls,
936 recv_reorder_idx, recvcounts, rdispls,
938 "inform_dist_vertex_owners", __LINE__);
942 int * curr_vertex_ranks =
946 for (
size_t i = 0; i < recvcounts[
rank]; ++i, ++j)
947 curr_vertex_ranks[recv_reorder_idx[j]] =
rank;
948 *(vertex_ranks[
grid_idx]) = curr_vertex_ranks;
955 send_global_vertex_ids, sendcounts, sdispls,
956 recv_global_vertex_ids, recvcounts, rdispls,
957 sizeof(*send_global_vertex_ids),
yac_int_dt, comm,
958 "inform_dist_vertex_owners", __LINE__);
960 yac_int * curr_global_vertex_ids =
963 for (
size_t i = 0; i < num_vertices[
grid_idx]; ++i)
964 curr_global_vertex_ids[recv_reorder_idx[i]] = recv_global_vertex_ids[i];
966 *(global_vertex_ids[
grid_idx]) = curr_global_vertex_ids;
970 free(global_vertex_ids_buffer);
978 yac_int **global_vertex_ids_[2],
int **vertex_ranks[2], MPI_Comm comm) {
981 yac_int *global_vertex_ids[2] =
982 {*(global_vertex_ids_[0]), *(global_vertex_ids_[1])};
983 int global_ids_missing[2] =
984 {(num_vertices[0] > 0) && (global_vertex_ids[0] == NULL),
985 (num_vertices[1] > 0) && (global_vertex_ids[1] == NULL)};
987 MPI_Allreduce(MPI_IN_PLACE, global_ids_missing, 2, MPI_INT, MPI_MAX, comm),
990 size_t total_num_vertices = num_vertices[0] + num_vertices[1];
992 int comm_rank, comm_size;
996 double base_gc_norm_vector[3] = {0.0,0.0,1.0};
998 int vertices_available = total_num_vertices > 0;
1001 MPI_IN_PLACE, &vertices_available, 1, MPI_INT, MPI_MAX, comm), comm);
1003 if ((comm_size > 1) && vertices_available) {
1007 xmalloc(total_num_vertices *
sizeof(*dist_owners));
1008 for (
size_t i = 0; i < num_vertices[0]; ++i)
1011 for (
size_t i = 0, j = num_vertices[0]; i < num_vertices[1]; ++i, ++j)
1017 xmalloc(total_num_vertices *
sizeof(*dist_vertices));
1021 for (
int i = 0; i < 2; ++i) {
1023 for (
size_t j = 0; j < num_vertices[i]; ++j, ++k) {
1025 dist_vertices[k].
coord, vertex_coordinates[i][j],
1026 3 *
sizeof(vertex_coordinates[i][j][0]));
1029 (global_ids_missing[i])?YAC_INT_MAX:global_vertex_ids[i][j];
1036 size_t num_dist_vertices = total_num_vertices;
1037 size_t num_dist_owners = total_num_vertices;
1038 size_t (*all_bucket_sizes)[2] =
1039 xmalloc((
size_t)comm_size *
sizeof(*(all_bucket_sizes)));
1046 size_t * reorder_idx = NULL, reorder_idx_array_size = 0;
1047 int * list_flag = NULL;
1048 size_t list_flag_array_size = 0;
1050 MPI_Datatype remote_point_info_dt =
1058 (
size_t[2]){total_num_vertices,0}, &(all_bucket_sizes[0][0]), 2,
1060 size_t global_num_vertices = 0;
1061 for (
int i = 0; i < comm_size; ++i)
1062 global_num_vertices += all_bucket_sizes[i][0];
1064 &dist_vertices, &num_dist_vertices, &dist_owners, &num_dist_owners,
1065 (
size_t[2]){global_num_vertices, 0}, all_bucket_sizes, comm_size,
1067 dist_vertex_dt, remote_point_info_dt, group_comm);
1072 &dist_vertices, &num_dist_vertices, &dist_owners, &num_dist_owners,
1073 all_bucket_sizes,
comm_buffers, &reorder_idx, &reorder_idx_array_size,
1074 &list_flag, &list_flag_array_size, dist_vertex_dt, remote_point_info_dt,
1075 group_comm, base_gc_norm_vector);
1083 free(all_bucket_sizes);
1087 dist_vertices, num_dist_vertices, dist_owners,
1088 &reorder_idx, &reorder_idx_array_size, global_vertex_ids_,
1089 global_ids_missing, vertex_ranks, num_vertices,
comm);
1094 free(dist_vertices);
1097 *proc_sphere_part =
xmalloc(1 *
sizeof(**proc_sphere_part));
1098 (*proc_sphere_part)->U.data.rank = 0;
1099 (*proc_sphere_part)->U.is_leaf = 1;
1100 (*proc_sphere_part)->T.data.rank = 0;
1101 (*proc_sphere_part)->T.is_leaf = 1;
1102 (*proc_sphere_part)->gc_norm_vector[0] = base_gc_norm_vector[0];
1103 (*proc_sphere_part)->gc_norm_vector[1] = base_gc_norm_vector[1];
1104 (*proc_sphere_part)->gc_norm_vector[2] = base_gc_norm_vector[2];
1110 for (
size_t i = 0; i < num_vertices[
grid_idx]; ++i)
1111 (*(vertex_ranks[
grid_idx]))[i] = 0;
1112 if (global_ids_missing[
grid_idx]) {
1116 for (
size_t i = 0; i < num_vertices[
grid_idx]; ++i)
1124 return (node->U.is_leaf) && (node->
T.
is_leaf) &&
1125 (node->U.data.rank == 0) && (node->
T.
data.
rank == 0);
1129#ifdef YAC_NEC_EXPERIMENTAL
1131static void yac_proc_sphere_part_do_point_search_recursive(
1133 size_t * search_idx,
size_t * temp_search_idx,
int *
flag,
1134 size_t count,
int * ranks) {
1138 for (
size_t i = 0;
i < count; ++
i) {
1144 size_t u_size = 0, t_size = 0;
1145 for (
size_t i = 0;
i < count; ++
i) {
1146 if (
flag[i]) search_idx[u_size++] = search_idx[
i];
1147 else temp_search_idx[t_size++] = search_idx[
i];
1150 if (node->U.is_leaf) {
1151 size_t rank = node->U.data.rank;
1152 for (
size_t i = 0;
i < u_size; ++
i) ranks[search_idx[i]] = rank;
1154 yac_proc_sphere_part_do_point_search_recursive(
1155 node->U.data.node, search_coords, search_idx, temp_search_idx + t_size,
1156 flag, u_size, ranks);
1161 for (
size_t i = 0;
i < t_size; ++
i) ranks[temp_search_idx[i]] = rank;
1163 yac_proc_sphere_part_do_point_search_recursive(
1164 node->
T.
data.
node, search_coords, temp_search_idx, search_idx + u_size,
1165 flag, t_size, ranks);
1172 size_t count,
int * ranks) {
1175 for (
size_t i = 0; i < count; ++i) ranks[i] = 0;
1179#ifdef YAC_NEC_EXPERIMENTAL
1181 size_t * search_idx =
xmalloc(2 * count *
sizeof(*search_idx));
1182 for (
size_t i = 0; i < count; ++i) search_idx[i] = i;
1184 yac_proc_sphere_part_do_point_search_recursive(
1185 node, search_coords, search_idx, search_idx + count,
flag, count, ranks);
1194 for (
size_t i = 0; i < count; ++i) {
1196 double * curr_coord = search_coords[i];
1204 if (curr_node->U.is_leaf) {
1205 ranks[i] = curr_node->U.data.rank;
1208 curr_node = curr_node->U.data.node;
1228 int * ranks,
int * rank_count) {
1248 if (node->U.is_leaf) {
1250 ranks[*rank_count] = node->U.data.rank;
1261 int * ranks,
int * rank_count) {
1270 node->
T.
data.
node, bnd_circle, ranks, rank_count);
1273 if (node->U.is_leaf) {
1275 ranks[*rank_count] = node->U.data.rank;
1280 node->U.data.node, bnd_circle, ranks, rank_count);
1286 int * ranks,
int * rank_count) {
1290 "ERROR(yac_proc_sphere_part_do_bnd_circle_search): angle is >= PI")
1310 if (node->U.is_leaf) {
1311 *ranks = node->U.data.rank;
1327 uint64_t ** inner_node_sizes,
int * send_flags,
int * recv_flags,
1330 int curr_node_is_valid = (**inner_node_sizes >= min_size);
1337 if (curr_node_is_valid) {
1341 curr_valid_node = &temp_valid_node;
1344 curr_valid_node = last_valid_node;
1347 for (
int j = 0; j < 2; ++j) {
1355 if (leaf_sizes[
rank] < min_size) {
1362 if (
rank == comm_rank)
1363 for (
int i = 0; i < curr_valid_node->
num_ranks; ++i)
1364 recv_flags[ranks[i]] = 1;
1368 for (
int i = 0; i < curr_valid_node->
num_ranks; ++i) {
1369 if (ranks[i] == comm_rank) {
1370 send_flags[
rank] = 1;
1377 ++*inner_node_sizes;
1379 node_data.
data.
node, leaf_sizes, min_size, inner_node_sizes,
1380 send_flags, recv_flags, comm_rank, curr_valid_node);
1387 uint64_t ** inner_node_sizes) {
1389 uint64_t * curr_inner_node_size = *inner_node_sizes;
1391 if (
node->U.is_leaf) {
1392 node_size = leaf_sizes[
node->U.data.rank];
1394 ++*inner_node_sizes;
1401 ++*inner_node_sizes;
1405 return (*curr_inner_node_size = node_size);
1410 uint64_t min_size,
int * send_flags,
int * recv_flags,
1411 int comm_rank,
int comm_size) {
1416 uint64_t * inner_node_sizes =
1417 xcalloc((
size_t)comm_size,
sizeof(*inner_node_sizes));
1418 uint64_t * temp_inner_node_sizes = inner_node_sizes;
1422 *inner_node_sizes >= min_size,
1423 "ERROR(yac_proc_sphere_part_get_neigh_ranks): sum of global leaf sizes "
1432 temp_inner_node_sizes = inner_node_sizes;
1434 send_flags, recv_flags, comm_rank, &search_data);
1436 send_flags[comm_rank] = 0;
1437 recv_flags[comm_rank] = 0;
1439 free(search_data.
ranks);
1440 free(inner_node_sizes);
#define YAC_ASSERT(exp, msg)
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
static int compare_coords(double const *a, double const *b)
static double dotproduct_eft(double const a[], double const b[])
static const struct sin_cos_angle SIN_COS_M_PI
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
static void normalise_vector(double v[])
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)
void yac_proc_sphere_part_new(yac_coordinate_pointer vertex_coordinates[2], size_t *num_vertices, struct proc_sphere_part_node **proc_sphere_part, yac_int **global_vertex_ids_[2], int **vertex_ranks[2], MPI_Comm comm)
#define xcalloc(nmemb, size)
static int get_leaf_ranks(struct proc_sphere_part_node *node, int *ranks)
static struct proc_sphere_part_node * generate_proc_sphere_part_node_recursive(struct dist_vertex **vertices, size_t *num_vertices, struct remote_point_info **owners, size_t *num_owners, size_t(*all_bucket_sizes)[2], struct comm_buffers comm_buffers, size_t **reorder_idx, size_t *reorder_idx_array_size, int **list_flag_, size_t *list_flag_array_size, MPI_Datatype dist_vertex_dt, MPI_Datatype remote_point_info_dt, struct yac_group_comm group_comm, double prev_gc_norm_vector[3])
static uint64_t determine_node_sizes(struct proc_sphere_part_node *node, uint64_t *leaf_sizes, uint64_t **inner_node_sizes)
static void bnd_circle_search(struct proc_sphere_part_node *node, struct bounding_circle bnd_circle, int *ranks, int *rank_count)
static void reorder_data_remote_point_info(size_t *reorder_idx, size_t count, struct remote_point_info *data)
proc_sphere_part_list_type
static void compute_redist_recvcounts_rdispls(int comm_rank, int split_rank, int comm_size, size_t global_sizes[2], size_t(*all_bucket_sizes)[2], int *counts, int *displs, size_t *recv_count)
static int is_serial_node(struct proc_sphere_part_node *node)
static struct proc_sphere_part_node_data get_remote_data(struct proc_sphere_part_node_data local_data, struct yac_group_comm local_group_comm, struct yac_group_comm remote_group_comm)
static void get_neigh_ranks(struct proc_sphere_part_node *node, uint64_t *leaf_sizes, uint64_t min_size, uint64_t **inner_node_sizes, int *send_flags, int *recv_flags, int comm_rank, struct neigh_search_data *last_valid_node)
static MPI_Datatype yac_get_dist_vertex_mpi_datatype(MPI_Comm comm)
static void pack_proc_sphere_part_node(struct proc_sphere_part_node *node, void *pack_buffer, int pack_buffer_size, int *position, MPI_Comm comm)
static int get_proc_sphere_part_node_pack_size(struct proc_sphere_part_node node, MPI_Comm comm)
static void pack_proc_sphere_part_node_data(struct proc_sphere_part_node_data node_data, void *pack_buffer, int pack_buffer_size, int *position, MPI_Comm comm)
static void remove_duplicated_vertices(struct dist_vertex *vertices, size_t *num_vertices, struct remote_point_info *owners, size_t num_owners, size_t **owners_reorder_idx, size_t *owners_reorder_idx_array_size)
static void compute_redist_sendcounts_sdispls(int comm_rank, int split_rank, int comm_size, size_t global_sizes[2], size_t(*all_bucket_sizes)[2], int *counts, int *displs)
static void inform_dist_vertex_owners(struct dist_vertex *dist_vertices, size_t num_dist_vertices, struct remote_point_info *dist_owners, size_t **reorder_idx, size_t *reorder_idx_array_size, yac_int **global_vertex_ids[2], int *global_ids_missing, int **vertex_ranks[2], size_t *num_vertices, MPI_Comm comm)
static int get_proc_sphere_part_node_data_pack_size(struct proc_sphere_part_node_data node_data, MPI_Comm comm)
static int compare_dist_vertices(const void *a, const void *b)
static struct proc_sphere_part_node * unpack_proc_sphere_part_node(void *pack_buffer, int pack_buffer_size, int *position, MPI_Comm comm)
static struct proc_sphere_part_node_data unpack_proc_sphere_part_node_data(void *pack_buffer, int pack_buffer_size, int *position, MPI_Comm comm)
static enum proc_sphere_part_list_type determine_list_type(double const *restrict gc_norm_vector, double const *restrict vertex_coord)
static void redistribute_dist_vertices(struct dist_vertex **vertices, size_t *num_vertices, struct remote_point_info **owners, size_t *num_owners, size_t global_bucket_sizes[2], size_t(*all_bucket_sizes)[2], int split_rank, struct comm_buffers comm_buffers, size_t **owners_reorder_idx, size_t *owners_reorder_idx_array_size, MPI_Datatype dist_vertex_dt, MPI_Datatype remote_point_info_dt, struct yac_group_comm group_comm)
static void bnd_circle_search_big_angle(struct proc_sphere_part_node *node, struct bounding_circle bnd_circle, int *ranks, int *rank_count)
MPI_Datatype yac_get_remote_point_info_mpi_datatype(MPI_Comm comm)
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
struct proc_sphere_part_node * node
Data structure for the process sphere partition.
struct proc_sphere_part_node * node
int is_leaf
1 if this node is a leaf, 0 for inner nodes
union proc_sphere_part_node_data::@52 data
Inner node of the process sphere partition tree.
double gc_norm_vector[3]
Normal vector of the great circle dividing the two child nodes.
struct proc_sphere_part_node_data U T
Data of the two child nodes (U and T) of this node.
single location information of a point
void yac_alltoallv_p2p_group(void const *send_buffer, int const *sendcounts, int const *sdispls, void *recv_buffer, int const *recvcounts, int const *rdispls, size_t dt_size, MPI_Datatype dt, struct yac_group_comm group_comm)
int yac_group_comm_get_global_rank(struct yac_group_comm group_comm)
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
int yac_group_comm_get_rank(struct yac_group_comm group_comm)
void yac_group_comm_split(struct yac_group_comm group_comm, int split_rank, struct yac_group_comm *local_group_comm, struct yac_group_comm *remote_group_comm)
struct yac_group_comm yac_group_comm_new(MPI_Comm comm)
void yac_allreduce_sum_dble(double *buffer, int count, struct yac_group_comm group_comm)
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
int yac_group_comm_get_size(struct yac_group_comm group_comm)
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
void yac_bcast_group(void *buffer, int count, MPI_Datatype datatype, int root, struct yac_group_comm group_comm)
void yac_allgather_size_t(const size_t *sendbuf, size_t *recvbuf, int count, struct yac_group_comm group_comm)
void yac_group_comm_delete(struct yac_group_comm group_comm)
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const *caller, int line)
#define yac_mpi_call(call, comm)
double(* yac_coordinate_pointer)[3]