1/*********************************************************************
2 *
3 *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
4 *  See COPYRIGHT notice in top-level directory.
5 *
6 *********************************************************************/
7
8/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9 * This example shows how to use nc_put_vara_int() to write a 2D 4-byte integer
10 * array in parallel and read it back using the same array partitioning pattern.
11 * It first defines a netCDF variable of size global_nx * global_ny where
12 *    global_ny == NY and
13 *    global_nx == (NX * number of MPI processes).
14 * The data partitioning pattern is a column-wise partitioning across all
15 * proceses. Each process writes a subarray of size ny * nx.
16 *
17 *    To compile:
18 *        mpicc -O2 parallel_vara.c -o parallel_vara -lnetcdf -lpnetcdf
19 *
20 * Example commands for MPI run and outputs from running ncdump on the
21 * NC file produced by this example program:
22 *
23 *    % mpiexec -n 4 ./parallel_vara /pvfs2/wkliao/testfile.nc
24 *
25 *    % ncdump /pvfs2/wkliao/testfile.nc
26 *    netcdf testfile {
27 *    dimensions:
28 *            y = 10 ;
29 *            x = 16 ;
30 *    variables:
31 *            int var(y, x) ;
32 *                var:str_att_name = "example attribute of type text." ;
33 *                var:float_att_name = 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f ;
34 *    // global attributes:
35 *                :history = "Wed Apr 30 11:18:58 2014\n",
36 *       "" ;
37 *    data:
38 *
39 *     var =
40 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
41 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
42 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
43 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
44 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
45 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
46 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
47 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
48 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
49 *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ;
50 *    }
51 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h> /* strcpy() */
56#include <unistd.h> /* getopt() */
57#include <time.h>   /* time() localtime(), asctime() */
58#include <assert.h>
59#include <mpi.h>
60#include <netcdf.h>
61#include <netcdf_par.h>
62
63#define NY 10
64#define NX 4
65
66#define FATAL_ERR {if(err!=NC_NOERR) {printf("Error at line=%d: %s Aborting ...\n", __LINE__nc_strerror(err)); goto fn_exit;}}
67#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__nc_strerror(err));}
68
69static void
70usage(char *argv0)
71{
72    char *help =
73    "Usage: %s [-h] | [-q] [file_name]\n"
74    "       [-h] Print help\n"
75    "       [-q] Quiet mode (reports when fail)\n"
76    "       [filename] output netCDF file name\n";
77    fprintf(stderrhelpargv0);
78}
79
80int main(int argc, char** argv)
81{
82    extern int optind;
83    char filename[128];
84    int ijranknprocsverbose=1, err;
85    int ncidcmodeomodevariddimid[2], buf[NY][NX];
86    char str_att[128];
87    float float_att[100];
88    size_t global_nyglobal_nxstart[2], count[2];
89
90    MPI_Init(&argc, &argv);
91    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
92    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
93
94    /* get command-line arguments */
95    while ((i = getopt(argcargv, "hq")) != EOF)
96        switch(i) {
97            case 'q': verbose = 0;
98                      break;
99            case 'h':
100            default:  if (rank==0) usage(argv[0]);
101                      MPI_Finalize();
102                      return 0;
103        }
104    argc -= optind;
105    argv += optind;
106    if (argc == 1) strcpy(filenameargv[0]); /* optional argument */
107    else strcpy(filename, "testfile.nc");
108
109    MPI_Bcast(filename, 128, MPI_CHAR, 0, MPI_COMM_WORLD);
110
111    /* create a new file for writing ----------------------------------------*/
112    cmode = NC_CLOBBER | NC_PNETCDF;
113    err = nc_create_par(filenamecmodeMPI_COMM_WORLDMPI_INFO_NULL, &ncid); FATAL_ERR
114
115    /* the global array is NY * (NX * nprocs) */
116    global_ny = NY;
117    global_nx = NX * nprocs;
118
119    for (i=0; i<NYi++)
120        for (j=0; j<NXj++)
121             buf[i][j] = rank;
122
123    /* add a global attribute: a time stamp at rank 0 */
124    time_t ltime = time(NULL); /* get the current calendar time */
125    asctime_r(localtime(&ltime), str_att);
126
127    /* make sure the time string are consistent among all processes */
128    MPI_Bcast(str_att, strlen(str_att), MPI_CHAR, 0, MPI_COMM_WORLD);
129
130    err = nc_put_att_text(ncidNC_GLOBAL, "history", strlen(str_att),
131                          &str_att[0]); ERR
132
133    /* define dimensions x and y */
134    err = nc_def_dim(ncid, "Y", global_ny, &dimid[0]); ERR
135    err = nc_def_dim(ncid, "X", global_nx, &dimid[1]); ERR
136
137    /* define a 2D variable of integer type */
138    err = nc_def_var(ncid, "var", NC_INT, 2, dimid, &varid); ERR
139
140    /* add attributes to the variable */
141    strcpy(str_att, "example attribute of type text.");
142    err = nc_put_att_text(ncidvarid, "str_att_name", strlen(str_att),
143                          &str_att[0]); ERR
144
145    for (i=0; i<8; i++) float_att[i] = i;
146    err = nc_put_att_float(ncidvarid, "float_att_name", NC_FLOAT, 8,
147                           &float_att[0]); ERR
148
149    /* do not forget to exit define mode */
150    err = nc_enddef(ncid); ERR
151
152    /* set to use MPI/PnetCDF collective I/O */
153    err = nc_var_par_access(ncidvaridNC_COLLECTIVE); ERR
154
155    /* now we are in data mode */
156    start[0] = 0;
157    start[1] = NX * rank;
158    count[0] = NY;
159    count[1] = NX;
160
161    err = nc_put_vara_int(ncidvaridstartcount, &buf[0][0]); ERR
162
163    err = nc_close(ncid); ERR
164
165    omode = NC_PNETCDF | NC_NOWRITE;
166    err = nc_open_par(filenameomodeMPI_COMM_WORLDMPI_INFO_NULL, &ncid); FATAL_ERR
167
168    /* inquire dimension IDs and lengths */
169    err = nc_inq_dimid(ncid, "Y", &dimid[0]); ERR
170    err = nc_inq_dimid(ncid, "X", &dimid[1]); ERR
171
172    err = nc_inq_dimlen(nciddimid[0], &global_ny); ERR
173    err = nc_inq_dimlen(nciddimid[1], &global_nx); ERR
174
175    /* obtain variable ID */
176    err = nc_inq_varid(ncid, "var", &varid); ERR
177
178    /* set to use MPI/PnetCDF collective I/O */
179    err = nc_var_par_access(ncidvaridNC_COLLECTIVE); ERR
180
181    /* each process reads its subarray from the file */
182    err = nc_get_vara_int(ncidvaridstartcount, &buf[0][0]); ERR
183
184    /* close the file */
185    err = nc_close(ncid); ERR
186
187fn_exit:
188    MPI_Finalize();
189    return 0;
190}
191


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed