1 /*********************************************************************
2 *
3 * Copyright (C) 2012, Northwestern University and Argonne National Laboratory
4 * See COPYRIGHT notice in top-level directory.
5 *
6 *********************************************************************/
7 /* $Id: pnetcdf-read-flexible.c 2369 2016-03-22 21:56:02Z wkliao $ */
8
9 /* simple demonstration of pnetcdf
10 * knowing nothing about the file, read in the variables.
11 *
12 * This example demonstrates the flexible interface */
13
14 #include <stdlib.h>
15 #include <mpi.h>
16 #include <pnetcdf.h>
17 #include <stdio.h>
18
handle_error(int status,int lineno)19 static void handle_error(int status, int lineno)
20 {
21 fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
22 MPI_Abort(MPI_COMM_WORLD, 1);
23 }
24
main(int argc,char ** argv)25 int main(int argc, char **argv) {
26
27 int i, j, rank, nprocs, ret;
28 int ncfile, ndims, nvars, ngatts, unlimited;
29 int var_ndims, var_natts;;
30 MPI_Offset *dim_sizes, var_size;
31 MPI_Offset *start, *count;
32 char varname[NC_MAX_NAME+1];
33 int dimids[NC_MAX_VAR_DIMS];
34 nc_type type;
35 int *data=NULL;
36
37 MPI_Init(&argc, &argv);
38
39 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
40 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
41
42 if (argc != 2) {
43 if (rank == 0) printf("Usage: %s filename\n", argv[0]);
44 MPI_Finalize();
45 exit(-1);
46 }
47
48 ret = ncmpi_open(MPI_COMM_WORLD, argv[1], NC_NOWRITE, MPI_INFO_NULL,
49 &ncfile);
50 if (ret != NC_NOERR) handle_error(ret, __LINE__);
51
52 /* reader knows nothing about dataset, but we can interrogate with query
53 * routines: ncmpi_inq tells us how many of each kind of "thing"
54 * (dimension, variable, attribute) we will find in the file */
55
56 /* no communication needed after ncmpi_open: all processors have a cached
57 * view of the metadata once ncmpi_open returns */
58
59 ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
60 if (ret != NC_NOERR) handle_error(ret, __LINE__);
61
62 /* we do not really need the name of the dimension or the variable for
63 * reading in this example. we could, in a different example, take the
64 * name of a variable on the command line and read just that one */
65
66 dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
67 /* netcdf dimension identifiers are allocated sequentially starting
68 * at zero; same for variable identifiers */
69 for(i=0; i<ndims; i++) {
70 ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
71 if (ret != NC_NOERR) handle_error(ret, __LINE__);
72 }
73
74 for(i=0; i<nvars; i++) {
75 /* much less coordination in this case compared to rank 0 doing all
76 * the i/o: everyone already has the necessary information */
77 ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
78 &var_natts);
79 if (ret != NC_NOERR) handle_error(ret, __LINE__);
80
81 start = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
82 count = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
83
84 /* we will simply decompose along one dimension. Generally the
85 * application has some algorithm for domain decomposition. Note
86 * that data decomposition can have an impact on i/o performance.
87 * Often it's best just to do what is natural for the application,
88 * but something to consider if performance is not what was
89 * expected/desired */
90
91 start[0] = (dim_sizes[dimids[0]]/nprocs)*rank;
92 count[0] = (dim_sizes[dimids[0]]/nprocs);
93 var_size = count[0];
94
95 for (j=1; j<var_ndims; j++) {
96 start[j] = 0;
97 count[j] = dim_sizes[dimids[j]];
98 var_size *= count[j];
99 }
100
101 switch(type) {
102 case NC_INT:
103 data = (int*) calloc(var_size, sizeof(int));
104 ret = ncmpi_get_vara_all(ncfile, i, start, count, data,
105 var_size, MPI_INT);
106 if (ret != NC_NOERR) handle_error(ret, __LINE__);
107 break;
108 default:
109 /* we can do this for all the known netcdf types but this
110 * example is already getting too long */
111 fprintf(stderr, "unsupported NetCDF type \n");
112 }
113
114 free(start);
115 free(count);
116 if (data != NULL) free(data);
117 }
118
119 ret = ncmpi_close(ncfile);
120 if (ret != NC_NOERR) handle_error(ret, __LINE__);
121 free(dim_sizes);
122
123 MPI_Finalize();
124 return 0;
125 }
126
127 /*
128 *vim: ts=8 sts=4 sw=4 noexpandtab */
129