599 char const * filename,
char const * grid_name,
size_t num_cells,
600 int num_vertices_per_cell,
int cell_center_coords_avaiable,
601 int cell_global_ids_available,
int core_cell_mask_available,
602 int vertex_global_ids_available,
int core_vertex_mask_available,
603 int edge_global_ids_available,
int core_edge_mask_available) {
605 size_t grid_name_len = strlen(grid_name) + 1;
607 char nv_dim_name[3 + grid_name_len];
608 char nc_dim_name[3 + grid_name_len];
610 char cla_var_name[4 + grid_name_len];
611 char clo_var_name[4 + grid_name_len];
612 char lat_var_name[4 + grid_name_len];
613 char lon_var_name[4 + grid_name_len];
614 char rnk_var_name[4 + grid_name_len];
615 char cmk_var_name[4 + grid_name_len];
616 char gid_var_name[4 + grid_name_len];
617 char vcmk_var_name[5 + grid_name_len];
618 char vgid_var_name[5 + grid_name_len];
619 char ecmk_var_name[5 + grid_name_len];
620 char egid_var_name[5 + grid_name_len];
621 char const * unit_att =
"units";
622 char const * coord_unit =
"degree";
624 snprintf(nv_dim_name, 3 + grid_name_len,
"nv_%s", grid_name);
625 snprintf(nc_dim_name, 3 + grid_name_len,
"nc_%s", grid_name);
627 snprintf(cla_var_name, 4 + grid_name_len,
"%s.cla", grid_name);
628 snprintf(clo_var_name, 4 + grid_name_len,
"%s.clo", grid_name);
629 snprintf(lat_var_name, 4 + grid_name_len,
"%s.lat", grid_name);
630 snprintf(lon_var_name, 4 + grid_name_len,
"%s.lon", grid_name);
631 snprintf(rnk_var_name, 4 + grid_name_len,
"%s.rnk", grid_name);
632 snprintf(cmk_var_name, 4 + grid_name_len,
"%s.cmk", grid_name);
633 snprintf(gid_var_name, 4 + grid_name_len,
"%s.gid", grid_name);
634 snprintf(vcmk_var_name, 5 + grid_name_len,
"%s.vcmk", grid_name);
635 snprintf(vgid_var_name, 5 + grid_name_len,
"%s.vgid", grid_name);
636 snprintf(ecmk_var_name, 5 + grid_name_len,
"%s.ecmk", grid_name);
637 snprintf(egid_var_name, 5 + grid_name_len,
"%s.egid", grid_name);
644 yac_nc_create(filename, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
652 def_dim(filename, ncid, nv_dim_name, (
size_t)num_vertices_per_cell, file_is_new);
657 int corner_dims[2] = {nc_dim_id, nv_dim_id};
658 int cell_dims[1] = {nc_dim_id};
660 filename, ncid, cla_var_name, NC_DOUBLE, 2, corner_dims,
661 unit_att, coord_unit, file_is_new);
663 filename, ncid, clo_var_name, NC_DOUBLE, 2, corner_dims,
664 unit_att, coord_unit, file_is_new);
665 if (cell_center_coords_avaiable) {
667 filename, ncid, lat_var_name, NC_DOUBLE, 1, cell_dims,
668 unit_att, coord_unit, file_is_new);
670 filename, ncid, lon_var_name, NC_DOUBLE, 1, cell_dims,
671 unit_att, coord_unit, file_is_new);
673 if (cell_global_ids_available)
675 filename, ncid, gid_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
676 if (core_cell_mask_available)
678 filename, ncid, cmk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
679 if (vertex_global_ids_available)
681 filename, ncid, vgid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
682 if (core_vertex_mask_available)
684 filename, ncid, vcmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
685 if (edge_global_ids_available)
687 filename, ncid, egid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
688 if (core_edge_mask_available)
690 filename, ncid, ecmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
692 filename, ncid, rnk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
694 time_t now = time(NULL);
695 char str_now_UTC[32];
697 str_now_UTC,
sizeof(str_now_UTC),
"%Y-%m-%dT%H:%M:%SZ",
701 char const * created_by =
"Created by YAC";
709 nc_put_att_text(ncid, NC_GLOBAL,
"title", strlen(created_by), created_by));
711 nc_put_att_text(ncid, NC_GLOBAL,
"description", strlen(created_by), created_by));
715 nc_put_att_text(ncid, NC_GLOBAL,
"timeStamp", strlen(str_now_UTC), str_now_UTC));
748 struct yac_basic_grid * grid,
char const * filename, MPI_Comm comm) {
750#ifndef YAC_NETCDF_ENABLED
757 "ERROR(yac_basic_grid_to_file_parallel): "
758 "YAC is built without the NetCDF support");
761 int comm_rank, comm_size;
766 int filename_len = (int)strlen(filename) + 1;
767 yac_mpi_call(MPI_Bcast(&filename_len, 1, MPI_INT, 0, comm), comm);
768 char * filename_buffer =
769 xmalloc((
size_t)filename_len *
sizeof(*filename_buffer));
770 if (comm_rank == 0) strcpy(filename_buffer, filename);
772 MPI_Bcast(filename_buffer, filename_len, MPI_CHAR, 0, comm), comm);
775 !strcmp(filename, filename_buffer),
776 "inconsistent filename (\"%s\" on rank 0 != \"%s\" on rank %d)",
777 filename_buffer, filename, comm_rank);
778 free(filename_buffer);
784 ((cell_field != NULL) &&
789 uint64_t local_cell_count = (uint64_t)grid->data.num_cells;
790 uint64_t * global_cell_counts =
791 xmalloc((
size_t)comm_size *
sizeof(*global_cell_counts));
792 int max_num_vertices_per_cell = 0;
793 int cell_center_coords_avaiable =
794 (
grid_data->num_cells == 0) || (cell_center_coords != NULL);
795 int cell_global_ids_available =
797 int core_cell_mask_available =
799 int vertex_global_ids_available =
801 int core_vertex_mask_available =
803 int edge_global_ids_available =
805 int core_edge_mask_available =
808 for (
size_t i = 0; i < grid->data.num_cells; ++i)
809 if (grid->data.num_vertices_per_cell[i] > max_num_vertices_per_cell)
810 max_num_vertices_per_cell = grid->data.num_vertices_per_cell[i];
814 &local_cell_count, 1, MPI_UINT64_T,
815 global_cell_counts, 1, MPI_UINT64_T, comm), comm);
818 MPI_IN_PLACE, &max_num_vertices_per_cell, 1, MPI_INT, MPI_MAX, comm),
820 int ints[7] = {cell_center_coords_avaiable,
821 cell_global_ids_available,
822 core_cell_mask_available,
823 vertex_global_ids_available,
824 core_vertex_mask_available,
825 edge_global_ids_available,
826 core_edge_mask_available};
829 MPI_IN_PLACE, ints,
sizeof(ints)/
sizeof(ints[0]),
830 MPI_INT, MPI_MIN, comm), comm);
831 cell_center_coords_avaiable = ints[0];
832 cell_global_ids_available = ints[1];
833 core_cell_mask_available = ints[2];
834 vertex_global_ids_available = ints[3];
835 core_vertex_mask_available = ints[4];
836 edge_global_ids_available = ints[5];
837 core_edge_mask_available = ints[6];
839 size_t global_cell_count = 0;
840 for (
int i = 0; i < comm_size; ++i)
841 global_cell_count += (
size_t)(global_cell_counts[i]);
843 YAC_ASSERT_F(global_cell_count > 0,
"grid \"%s\" has no cells", grid->name);
848 filename, grid->name, global_cell_count, max_num_vertices_per_cell,
849 cell_center_coords_avaiable,
850 cell_global_ids_available, core_cell_mask_available,
851 vertex_global_ids_available, core_vertex_mask_available,
852 edge_global_ids_available, core_edge_mask_available);
861 size_t recv_count = 0;
862 size_t io_start_idx = SIZE_MAX;
867 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
868 if (io_ranks[io_rank_idx] == comm_rank)
break;
872 ((
long long)(io_rank_idx) * (
long long)global_cell_count)/
873 (
long long)num_io_ranks);
876 ((
long long)(io_rank_idx + 1) * (
long long)global_cell_count)/
877 (
long long)num_io_ranks - (
long long)io_start_idx);
881 struct Xt_com_pos * com_pos_buffer =
882 xmalloc(5 * (
size_t)comm_size *
sizeof(*com_pos_buffer));
883 struct Xt_com_pos * cell_src_com = com_pos_buffer;
884 struct Xt_com_pos * cell_dst_com = com_pos_buffer + (size_t)comm_size;
885 struct Xt_com_pos * vertex_src_com = com_pos_buffer + 2 * (size_t)comm_size;
886 struct Xt_com_pos * vertex_dst_com = com_pos_buffer + 3 * (size_t)comm_size;
887 struct Xt_com_pos * edge_src_com = com_pos_buffer + 4 * (size_t)comm_size;
888 struct Xt_com_pos * edge_dst_com = vertex_dst_com;
889 int num_src_msg = 0, num_dst_msg = 0;
890 int * transfer_pos_buffer =
892 (
size_t)(2 * max_num_vertices_per_cell + 1) *
893 (grid->data.num_cells + recv_count) *
sizeof(*transfer_pos_buffer));
894 int * cell_send_pos = transfer_pos_buffer;
895 int * cell_recv_pos = transfer_pos_buffer + grid->data.num_cells;
896 int * vertex_send_pos =
897 transfer_pos_buffer + grid->data.num_cells + recv_count;
898 int * vertex_recv_pos =
899 transfer_pos_buffer + grid->data.num_cells + recv_count +
900 (size_t)max_num_vertices_per_cell * grid->data.num_cells;
901 int * edge_send_pos =
902 transfer_pos_buffer + grid->data.num_cells + recv_count +
903 (size_t)max_num_vertices_per_cell * grid->data.num_cells +
904 (
size_t)max_num_vertices_per_cell * recv_count;
906 for (
size_t i = 0; i < grid->data.num_cells; ++i) {
909 grid->data.cell_to_vertex + grid->data.cell_to_vertex_offsets[i];
910 size_t * cell_to_edge =
911 grid->data.cell_to_edge + grid->data.cell_to_edge_offsets[i];
912 int num_vertices = grid->data.num_vertices_per_cell[i];
914 cell_send_pos[i] = (int)i;
915 for (
int j = 0; j < num_vertices; ++j)
916 vertex_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] =
918 for (
int j = num_vertices; j < max_num_vertices_per_cell; ++j)
919 vertex_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] = 0;
920 for (
int j = 0; j < num_vertices; ++j)
921 edge_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] =
923 for (
int j = num_vertices; j < max_num_vertices_per_cell; ++j)
924 edge_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] = 0;
927 for (
size_t i = 0, k = 0; i < recv_count; ++i) {
928 cell_recv_pos[i] = (int)i;
929 for (
int j = 0; j < max_num_vertices_per_cell; ++j, ++k)
930 vertex_recv_pos[k] = k;
933 size_t io_end_idx = 0;
934 size_t global_count_accu = 0;
935 for (
int io_rank_idx = 0, curr_rank = 0; io_rank_idx < num_io_ranks;
938 int curr_io_rank = io_ranks[io_rank_idx];
939 size_t io_start_idx = io_end_idx;
942 ((
long long)(io_rank_idx + 1) * (
long long)global_cell_count)/
943 (
long long)num_io_ranks);
944 size_t io_size = io_end_idx - io_start_idx;
945 size_t curr_recv_size = 0;
947 while(global_count_accu < io_end_idx) {
951 (global_count_accu + global_cell_counts[curr_rank]) -
952 (io_start_idx + curr_recv_size), io_size - curr_recv_size);
954 if (curr_rank == comm_rank) {
955 cell_src_com[num_src_msg].transfer_pos = cell_send_pos;
956 cell_src_com[num_src_msg].num_transfer_pos = (int)count;
957 cell_src_com[num_src_msg].rank = curr_io_rank;
958 cell_send_pos += count;
960 vertex_src_com[num_src_msg].transfer_pos = vertex_send_pos;
961 vertex_src_com[num_src_msg].num_transfer_pos =
962 (int)count * max_num_vertices_per_cell;
963 vertex_src_com[num_src_msg].rank = curr_io_rank;
965 count * (size_t)max_num_vertices_per_cell;
967 edge_src_com[num_src_msg].transfer_pos = edge_send_pos;
968 edge_src_com[num_src_msg].num_transfer_pos =
969 (int)count * max_num_vertices_per_cell;
970 edge_src_com[num_src_msg].rank = curr_io_rank;
972 count * (size_t)max_num_vertices_per_cell;
977 if (curr_io_rank == comm_rank) {
978 cell_dst_com[num_dst_msg].transfer_pos = cell_recv_pos;
979 cell_dst_com[num_dst_msg].num_transfer_pos = (int)count;
980 cell_dst_com[num_dst_msg].rank = curr_rank;
981 cell_recv_pos += count;
983 vertex_dst_com[num_dst_msg].transfer_pos = vertex_recv_pos;
984 vertex_dst_com[num_dst_msg].num_transfer_pos =
985 (int)count * max_num_vertices_per_cell;
986 vertex_dst_com[num_dst_msg].rank = curr_rank;
987 vertex_recv_pos += count * (size_t)max_num_vertices_per_cell;
992 if ((global_count_accu + global_cell_counts[curr_rank]) <=
994 global_count_accu += global_cell_counts[curr_rank];
998 curr_recv_size += count;
1000 if (curr_recv_size >= io_size)
break;
1004 free(global_cell_counts);
1008 size_t start[2], count[2];
1012 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
1013 if (io_ranks[io_rank_idx] == comm_rank)
break;
1015 start[0] = io_start_idx;
1017 count[0] = recv_count;
1018 count[1] = max_num_vertices_per_cell;
1020 yac_nc_open(filename, NC_WRITE | NC_SHARE, &ncid);
1028 (
size_t)max_num_vertices_per_cell * recv_count *
1036 xt_xmap_intersection_pos_new(
1037 num_src_msg, cell_src_com, num_dst_msg, cell_dst_com, comm);
1039 Xt_redist cell_redist_int = xt_redist_p2p_new(cell_xmap, MPI_INT);
1042 int * num_vertices_per_cell =
1043 xmalloc(recv_count *
sizeof(*num_vertices_per_cell));
1044 xt_redist_s_exchange1(
1045 cell_redist_int, grid->data.num_vertices_per_cell, num_vertices_per_cell);
1048 if (cell_center_coords_avaiable) {
1051 double * send_buffer_dble =
1052 xmalloc(2 * grid->data.num_cells *
sizeof(*send_buffer_dble));;
1053 double * send_buffer_lon = send_buffer_dble;
1054 double * send_buffer_lat = send_buffer_dble + grid->data.num_cells;
1055 for (
size_t i = 0; i < grid->data.num_cells; ++i) {
1057 cell_center_coords[i], send_buffer_lon + i, send_buffer_lat + i);
1058 send_buffer_lon[i] /=
YAC_RAD;
1059 send_buffer_lat[i] /=
YAC_RAD;
1063 Xt_redist cell_redist_dble = xt_redist_p2p_new(cell_xmap, MPI_DOUBLE);
1064 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lon,
recv_buffer);
1066 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lat,
recv_buffer);
1068 xt_redist_delete(cell_redist_dble);
1069 free(send_buffer_dble);
1072 int * cell_send_buffer_int =
1073 xmalloc(grid->data.num_cells *
sizeof(*cell_send_buffer_int));
1078 for (
size_t i = 0; i < grid->data.num_cells; ++i)
1079 cell_send_buffer_int[i] = comm_rank;
1082 xt_redist_s_exchange1(cell_redist_int, cell_send_buffer_int,
recv_buffer);
1087 if (core_cell_mask_available) {
1090 xt_redist_s_exchange1(
1091 cell_redist_int, grid->data.core_cell_mask,
recv_buffer);
1096 if (cell_global_ids_available) {
1099 for (
size_t i = 0; i < grid->data.num_cells; ++i)
1100 cell_send_buffer_int[i] = (
int)(grid->data.cell_ids[i]);
1103 xt_redist_s_exchange1(
1104 cell_redist_int, cell_send_buffer_int,
recv_buffer);
1108 xt_redist_delete(cell_redist_int);
1109 free(cell_send_buffer_int);
1111 xt_xmap_delete(cell_xmap);
1117 Xt_xmap vertex_xmap =
1118 xt_xmap_intersection_pos_new(
1119 num_src_msg, vertex_src_com, num_dst_msg, vertex_dst_com, comm);
1124 double * send_buffer_dble =
1125 xmalloc(2 * grid->data.num_vertices *
sizeof(*send_buffer_dble));
1126 double * send_buffer_lon = send_buffer_dble;
1127 double * send_buffer_lat = send_buffer_dble + grid->data.num_vertices;
1128 for (
size_t i = 0; i < grid->data.num_vertices; ++i) {
1130 grid->data.vertex_coordinates[i],
1131 send_buffer_lon + i, send_buffer_lat + i);
1132 send_buffer_lon[i] /=
YAC_RAD;
1133 send_buffer_lat[i] /=
YAC_RAD;
1137 Xt_redist vertex_redist_dble = xt_redist_p2p_new(vertex_xmap, MPI_DOUBLE);
1138 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lon,
recv_buffer);
1139 for (
size_t i = 0, k = 0; i < recv_count;
1140 ++i, k += (size_t)max_num_vertices_per_cell)
1141 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1142 j < (size_t)max_num_vertices_per_cell; ++j)
1145 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lat,
recv_buffer);
1146 free(send_buffer_dble);
1147 for (
size_t i = 0, k = 0; i < recv_count;
1148 ++i, k += (size_t)max_num_vertices_per_cell)
1149 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1150 j < (size_t)max_num_vertices_per_cell; ++j)
1153 xt_redist_delete(vertex_redist_dble);
1156 Xt_redist vertex_redist_int = xt_redist_p2p_new(vertex_xmap, MPI_INT);
1157 int * vertex_send_buffer_int =
1158 xmalloc(grid->data.num_vertices *
sizeof(*vertex_send_buffer_int));
1161 if (core_vertex_mask_available) {
1164 xt_redist_s_exchange1(
1165 vertex_redist_int, grid->data.core_vertex_mask,
recv_buffer);
1166 for (
size_t i = 0, k = 0; i < recv_count;
1167 ++i, k += (size_t)max_num_vertices_per_cell)
1168 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1169 j < (size_t)max_num_vertices_per_cell; ++j)
1175 if (vertex_global_ids_available) {
1178 for (
size_t i = 0; i < grid->data.num_vertices; ++i)
1179 vertex_send_buffer_int[i] = (
int)(grid->data.vertex_ids[i]);
1182 xt_redist_s_exchange1(
1183 vertex_redist_int, vertex_send_buffer_int,
recv_buffer);
1184 for (
size_t i = 0, k = 0; i < recv_count;
1185 ++i, k += (size_t)max_num_vertices_per_cell)
1186 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1187 j < (size_t)max_num_vertices_per_cell; ++j)
1192 free(vertex_send_buffer_int);
1193 xt_redist_delete(vertex_redist_int);
1195 xt_xmap_delete(vertex_xmap);
1201 if (core_edge_mask_available || edge_global_ids_available) {
1204 xt_xmap_intersection_pos_new(
1205 num_src_msg, edge_src_com, num_dst_msg, edge_dst_com, comm);
1207 Xt_redist edge_redist_int = xt_redist_p2p_new(edge_xmap, MPI_INT);
1208 int * edge_send_buffer_int =
1209 xmalloc(grid->data.num_edges *
sizeof(*edge_send_buffer_int));
1212 if (core_edge_mask_available) {
1215 xt_redist_s_exchange1(
1216 edge_redist_int, grid->data.core_edge_mask,
recv_buffer);
1217 for (
size_t i = 0, k = 0; i < recv_count;
1218 ++i, k += (size_t)max_num_vertices_per_cell)
1219 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1220 j < (size_t)max_num_vertices_per_cell; ++j)
1226 if (edge_global_ids_available) {
1229 for (
size_t i = 0; i < grid->data.num_edges; ++i)
1230 edge_send_buffer_int[i] = (
int)(grid->data.edge_ids[i]);
1233 xt_redist_s_exchange1(
1234 edge_redist_int, edge_send_buffer_int,
recv_buffer);
1235 for (
size_t i = 0, k = 0; i < recv_count;
1236 ++i, k += (size_t)max_num_vertices_per_cell)
1237 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1238 j < (size_t)max_num_vertices_per_cell; ++j)
1243 free(edge_send_buffer_int);
1244 xt_redist_delete(edge_redist_int);
1246 xt_xmap_delete(edge_xmap);
1252 free(num_vertices_per_cell);
1254 free(com_pos_buffer);
1255 free(transfer_pos_buffer);