This example simulates a whole model setup with two components (ocean, atmosphere) where rank 2 is shared by both components.
#define EXACT
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tests.h"
#define DUMMY_VALUE (-1337.0)
double * data;
size_t data_size;
int dummy_id;
};
static void generate_icon_grid(
int comm_rank, int comm_size, int comp_id, int * grid_id,
char const * grid_dir);
static void generate_cube_grid(
int comm_rank, int comm_size, int comp_id, int * grid_id,
static void check_results(
int main(
int argc,
char** argv) {
int global_rank, global_size;
MPI_Comm_rank(MPI_COMM_WORLD, &global_rank);
MPI_Comm_size(MPI_COMM_WORLD, &global_size);
if (global_size != 3) {
fprintf(stderr, "Wrong number of processes (should be 3)\n");
exit(EXIT_FAILURE);
}
if (argc != 3) {
PUT_ERR("ERROR: missing config/grid file directory");
xt_finalize();
MPI_Finalize();
return TEST_EXIT_CODE;
}
int comp_ids[2];
int num_comps;
if ((global_rank == 0) || (global_rank == 1)) {
num_comps = 1;
} else {
char const * comp_names[2] = {"comp1", "comp2"};
num_comps = 2;
}
int grid_ids[2];
if ((global_rank == 0) || (global_rank == 2))
generate_icon_grid(
(global_rank == 2), 2, comp_ids[0], &(grid_ids[0]),
&(in_field_configs[0]),
&(out_field_configs[0]), argv[2]);
if ((global_rank == 1) || (global_rank == 2))
generate_cube_grid(
(global_rank == 2), 2, comp_ids[global_rank == 2],
&(grid_ids[global_rank == 2]),
&(in_field_configs[global_rank == 2]),
&(out_field_configs[global_rank == 2]));
char * yaml_filename =
strcat(
strcpy(
malloc(strlen(argv[1]) + 32), argv[1]), "coupling_test2.yaml");
free(yaml_filename);
for (int t = 0; t < 100; ++t) {
if (global_rank == 0) {
{
int send_info, recv_info, err;
int id = out_field_configs[0].id;
int dummy_id = out_field_configs[0].dummy_id;
double *point_set_data[1];
double **collection_data[1] = {point_set_data};
point_set_data[0] = out_field_configs[0].data;
id, dummy_id, 1, collection_data, NULL,
&send_info, &recv_info, &err);
if (err) PUT_ERR("ERROR in yac_cexchange");
}
{
int send_info, recv_info, err;
int id = in_field_configs[0].id;
int dummy_id = in_field_configs[0].dummy_id;
double *collection_data[1] = {in_field_configs[0].data};
init_in_field_data(in_field_configs[0]);
dummy_id, id, 1, NULL, collection_data,
&send_info, &recv_info, &err);
check_results(in_field_configs[0], out_field_configs[0]);
if (err) PUT_ERR("ERROR in yac_cexchange");
}
} else if (global_rank == 1) {
{
int info, err;
int id = in_field_configs[0].id;
double *collection_data[1] = {in_field_configs[0].data};
init_in_field_data(in_field_configs[0]);
yac_cget(
id, 1, collection_data, &info, &err);
check_results(in_field_configs[0], out_field_configs[0]);
}
{
int info, err;
int id = out_field_configs[0].id;
double *point_set_data[1];
double **collection_data[1] = {point_set_data};
point_set_data[0] = out_field_configs[0].data;
yac_cput(
id, 1, collection_data, &info, &err);
}
} else {
for (int i = 0; i < 2; ++i) {
int out_info, in_info, err;
int out_id = out_field_configs[i].id;
int in_id = in_field_configs[i^1].id;
double *out_point_set_data[1];
double **out_collection_data[1] = {out_point_set_data};
out_point_set_data[0] = out_field_configs[i].data;
double *in_collection_data[1] = {in_field_configs[i^1].data};
init_in_field_data(in_field_configs[i^1]);
out_id, in_id, 1, out_collection_data, in_collection_data,
&out_info, &in_info, &err);
check_results(in_field_configs[i^1], out_field_configs[i^1]);
}
}
}
for (int i = 0; i < num_comps; ++i) {
free(out_field_configs[i].data);
free(in_field_configs[i].data);
}
return TEST_EXIT_CODE;
}
static void generate_icon_grid(
int comm_rank, int comm_size, int comp_id, int * grid_id,
char const * grid_dir) {
int nbr_vertices;
int nbr_cells;
int * num_vertices_per_cell;
int * cell_to_vertex;
double * x_vertices;
double * y_vertices;
double * x_cells;
double * y_cells;
int * cell_mask;
int * global_cell_id;
int * cell_core_mask;
int * global_corner_id;
int * corner_core_mask;
char * grid_filename =
strcat(
strcpy(
malloc(strlen(grid_dir) + 32), grid_dir), "icon_grid_0030_R02B03_G.nc");
grid_filename, &nbr_vertices, &nbr_cells, &num_vertices_per_cell,
&cell_to_vertex, &x_vertices, &y_vertices, &x_cells, &y_cells,
&global_cell_id, &cell_mask,
&cell_core_mask, &global_corner_id, &corner_core_mask,
comm_rank, comm_size);
free(grid_filename);
"icon", nbr_vertices, nbr_cells, num_vertices_per_cell,
x_vertices, y_vertices, cell_to_vertex, grid_id);
PUT_ERR("error in yac_cget_grid_size");
PUT_ERR("error in yac_cget_grid_size");
int corner_point_id, cell_point_id;
&corner_point_id);
&cell_point_id);
PUT_ERR("error in yac_cget_points_size");
PUT_ERR("error in yac_cget_points_size");
for (int i = 0; i < nbr_cells; ++i) cell_mask[i] = cell_mask[i] == 0;
"icon_to_cube_dummy", comp_id, &cell_point_id, 1, 1, "1",
"cube_to_icon_dummy", comp_id, &cell_point_id, 1, 1, "1",
out_config->data =
xmalloc(nbr_cells *
sizeof(*(out_config->data)));
for (int i = 0; i < nbr_cells; ++i)
out_config->data[i] =
(cell_core_mask[i])?
DUMMY_VALUE;
in_config->data =
xmalloc(nbr_cells *
sizeof(*(in_config->data)));
in_config->data_size = nbr_cells;
out_config->data_size = nbr_cells;
&global_cell_id,
&cell_core_mask,
&num_vertices_per_cell,
&global_corner_id,
&corner_core_mask,
&cell_to_vertex,
&x_cells,
&y_cells,
&x_vertices,
&y_vertices);
}
static void generate_cube_grid(
int comm_rank, int comm_size, int comp_id, int * grid_id,
unsigned n = 50;
unsigned nbr_vertices;
unsigned nbr_cells;
unsigned * num_vertices_per_cell;
unsigned * cell_to_vertex;
double * x_vertices;
double * y_vertices;
double * x_cells;
double * y_cells;
int * cell_core_mask;
int * corner_core_mask;
int * global_cell_id;
int * global_corner_id;
&num_vertices_per_cell, &cell_to_vertex,
&x_vertices, &y_vertices, &x_cells,
&y_cells, &global_cell_id,
&cell_core_mask, &global_corner_id,
&corner_core_mask, comm_rank, comm_size);
"cube", nbr_vertices, nbr_cells, (int*)num_vertices_per_cell,
x_vertices, y_vertices, (int*)cell_to_vertex, grid_id);
PUT_ERR("error in yac_cget_grid_size");
PUT_ERR("error in yac_cget_grid_size");
int corner_point_id, cell_point_id;
&corner_point_id);
&cell_point_id);
PUT_ERR("error in yac_cget_points_size");
PUT_ERR("error in yac_cget_points_size");
out_config->data =
xmalloc(nbr_cells *
sizeof(*(out_config->data)));
for (unsigned i = 0; i < nbr_cells; ++i)
out_config->data[i] =
(cell_core_mask[i])?
DUMMY_VALUE;
in_config->data =
xmalloc(nbr_cells *
sizeof(*(in_config->data)));
out_config->data_size = nbr_cells;
in_config->data_size = nbr_cells;
free(cell_core_mask);
free(corner_core_mask);
free(global_cell_id);
free(global_corner_id);
free(x_vertices);
free(y_vertices);
free(x_cells);
free(y_cells);
free(num_vertices_per_cell);
free(cell_to_vertex);
}
}
static void check_results(
fputs("ERROR(check_results): inconsistent data_size\n", stderr);
exit(EXIT_FAILURE);
}
if (fabs(
field_config.data[i] - ref_field_config.data[i]) > 1e-3) {
fputs("ERROR(check_results): data missmatch\n", stderr);
exit(EXIT_FAILURE);
}
}
}
int main(int argc, char **argv)
void yac_generate_part_cube_grid_information(unsigned n, unsigned *nbr_vertices, unsigned *nbr_cells, unsigned **num_vertices_per_cell, unsigned **cell_to_vertex, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **global_cell_id, int **cell_core_mask, int **global_corner_id, int **corner_core_mask, int rank, int size)
void yac_delete_icon_grid_data(int **cell_mask, int **global_cell_id, int **global_cell_id_rank, int **num_vertices_per_cell, int **global_corner_id, int **global_corner_id_rank, int **cell_to_vertex, double **x_cells, double **y_cells, double **x_vertices, double **y_vertices)
void yac_read_part_icon_grid_information(const char *filename, int *nbr_vertices, int *nbr_cells, int **num_vertices_per_cell, int **cell_to_vertex, double **x_vertices, double **y_vertices, double **x_cells, double **y_cells, int **global_cell_id, int **cell_mask, int **cell_core_mask, int **global_corner_id, int **corner_core_mask, int rank, int size)
double yac_test_harmonic(double lon, double lat)
void yac_cset_global_index(int const *global_index, int location, int grid_id)
int const YAC_LOCATION_CELL
int const YAC_LOCATION_CORNER
void yac_cget(int const field_id, int collection_size, double **recv_field, int *info, int *ierr)
int const YAC_TIME_UNIT_SECOND
void yac_cdef_grid_unstruct(const char *grid_name, int nbr_vertices, int nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex, int *grid_id)
void yac_cexchange(int const send_field_id, int const recv_field_id, int const collection_size, double ***const send_field, double **recv_field, int *send_info, int *recv_info, int *ierr)
void yac_cdef_points_unstruct(int const grid_id, int const nbr_points, int const located, double const *x_points, double const *y_points, int *point_id)
void yac_cput(int const field_id, int const collection_size, double ***const send_field, int *info, int *ierr)
void yac_cread_config_yaml(const char *yaml_filename)
int const YAC_ACTION_NONE
no data exchanges
void yac_cdef_calendar(int calendar)
void yac_cset_core_mask(int const *is_core, int location, int grid_id)
void yac_cdef_comps(char const **comp_names, int num_comps, int *comp_ids)
int const YAC_PROLEPTIC_GREGORIAN
void yac_cset_mask(int const *is_valid, int points_id)
int const YAC_ACTION_COUPLING
data exchange
size_t yac_cget_grid_size(int located, int grid_id)
void yac_cdef_comp(char const *comp_name, int *comp_id)
void yac_cdef_field(char const *name, int const comp_id, int const *point_ids, int const num_pointsets, int collection_size, const char *timestep, int time_unit, int *field_id)
size_t yac_cget_points_size(int points_id)