624 char const * filename,
char const * grid_name,
size_t num_cells,
625 int num_vertices_per_cell,
int cell_center_coords_avaiable,
626 int cell_global_ids_available,
int core_cell_mask_available,
627 int vertex_global_ids_available,
int core_vertex_mask_available,
628 int edge_global_ids_available,
int core_edge_mask_available) {
630 size_t grid_name_len = strlen(grid_name) + 1;
632 char nv_dim_name[3 + grid_name_len];
633 char nc_dim_name[3 + grid_name_len];
635 char cla_var_name[4 + grid_name_len];
636 char clo_var_name[4 + grid_name_len];
637 char lat_var_name[4 + grid_name_len];
638 char lon_var_name[4 + grid_name_len];
639 char rnk_var_name[4 + grid_name_len];
640 char cmk_var_name[4 + grid_name_len];
641 char gid_var_name[4 + grid_name_len];
642 char vcmk_var_name[5 + grid_name_len];
643 char vgid_var_name[5 + grid_name_len];
644 char ecmk_var_name[5 + grid_name_len];
645 char egid_var_name[5 + grid_name_len];
646 char const * unit_att =
"units";
647 char const * coord_unit =
"degree";
649 snprintf(nv_dim_name, 3 + grid_name_len,
"nv_%s", grid_name);
650 snprintf(nc_dim_name, 3 + grid_name_len,
"nc_%s", grid_name);
652 snprintf(cla_var_name, 4 + grid_name_len,
"%s.cla", grid_name);
653 snprintf(clo_var_name, 4 + grid_name_len,
"%s.clo", grid_name);
654 snprintf(lat_var_name, 4 + grid_name_len,
"%s.lat", grid_name);
655 snprintf(lon_var_name, 4 + grid_name_len,
"%s.lon", grid_name);
656 snprintf(rnk_var_name, 4 + grid_name_len,
"%s.rnk", grid_name);
657 snprintf(cmk_var_name, 4 + grid_name_len,
"%s.cmk", grid_name);
658 snprintf(gid_var_name, 4 + grid_name_len,
"%s.gid", grid_name);
659 snprintf(vcmk_var_name, 5 + grid_name_len,
"%s.vcmk", grid_name);
660 snprintf(vgid_var_name, 5 + grid_name_len,
"%s.vgid", grid_name);
661 snprintf(ecmk_var_name, 5 + grid_name_len,
"%s.ecmk", grid_name);
662 snprintf(egid_var_name, 5 + grid_name_len,
"%s.egid", grid_name);
669 yac_nc_create(filename, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
677 def_dim(filename, ncid, nv_dim_name, (
size_t)num_vertices_per_cell, file_is_new);
679 def_dim(filename, ncid, nc_dim_name, (
size_t)num_cells, file_is_new);
682 int corner_dims[2] = {nc_dim_id, nv_dim_id};
683 int cell_dims[1] = {nc_dim_id};
685 filename, ncid, cla_var_name, NC_DOUBLE, 2, corner_dims,
686 unit_att, coord_unit, file_is_new);
688 filename, ncid, clo_var_name, NC_DOUBLE, 2, corner_dims,
689 unit_att, coord_unit, file_is_new);
690 if (cell_center_coords_avaiable) {
692 filename, ncid, lat_var_name, NC_DOUBLE, 1, cell_dims,
693 unit_att, coord_unit, file_is_new);
695 filename, ncid, lon_var_name, NC_DOUBLE, 1, cell_dims,
696 unit_att, coord_unit, file_is_new);
698 if (cell_global_ids_available)
700 filename, ncid, gid_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
701 if (core_cell_mask_available)
703 filename, ncid, cmk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
704 if (vertex_global_ids_available)
706 filename, ncid, vgid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
707 if (core_vertex_mask_available)
709 filename, ncid, vcmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
710 if (edge_global_ids_available)
712 filename, ncid, egid_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
713 if (core_edge_mask_available)
715 filename, ncid, ecmk_var_name, NC_INT, 2, corner_dims, NULL, NULL, file_is_new);
717 filename, ncid, rnk_var_name, NC_INT, 1, cell_dims, NULL, NULL, file_is_new);
719 time_t now = time(NULL);
720 char str_now_UTC[32];
722 str_now_UTC,
sizeof(str_now_UTC),
"%Y-%m-%dT%H:%M:%SZ",
725 char const * created_by =
"Created by YAC";
730 nc_put_att_text(ncid, NC_GLOBAL,
"title", strlen(created_by), created_by));
732 nc_put_att_text(ncid, NC_GLOBAL,
"description", strlen(created_by), created_by));
736 nc_put_att_text(ncid, NC_GLOBAL,
"timeStamp", strlen(str_now_UTC), str_now_UTC));
769 struct yac_basic_grid * grid,
char const * filename, MPI_Comm comm) {
771#ifndef YAC_NETCDF_ENABLED
778 "ERROR(yac_basic_grid_to_file_parallel): "
779 "YAC is built without the NetCDF support");
782 int comm_rank, comm_size;
787 int filename_len = (int)strlen(filename) + 1;
788 yac_mpi_call(MPI_Bcast(&filename_len, 1, MPI_INT, 0, comm), comm);
789 char * filename_buffer =
790 xmalloc((
size_t)filename_len *
sizeof(*filename_buffer));
791 if (comm_rank == 0) strcpy(filename_buffer, filename);
793 MPI_Bcast(filename_buffer, filename_len, MPI_CHAR, 0, comm), comm);
796 !strcmp(filename, filename_buffer),
797 "ERROR(yac_basic_grid_to_file_parallel): "
798 "inconsistent filename (\"%s\" on rank 0 != \"%s\" on rank %d)",
799 filename_buffer, filename, comm_rank);
800 free(filename_buffer);
806 ((cell_field != NULL) &&
812 uint64_t * global_cell_counts =
813 xmalloc((
size_t)comm_size *
sizeof(*global_cell_counts));
814 int max_num_vertices_per_cell = 0;
815 int cell_center_coords_avaiable =
816 (grid_data->
num_cells == 0) || (cell_center_coords != NULL);
817 int cell_global_ids_available =
819 int core_cell_mask_available =
821 int vertex_global_ids_available =
823 int core_vertex_mask_available =
825 int edge_global_ids_available =
827 int core_edge_mask_available =
836 &local_cell_count, 1, MPI_UINT64_T,
837 global_cell_counts, 1, MPI_UINT64_T, comm), comm);
840 MPI_IN_PLACE, &max_num_vertices_per_cell, 1, MPI_INT, MPI_MAX, comm),
842 int ints[7] = {cell_center_coords_avaiable,
843 cell_global_ids_available,
844 core_cell_mask_available,
845 vertex_global_ids_available,
846 core_vertex_mask_available,
847 edge_global_ids_available,
848 core_edge_mask_available};
851 MPI_IN_PLACE, ints,
sizeof(ints)/
sizeof(ints[0]),
852 MPI_INT, MPI_MIN, comm), comm);
853 cell_center_coords_avaiable = ints[0];
854 cell_global_ids_available = ints[1];
855 core_cell_mask_available = ints[2];
856 vertex_global_ids_available = ints[3];
857 core_vertex_mask_available = ints[4];
858 edge_global_ids_available = ints[5];
859 core_edge_mask_available = ints[6];
861 size_t global_cell_count = 0;
862 for (
int i = 0; i < comm_size; ++i)
863 global_cell_count += (
size_t)(global_cell_counts[i]);
866 global_cell_count > 0,
867 "ERROR(yac_basic_grid_to_file_parallel): grid \"%s\" has no cells",
873 filename, grid->
name, global_cell_count, max_num_vertices_per_cell,
874 cell_center_coords_avaiable,
875 cell_global_ids_available, core_cell_mask_available,
876 vertex_global_ids_available, core_vertex_mask_available,
877 edge_global_ids_available, core_edge_mask_available);
886 size_t recv_count = 0;
887 size_t io_start_idx = SIZE_MAX;
892 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
893 if (io_ranks[io_rank_idx] == comm_rank)
break;
897 ((
long long)(io_rank_idx) * (
long long)global_cell_count)/
898 (
long long)num_io_ranks);
901 ((
long long)(io_rank_idx + 1) * (
long long)global_cell_count)/
902 (
long long)num_io_ranks - (
long long)io_start_idx);
906 struct Xt_com_pos * com_pos_buffer =
907 xmalloc(5 * (
size_t)comm_size *
sizeof(*com_pos_buffer));
908 struct Xt_com_pos * cell_src_com = com_pos_buffer;
909 struct Xt_com_pos * cell_dst_com = com_pos_buffer + (size_t)comm_size;
910 struct Xt_com_pos * vertex_src_com = com_pos_buffer + 2 * (size_t)comm_size;
911 struct Xt_com_pos * vertex_dst_com = com_pos_buffer + 3 * (size_t)comm_size;
912 struct Xt_com_pos * edge_src_com = com_pos_buffer + 4 * (size_t)comm_size;
913 struct Xt_com_pos * edge_dst_com = vertex_dst_com;
914 int num_src_msg = 0, num_dst_msg = 0;
915 int * transfer_pos_buffer =
917 (
size_t)(2 * max_num_vertices_per_cell + 1) *
918 (grid->
data.
num_cells + recv_count) *
sizeof(*transfer_pos_buffer));
919 int * cell_send_pos = transfer_pos_buffer;
920 int * cell_recv_pos = transfer_pos_buffer + grid->
data.
num_cells;
921 int * vertex_send_pos =
923 int * vertex_recv_pos =
926 int * edge_send_pos =
929 (
size_t)max_num_vertices_per_cell * recv_count;
933 size_t * cell_to_vertex =
935 size_t * cell_to_edge =
939 cell_send_pos[i] = (int)i;
940 for (
int j = 0; j < num_vertices; ++j)
941 vertex_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] =
943 for (
int j = num_vertices; j < max_num_vertices_per_cell; ++j)
944 vertex_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] = 0;
945 for (
int j = 0; j < num_vertices; ++j)
946 edge_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] =
948 for (
int j = num_vertices; j < max_num_vertices_per_cell; ++j)
949 edge_send_pos[i * (
size_t)max_num_vertices_per_cell + (size_t)j] = 0;
952 for (
size_t i = 0, k = 0; i < recv_count; ++i) {
953 cell_recv_pos[i] = (int)i;
954 for (
int j = 0; j < max_num_vertices_per_cell; ++j, ++k)
955 vertex_recv_pos[k] = k;
958 size_t io_end_idx = 0;
959 size_t global_count_accu = 0;
960 for (
int io_rank_idx = 0, curr_rank = 0; io_rank_idx < num_io_ranks;
963 int curr_io_rank = io_ranks[io_rank_idx];
964 size_t io_start_idx = io_end_idx;
967 ((
long long)(io_rank_idx + 1) * (
long long)global_cell_count)/
968 (
long long)num_io_ranks);
969 size_t io_size = io_end_idx - io_start_idx;
970 size_t curr_recv_size = 0;
972 while(global_count_accu < io_end_idx) {
976 (global_count_accu + global_cell_counts[curr_rank]) -
977 (io_start_idx + curr_recv_size), io_size - curr_recv_size);
979 if (curr_rank == comm_rank) {
980 cell_src_com[num_src_msg].transfer_pos = cell_send_pos;
981 cell_src_com[num_src_msg].num_transfer_pos = (int)count;
982 cell_src_com[num_src_msg].rank = curr_io_rank;
983 cell_send_pos += count;
985 vertex_src_com[num_src_msg].transfer_pos = vertex_send_pos;
986 vertex_src_com[num_src_msg].num_transfer_pos =
987 (int)count * max_num_vertices_per_cell;
988 vertex_src_com[num_src_msg].rank = curr_io_rank;
990 count * (size_t)max_num_vertices_per_cell;
992 edge_src_com[num_src_msg].transfer_pos = edge_send_pos;
993 edge_src_com[num_src_msg].num_transfer_pos =
994 (int)count * max_num_vertices_per_cell;
995 edge_src_com[num_src_msg].rank = curr_io_rank;
997 count * (size_t)max_num_vertices_per_cell;
1002 if (curr_io_rank == comm_rank) {
1003 cell_dst_com[num_dst_msg].transfer_pos = cell_recv_pos;
1004 cell_dst_com[num_dst_msg].num_transfer_pos = (int)count;
1005 cell_dst_com[num_dst_msg].rank = curr_rank;
1006 cell_recv_pos += count;
1008 vertex_dst_com[num_dst_msg].transfer_pos = vertex_recv_pos;
1009 vertex_dst_com[num_dst_msg].num_transfer_pos =
1010 (int)count * max_num_vertices_per_cell;
1011 vertex_dst_com[num_dst_msg].rank = curr_rank;
1012 vertex_recv_pos += count * (size_t)max_num_vertices_per_cell;
1017 if ((global_count_accu + global_cell_counts[curr_rank]) <=
1019 global_count_accu += global_cell_counts[curr_rank];
1023 curr_recv_size += count;
1025 if (curr_recv_size >= io_size)
break;
1029 free(global_cell_counts);
1033 size_t start[2], count[2];
1037 for (io_rank_idx = 0; io_rank_idx < num_io_ranks; ++io_rank_idx)
1038 if (io_ranks[io_rank_idx] == comm_rank)
break;
1040 start[0] = io_start_idx;
1042 count[0] = recv_count;
1043 count[1] = max_num_vertices_per_cell;
1045 yac_nc_open(filename, NC_WRITE | NC_SHARE, &ncid);
1051 void * recv_buffer =
1053 (
size_t)max_num_vertices_per_cell * recv_count *
1061 xt_xmap_intersection_pos_new(
1062 num_src_msg, cell_src_com, num_dst_msg, cell_dst_com, comm);
1064 Xt_redist cell_redist_int = xt_redist_p2p_new(cell_xmap, MPI_INT);
1067 int * num_vertices_per_cell =
1068 xmalloc(recv_count *
sizeof(*num_vertices_per_cell));
1069 xt_redist_s_exchange1(
1073 if (cell_center_coords_avaiable) {
1076 double * send_buffer_dble =
1078 double * send_buffer_lon = send_buffer_dble;
1079 double * send_buffer_lat = send_buffer_dble + grid->
data.
num_cells;
1082 cell_center_coords[i], send_buffer_lon + i, send_buffer_lat + i);
1083 send_buffer_lon[i] /=
YAC_RAD;
1084 send_buffer_lat[i] /=
YAC_RAD;
1088 Xt_redist cell_redist_dble = xt_redist_p2p_new(cell_xmap, MPI_DOUBLE);
1089 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lon, recv_buffer);
1090 put_vara(ncid, grid->
name,
"lon", start, count, recv_buffer);
1091 xt_redist_s_exchange1(cell_redist_dble, send_buffer_lat, recv_buffer);
1092 put_vara(ncid, grid->
name,
"lat", start, count, recv_buffer);
1093 xt_redist_delete(cell_redist_dble);
1094 free(send_buffer_dble);
1097 int * cell_send_buffer_int =
1104 cell_send_buffer_int[i] = comm_rank;
1107 xt_redist_s_exchange1(cell_redist_int, cell_send_buffer_int, recv_buffer);
1108 put_vara(ncid, grid->
name,
"rnk", start, count, recv_buffer);
1112 if (core_cell_mask_available) {
1115 xt_redist_s_exchange1(
1117 put_vara(ncid, grid->
name,
"cmk", start, count, recv_buffer);
1121 if (cell_global_ids_available) {
1125 cell_send_buffer_int[i] = (
int)(grid->
data.
cell_ids[i]);
1128 xt_redist_s_exchange1(
1129 cell_redist_int, cell_send_buffer_int, recv_buffer);
1130 put_vara(ncid, grid->
name,
"gid", start, count, recv_buffer);
1133 xt_redist_delete(cell_redist_int);
1134 free(cell_send_buffer_int);
1136 xt_xmap_delete(cell_xmap);
1142 Xt_xmap vertex_xmap =
1143 xt_xmap_intersection_pos_new(
1144 num_src_msg, vertex_src_com, num_dst_msg, vertex_dst_com, comm);
1149 double * send_buffer_dble =
1151 double * send_buffer_lon = send_buffer_dble;
1156 send_buffer_lon + i, send_buffer_lat + i);
1157 send_buffer_lon[i] /=
YAC_RAD;
1158 send_buffer_lat[i] /=
YAC_RAD;
1162 Xt_redist vertex_redist_dble = xt_redist_p2p_new(vertex_xmap, MPI_DOUBLE);
1163 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lon, recv_buffer);
1164 for (
size_t i = 0, k = 0; i < recv_count;
1165 ++i, k += (size_t)max_num_vertices_per_cell)
1166 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1167 j < (size_t)max_num_vertices_per_cell; ++j)
1168 ((
double*)recv_buffer)[k+j] = DBL_MAX;
1169 put_vara(ncid, grid->
name,
"clo", start, count, recv_buffer);
1170 xt_redist_s_exchange1(vertex_redist_dble, send_buffer_lat, recv_buffer);
1171 free(send_buffer_dble);
1172 for (
size_t i = 0, k = 0; i < recv_count;
1173 ++i, k += (size_t)max_num_vertices_per_cell)
1174 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1175 j < (size_t)max_num_vertices_per_cell; ++j)
1176 ((
double*)recv_buffer)[k+j] = DBL_MAX;
1177 put_vara(ncid, grid->
name,
"cla", start, count, recv_buffer);
1178 xt_redist_delete(vertex_redist_dble);
1181 Xt_redist vertex_redist_int = xt_redist_p2p_new(vertex_xmap, MPI_INT);
1182 int * vertex_send_buffer_int =
1186 if (core_vertex_mask_available) {
1189 xt_redist_s_exchange1(
1191 for (
size_t i = 0, k = 0; i < recv_count;
1192 ++i, k += (size_t)max_num_vertices_per_cell)
1193 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1194 j < (size_t)max_num_vertices_per_cell; ++j)
1195 ((
int*)recv_buffer)[k+j] = INT_MAX;
1196 put_vara(ncid, grid->
name,
"vcmk", start, count, recv_buffer);
1200 if (vertex_global_ids_available) {
1207 xt_redist_s_exchange1(
1208 vertex_redist_int, vertex_send_buffer_int, recv_buffer);
1209 for (
size_t i = 0, k = 0; i < recv_count;
1210 ++i, k += (size_t)max_num_vertices_per_cell)
1211 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1212 j < (size_t)max_num_vertices_per_cell; ++j)
1213 ((
int*)recv_buffer)[k+j] = INT_MAX;
1214 put_vara(ncid, grid->
name,
"vgid", start, count, recv_buffer);
1217 free(vertex_send_buffer_int);
1218 xt_redist_delete(vertex_redist_int);
1220 xt_xmap_delete(vertex_xmap);
1226 if (core_edge_mask_available || edge_global_ids_available) {
1229 xt_xmap_intersection_pos_new(
1230 num_src_msg, edge_src_com, num_dst_msg, edge_dst_com, comm);
1232 Xt_redist edge_redist_int = xt_redist_p2p_new(edge_xmap, MPI_INT);
1233 int * edge_send_buffer_int =
1237 if (core_edge_mask_available) {
1240 xt_redist_s_exchange1(
1242 for (
size_t i = 0, k = 0; i < recv_count;
1243 ++i, k += (size_t)max_num_vertices_per_cell)
1244 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1245 j < (size_t)max_num_vertices_per_cell; ++j)
1246 ((
int*)recv_buffer)[k+j] = INT_MAX;
1247 put_vara(ncid, grid->
name,
"ecmk", start, count, recv_buffer);
1251 if (edge_global_ids_available) {
1255 edge_send_buffer_int[i] = (
int)(grid->
data.
edge_ids[i]);
1258 xt_redist_s_exchange1(
1259 edge_redist_int, edge_send_buffer_int, recv_buffer);
1260 for (
size_t i = 0, k = 0; i < recv_count;
1261 ++i, k += (size_t)max_num_vertices_per_cell)
1262 for (
size_t j = (
size_t)num_vertices_per_cell[i];
1263 j < (size_t)max_num_vertices_per_cell; ++j)
1264 ((
int*)recv_buffer)[k+j] = INT_MAX;
1265 put_vara(ncid, grid->
name,
"egid", start, count, recv_buffer);
1268 free(edge_send_buffer_int);
1269 xt_redist_delete(edge_redist_int);
1271 xt_xmap_delete(edge_xmap);
1277 free(num_vertices_per_cell);
1279 free(com_pos_buffer);
1280 free(transfer_pos_buffer);