File: pnetcdf-permute.c

package info (click to toggle)
pnetcdf 1.14.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,812 kB
  • sloc: ansic: 85,298; f90: 10,707; fortran: 9,283; cpp: 8,864; makefile: 3,084; perl: 2,833; sh: 2,538; yacc: 1,227; lex: 216
file content (162 lines) | stat: -rw-r--r-- 5,532 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*********************************************************************
 *
 *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 *  See COPYRIGHT notice in top-level directory.
 *
 *********************************************************************/
/* $Id$ */

/* simple demonstration of pnetcdf
 * knowing nothing about the file, read in the variables.
 *
 * This example demonstrates the flexible interface, using the MPI derived
 * datatype to transpose the matrix.
 *
 * Note this program demonstrates transposition for one process only
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#include <pnetcdf.h>

#include <assert.h>

static void handle_error(int status, int lineno)
{
    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
    MPI_Abort(MPI_COMM_WORLD, 1);
}

int main(int argc, char **argv) {

#define NDIMS 3
    char filename[256];
    int i, j, k, rank, nprocs, ret;
    int ncfile, ndims=NDIMS;
    int dim_sizes[NDIMS];
    MPI_Offset start[NDIMS], count[NDIMS], nitems;
    int dimids[NDIMS], transposed_dims[NDIMS];
    int varid1, transposed_varid, flexible_varid;
    double *data, *transposed_data;
    MPI_Datatype transposed_type, one_d, two_d;

    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

    if (argc > 2) {
        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
        MPI_Finalize();
        exit(-1);
    }
    if (argc > 1) snprintf(filename, 256, "%s", argv[1]);
    else          strcpy(filename, "testfile.nc");

    ret = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_OFFSET,
                       MPI_INFO_NULL, &ncfile);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    dim_sizes[0] = 4;
    dim_sizes[1] = 5;
    dim_sizes[2] = 6;

    ret = ncmpi_def_dim(ncfile, "x", dim_sizes[0], &(dimids[0]));
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    ret = ncmpi_def_dim(ncfile, "y", dim_sizes[1], &(dimids[1]));
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    ret = ncmpi_def_dim(ncfile, "z", dim_sizes[2], &(dimids[2]));
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, dimids, &varid1);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* moab wants to permute {i,j,k} to {j,k,i} */
    transposed_dims[0] = dimids[1];
    transposed_dims[1] = dimids[2];
    transposed_dims[2] = dimids[0];
    ret = ncmpi_def_var(ncfile, "transposed-v1", NC_INT, ndims, transposed_dims,
	    &transposed_varid);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* want this to end up looking like transposed-v1 */
    ret = ncmpi_def_var(ncfile, "flexible-v1", NC_INT, ndims, transposed_dims,
	    &flexible_varid);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    ret = ncmpi_enddef(ncfile);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    nitems = dim_sizes[0]*dim_sizes[1]*dim_sizes[2];
    data = (double*) calloc(nitems, sizeof(double));
    transposed_data = (double*) calloc(nitems, sizeof(double));

    for (i=0; i<dim_sizes[0]; i++) {
	for (j=0; j<dim_sizes[1]; j++) {
	    for (k=0; k<dim_sizes[2]; k++) {
		/* data in x,y,z order */
		data[i*dim_sizes[1]*dim_sizes[2] + j*dim_sizes[2] + k] =
		    100*i*dim_sizes[1]*dim_sizes[2] + 10*j*dim_sizes[2] + k;
		/* permute the array data[X][Y][Z] to transpose[Y][Z][X] */
		assert((j*dim_sizes[2]*dim_sizes[0] + k*dim_sizes[0] + i) < nitems);
		transposed_data[j*dim_sizes[2]*dim_sizes[0] + k*dim_sizes[0] + i] =
		    100*i*dim_sizes[1]*dim_sizes[2] + 10*j*dim_sizes[2] + k;
	    }
	}
    }

    /* initial array written in i,j,k order  */

    start[0] = start[1] = start[2] = 0;
    count[0] = dim_sizes[0];
    count[1] = dim_sizes[1];
    count[2] = dim_sizes[2];
    if (rank > 0) nitems = count[0] = count[1] = count[2] = 0;
    ret = ncmpi_put_vara_all(ncfile, varid1, start, count, data, nitems, MPI_DOUBLE);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    count[0] = dim_sizes[1];
    count[1] = dim_sizes[2];
    count[2] = dim_sizes[0];
    if (rank > 0) nitems = count[0] = count[1] = count[2] = 0;
    ret = ncmpi_put_vara_all(ncfile, transposed_varid, start, count,
	    transposed_data, nitems, MPI_DOUBLE);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* permute ijk (4x5x6) into jki (5x6x4)*/
    /* new innermost dimension is I items, strided across the old JK face*/
    MPI_Type_vector(dim_sizes[0], 1, dim_sizes[1]*dim_sizes[2], MPI_DOUBLE, &one_d);
    /* new middle dimension is K items, strided over the K row, which isn't
     * actually a stride in this case.  We use hvector here because we
     * operate directly in terms of array items */
    MPI_Type_create_hvector(dim_sizes[2], 1, sizeof(double), one_d, &two_d);
    /* new outermost dimension is J items, strided over the old J row */
    MPI_Type_create_hvector(dim_sizes[1], 1, dim_sizes[2]*sizeof(double), two_d, &transposed_type);

    MPI_Type_commit(&transposed_type);
    MPI_Type_free(&one_d);
    MPI_Type_free(&two_d);

    nitems = 1;
    if (rank > 0) nitems = 0;
    ret = ncmpi_put_vara_all(ncfile, flexible_varid, start, count,
	    data, nitems, transposed_type);

    MPI_Type_free(&transposed_type);

    ret = ncmpi_close(ncfile);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    free(data);
    free(transposed_data);

    MPI_Finalize();
    return 0;
}

/*
 *vim: ts=8 sts=4 sw=4 noexpandtab */