Exemple #1
0
int main(int argc, char **argv) {

    int i, j;
    int status;
    int ncid1, ncid2;
    int ndims, nvars, ngatts, unlimdimid;
    char name[NC_MAX_NAME];
    nc_type type, vartypes[NC_MAX_VARS];
    MPI_Offset attlen;
    MPI_Offset dimlen, shape[NC_MAX_VAR_DIMS], varsize, start[NC_MAX_VAR_DIMS];
    void *valuep;
    int dimids[NC_MAX_DIMS], varids[NC_MAX_VARS];
    int vardims[NC_MAX_VARS][NC_MAX_VAR_DIMS/16]; /* divided by 16 due to my memory limitation */
    int varndims[NC_MAX_VARS], varnatts[NC_MAX_VARS];
    params opts;

    int rank;
    int nprocs;
    MPI_Comm comm = MPI_COMM_WORLD;


    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0)
        fprintf(stderr, "Testing independent read ... ");
    parse_read_args(argc, argv, rank, &opts);

    /**********  START OF NETCDF ACCESS **************/


    /* Read a netCDF file and write it out to another file */

    /**
     * Open the input dataset - ncid1:
     *   File name: "../data/test_int.nc"
     *   Dataset API: Collective
     * And create the output dataset - ncid2:
     *   File name: "testread.nc"
     *   Dataset API: Collective
     */

    status = ncmpi_open(comm, opts.infname, 0, MPI_INFO_NULL, &ncid1);
    if (status != NC_NOERR) handle_error(status);

    status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid2);
    if (status != NC_NOERR) handle_error(status);


    /**
     * Inquire the dataset definitions of input dataset AND
     * Add dataset definitions for output dataset.
     */

    status = ncmpi_inq(ncid1, &ndims, &nvars, &ngatts, &unlimdimid);
    if (status != NC_NOERR) handle_error(status);


    /* Inquire global attributes, assume CHAR attributes. */

    for (i = 0; i < ngatts; i++) {
        status = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name);
        if (status != NC_NOERR) handle_error(status);
        status = ncmpi_inq_att (ncid1, NC_GLOBAL, name, &type, &attlen);
        if (status != NC_NOERR) handle_error(status);
        switch (type) {
        case NC_CHAR:
            valuep = (void *)malloc(attlen * sizeof(char));
            status = ncmpi_get_att_text(ncid1, NC_GLOBAL, name, valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_att_text (ncid2, NC_GLOBAL, name, attlen, (char *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_SHORT:
            valuep = (void *)malloc(attlen * sizeof(short));
            status = ncmpi_get_att_short(ncid1, NC_GLOBAL, name, valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_att_short (ncid2, NC_GLOBAL, name, type, attlen, (short *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_INT:
            valuep = (void *)malloc(attlen * sizeof(int));
            status = ncmpi_get_att_int(ncid1, NC_GLOBAL, name, valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_att_int (ncid2, NC_GLOBAL, name, type, attlen, (int *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_FLOAT:
            valuep = (void *)malloc(attlen * sizeof(float));
            status = ncmpi_get_att_float(ncid1, NC_GLOBAL, name, valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_att_float (ncid2, NC_GLOBAL, name, type, attlen, (float *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_DOUBLE:
            valuep = (void *)malloc(attlen * sizeof(double));
            status = ncmpi_get_att_double(ncid1, NC_GLOBAL, name, valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_att_double (ncid2, NC_GLOBAL, name, type, attlen, (double *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        default:
            ;
            /* handle unexpected types */
        }
    }

    /* Inquire dimension */

    for (i = 0; i < ndims; i++) {
        status = ncmpi_inq_dim(ncid1, i, name, &dimlen);
        if (status != NC_NOERR) handle_error(status);
        if (i == unlimdimid)
            dimlen = NC_UNLIMITED;
        status = ncmpi_def_dim(ncid2, name, dimlen, dimids+i);
        if (status != NC_NOERR) handle_error(status);
    }

    /* Inquire variables */

    for (i = 0; i < nvars; i++) {
        status = ncmpi_inq_var (ncid1, i, name, vartypes+i, varndims+i, vardims[i], varnatts+i);
        if (status != NC_NOERR) handle_error(status);

        status = ncmpi_def_var(ncid2, name, vartypes[i], varndims[i], vardims[i], varids+i);
        if (status != NC_NOERR) handle_error(status);

        /* var attributes, assume CHAR attributes */

        for (j = 0; j < varnatts[i]; j++) {
            status = ncmpi_inq_attname(ncid1, varids[i], j, name);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_inq_att (ncid1, varids[i], name, &type, &attlen);
            if (status != NC_NOERR) handle_error(status);
            switch (type) {
            case NC_CHAR:
                valuep = (void *)malloc(attlen * sizeof(char));
                status = ncmpi_get_att_text(ncid1, varids[i], name, valuep);
                if (status != NC_NOERR) handle_error(status);
                status = ncmpi_put_att_text (ncid2, varids[i], name, attlen, (char *)valuep);
                if (status != NC_NOERR) handle_error(status);
                free(valuep);
                break;
            case NC_SHORT:
                valuep = (void *)malloc(attlen * sizeof(short));
                status = ncmpi_get_att_short(ncid1, varids[i], name, valuep);
                if (status != NC_NOERR) handle_error(status);
                status = ncmpi_put_att_short (ncid2, varids[i], name, type, attlen, (short *)valuep);
                if (status != NC_NOERR) handle_error(status);
                free(valuep);
                break;
            case NC_INT:
                valuep = (void *)malloc(attlen * sizeof(int));
                status = ncmpi_get_att_int(ncid1, varids[i], name, valuep);
                if (status != NC_NOERR) handle_error(status);
                status = ncmpi_put_att_int (ncid2, varids[i], name, type, attlen, (int *)valuep);
                if (status != NC_NOERR) handle_error(status);
                free(valuep);
                break;
            case NC_FLOAT:
                valuep = (void *)malloc(attlen * sizeof(float));
                status = ncmpi_get_att_float(ncid1, varids[i], name, valuep);
                if (status != NC_NOERR) handle_error(status);
                status = ncmpi_put_att_float (ncid2, varids[i], name, type, attlen, (float *)valuep);
                if (status != NC_NOERR) handle_error(status);
                free(valuep);
                break;
            case NC_DOUBLE:
                valuep = (void *)malloc(attlen * sizeof(double));
                status = ncmpi_get_att_double(ncid1, varids[i], name, valuep);
                if (status != NC_NOERR) handle_error(status);
                status = ncmpi_put_att_double (ncid2, varids[i], name, type, attlen, (double *)valuep);
                if (status != NC_NOERR) handle_error(status);
                free(valuep);
                break;
            default:
                ;
                /* handle unexpected types */
            }
        }
    }

    /**
     * End Define Mode (switch to data mode) for output dataset
     *   Dataset API: Collective
     */

    status = ncmpi_enddef(ncid2);
    if (status != NC_NOERR) handle_error(status);

    /**
     * Read data of variables from input dataset (assume INT variables)
     * Write the data out to the corresponding variables in the output dataset
     *
     *  Data Partition (Assume 4 processors):
     *   square: 2-D, (Block, *), 25*100 from 100*100
     *   cube:   3-D, (Block, *, *), 25*100*100 from 100*100*100
     *   xytime: 3-D, (Block, *, *), 25*100*100 from 100*100*100
     *   time:   1-D, Block-wise, 25 from 100
     *
     *  Data Mode API: non-collective
     */

    status = ncmpi_begin_indep_data(ncid1);
    if (status != NC_NOERR) handle_error(status);
    status =ncmpi_begin_indep_data(ncid2);
    if (status != NC_NOERR) handle_error(status);

    for (i = 0; i < NC_MAX_VAR_DIMS; i++)
        start[i] = 0;
    for (i = 0; i < nvars; i++) {
        varsize = 1;
        for (j = 0; j < varndims[i]; j++) {
            status = ncmpi_inq_dim(ncid1, vardims[i][j], name, shape + j);
            if (status != NC_NOERR) handle_error(status);
            if (j == 0) {
                shape[j] /= nprocs;
                start[j] = shape[j] * rank;
            }
            varsize *= shape[j];
        }
        switch (vartypes[i]) {
        case NC_CHAR:
            break;
        case NC_SHORT:
            valuep = (void *)malloc(varsize * sizeof(short));
            status = ncmpi_get_vara_short(ncid1, i, start, shape, (short *)valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_vara_short(ncid2, varids[i],
                                          start, shape, (short *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_INT:
            valuep = (void *)malloc(varsize * sizeof(int));
            status = ncmpi_get_vara_int(ncid1, i, start, shape, (int *)valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_vara_int(ncid2, varids[i],
                                        start, shape, (int *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_FLOAT:
            valuep = (void *)malloc(varsize * sizeof(float));
            status = ncmpi_get_vara_float(ncid1, i, start, shape, (float *)valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_vara_float(ncid2, varids[i],
                                          start, shape, (float *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        case NC_DOUBLE:
            valuep = (void *)malloc(varsize * sizeof(double));
            status = ncmpi_get_vara_double(ncid1, i, start, shape, (double *)valuep);
            if (status != NC_NOERR) handle_error(status);
            status = ncmpi_put_vara_double(ncid2, varids[i],
                                           start, shape, (double *)valuep);
            if (status != NC_NOERR) handle_error(status);
            free(valuep);
            break;
        default:
            ;
            /* handle unexpected types */
        }
    }

    status = ncmpi_end_indep_data(ncid1);
    if (status != NC_NOERR) handle_error(status);
    status = ncmpi_end_indep_data(ncid2);
    if (status != NC_NOERR) handle_error(status);

    status = ncmpi_sync(ncid1);
    if (status != NC_NOERR) handle_error(status);
    status = ncmpi_sync(ncid2);
    if (status != NC_NOERR) handle_error(status);

    /**
     * Close the datasets
     *   Dataset API:  collective
     */

    status = ncmpi_close(ncid1);
    if (status != NC_NOERR) handle_error(status);
    status = ncmpi_close(ncid2);
    if (status != NC_NOERR) handle_error(status);

    /*******************  END OF NETCDF ACCESS  ****************/

    if (rank == 0)
        fprintf(stderr, "OK\nInput file %s copied to: %s!\n", opts.infname, opts.outfname);

    MPI_Finalize();
    return 0;
}
int main(int argc, char **argv) {

    int i, j, rank, nprocs, ret;
    int ncfile, ndims, nvars, ngatts, unlimited;
    int var_ndims, var_natts;;
    MPI_Offset *dim_sizes, var_size;
    MPI_Offset *start, *count;
    int *requests, *statuses;
    char varname[NC_MAX_NAME+1];
    int dimids[NC_MAX_VAR_DIMS];
    nc_type type;
    int **data;

    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);
    }

    ret = ncmpi_open(MPI_COMM_WORLD, argv[1], NC_NOWRITE, MPI_INFO_NULL,
                     &ncfile);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* reader knows nothing about dataset, but we can interrogate with query
     * routines: ncmpi_inq tells us how many of each kind of "thing"
     * (dimension, variable, attribute) we will find in the file  */

    /* no commnunication needed after ncmpi_open: all processors have a cached
     * veiw of the metadata once ncmpi_open returns */

    ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* we do not really need the name of the dimension or the variable for
     * reading in this example.  we could, in a different example, take the
     * name of a variable on the command line and read just that one */

    dim_sizes = calloc(ndims, sizeof(MPI_Offset));
    /* netcdf dimension identifiers are allocated sequentially starting
     * at zero; same for variable identifiers */
    for(i=0; i<ndims; i++)  {
        ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
        if (ret != NC_NOERR) handle_error(ret, __LINE__);
    }

    requests = calloc(nvars, sizeof(int));
    statuses = calloc(nvars, sizeof(int));

    data =  malloc(nvars*sizeof(int*));

    for(i=0; i<nvars; i++) {
        /* much less coordination in this case compared to rank 0 doing all
         * the i/o: everyone already has the necessary information */
        ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
                            &var_natts);
        if (ret != NC_NOERR) handle_error(ret, __LINE__);

        start = calloc(var_ndims, sizeof(MPI_Offset));
        count = calloc(var_ndims, sizeof(MPI_Offset));

        /* we will simply decompose along one dimension.  Generally the
         * application has some algorithim for domain decomposistion.  Note
         * that data decomposistion can have an impact on i/o performance.
         * Often it's best just to do what is natural for the application,
         * but something to consider if performance is not what was
         * expected/desired */

        start[0] = (dim_sizes[dimids[0]]/nprocs)*rank;
        count[0] = (dim_sizes[dimids[0]]/nprocs);
        var_size = count[0];

        for (j=1; j<var_ndims; j++) {
            start[j] = 0;
            count[j] = dim_sizes[dimids[j]];
            var_size *= count[j];
        }

        switch(type) {
        case NC_INT:
            data[i] = calloc(var_size, sizeof(int));
            /* as with the writes, this call is independent: we
             * will do any coordination (if desired) in a
             * subsequent ncmpi_wait_all() call */
            ret = ncmpi_iget_vara(ncfile, i, start, count, data[i],
                                  var_size, MPI_INT, &(requests[i]));
            if (ret != NC_NOERR) handle_error(ret, __LINE__);
            break;
        default:
            /* we can do this for all the known netcdf types but this
             * example is already getting too long  */
            fprintf(stderr, "unsupported NetCDF type \n");
        }

        free(start);
        free(count);
    }

    ret = ncmpi_wait_all(ncfile, nvars, requests, statuses);
    if (ret != NC_NOERR) handle_error(ret, __LINE__);

    /* now that the ncmpi_wait_all has returned, the caller can do stuff with
     * the buffers passed in to the non-blocking operations.  The buffer resue
     * rules are similar to MPI non-blocking messages */

    for (i=0; i<nvars; i++) {
        if (data[i] != NULL) free(data[i]);
    }
    free(data);
    free(dim_sizes);
    free(requests);
    free(statuses);

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

    MPI_Finalize();
    return 0;
}
int main(int argc, char **argv) {

    int i, j=0, rank, nprocs, err;
    int ncfile, ndims, nvars, ngatts, unlimited, var_ndims, var_natts;;
    int *dimids=NULL;
    char filename[256], varname[NC_MAX_NAME+1];
    MPI_Offset *dim_sizes=NULL, var_size;
    nc_type type;
    int *data=NULL;

    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");

    if (rank == 0) {
        err = ncmpi_open(MPI_COMM_SELF, filename,
                         NC_NOWRITE, MPI_INFO_NULL, &ncfile);
        if (err != NC_NOERR) handle_error(err, __LINE__);

        /* reader knows nothing about dataset, but we can interrogate with
         * query routines: ncmpi_inq tells us how many of each kind of
         * "thing" (dimension, variable, attribute) we will find in the
         * file  */

        err = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
        if (err != NC_NOERR) handle_error(err, __LINE__);

        /* we do not really need the name of the dimension or the variable
         * for reading in this example.  we could, in a different example,
         * take the name of a variable on the command line and read just
         * that one */

        dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
        /* netcdf dimension identifiers are allocated sequentially starting
         * at zero; same for variable identifiers */
        for(i=0; i<ndims; i++)  {
            err = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
            if (err != NC_NOERR) handle_error(err, __LINE__);
        }
    }

    /* need to inform other MPI processors how many variables we will send */
    err = MPI_Bcast(&nvars, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_ERR(err)

    for(i=0; i<nvars; i++) {
        /* rank 0 will find out the size of each variable, read it, and
         * broadcast it to the rest of the processors */
        if (rank == 0) {
            /* obtain the number of dimensions of variable i, so we can
             * allocate the dimids array */
            err = ncmpi_inq_varndims(ncfile, i, &var_ndims);
            if (err != NC_NOERR) handle_error(err, __LINE__);
            dimids = (int*) malloc(var_ndims * sizeof(int));

            err = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
                    &var_natts);
            if (err != NC_NOERR) handle_error(err, __LINE__);

            for (j=0, var_size=1; j<var_ndims; j++)  {
                var_size *= dim_sizes[dimids[j]];
            }
            free(dimids);
        }
        /* oddity: there's no predefined MPI_Offset type */
        err = MPI_Bcast(&var_size, 1, MPI_OFFSET, 0, MPI_COMM_WORLD);
        MPI_ERR(err)

        data = (int*) calloc(var_size, sizeof(int));

        if (rank == 0) {
            switch(type) {
                case NC_INT:
                    /* now we have the variable identifiers and we know how big
                     * they are */

                    /* this approach is not scalable: i/o happens from a single
                     * processor.  This approach can be ok if the amount of
                     * data is quite small, but almost always the underlying
                     * MPI-IO library can do a better job */

                    err = ncmpi_get_var_int_all(ncfile, j, data);
                    if (err != NC_NOERR) handle_error(err, __LINE__);
                    break;
                default:
                    /* we can do this for all the known netcdf types but this
                     * example is already getting too long  */
                    fprintf(stderr, "unsupported NetCDF type \n");
            }
        }

        /*and finally all processors have the data */
        err = MPI_Bcast(data, var_size, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_ERR(err)

        /* Here, every process can do computation on the local buffer, data,
           or copy the contents to somewhere else */
        free(data);
    }

    if (rank == 0) {
        err = ncmpi_close(ncfile);
        if (err != NC_NOERR) handle_error(err, __LINE__);
        free(dim_sizes);
    }

    MPI_Finalize();
    return 0;
}
Exemple #4
0
/*
  reads input in pnetcdf format

  nblocks: (output) local number of blocks
  tot_blocks: (output) total number of blocks
  vblocks: (output) pointer to array of vblocks
  in_file: input file name
  comm: MPI communicator
  gids: (output) gids of local blocks (allocated by this function)
  num_neighbors: (output) number of neighbors for each local block
   (allocated by this function)
  neighbors: (output) gids of neighbors of each local block
   (allocated by this function)

  side effects: allocates vblocks, gids, num_neighbors, neighbors

*/
void pnetcdf_read(int *nblocks, int *tot_blocks, struct vblock_t ***vblocks,
      char *in_file, MPI_Comm comm, int *gids, int *num_neighbors,
      int **neighbors) {

#ifdef USEPNETCDF
  int err;
  int ncid, varids[23], dimids[8];
  MPI_Offset start[2], count[2];
  nc_type type;
  int ndims, natts;
  int dims[2];
  int rank, groupsize; /* MPI usual */

  /* open file for reading */
  err = ncmpi_open(comm, in_file, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR;

  err = ncmpi_inq_varid(ncid, "block_off_num_verts", &varids[5]); ERR;
  err = ncmpi_inq_varid(ncid, "block_off_num_complete_cells", &varids[6]); ERR;
  err = ncmpi_inq_varid(ncid, "block_off_tot_num_cell_faces", &varids[7]); ERR;
  err = ncmpi_inq_varid(ncid, "block_off_tot_num_face_verts", &varids[8]); ERR;
  err = ncmpi_inq_varid(ncid, "block_off_num_orig_particles", &varids[9]); ERR;

  /* get number of blocks */
  MPI_Offset num_g_blocks; /* 64 bit version of tot_blcoks */
  err = ncmpi_inq_dimlen(ncid, dimids[0], &num_g_blocks); ERR;
  *tot_blocks = num_g_blocks;
  MPI_Comm_rank(comm, &rank);
  MPI_Comm_size(comm, &groupsize);
  int start_block_ofst =  rank * (*tot_blocks / groupsize);
  *nblocks = (rank < groupsize - 1 ? (*tot_blocks / groupsize) :
        *tot_blocks - (rank * *tot_blocks / groupsize));

  /* block offsets */
  int64_t *block_ofsts = (int64_t*)malloc(*tot_blocks * sizeof(int64_t));
  *vblocks = (struct vblock_t**)malloc(*nblocks * sizeof(struct vblock_t*));

  /* read all blocks */
  gids = (int *)malloc(*nblocks * sizeof(int));
  num_neighbors = (int *)malloc(*nblocks * sizeof(int));
  neighbors = (int **)malloc(*nblocks * sizeof(int *));
  int b;
  for (b = 0; b < *nblocks; b++) {

    struct vblock_t* v = (struct vblock_t*)malloc(sizeof(struct vblock_t));

    /* quantities */
    start[0] = start_block_ofst + b;
    count[0] = 1;
    err = ncmpi_inq_varid(ncid, "num_verts", &varids[0]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[0], start, count,
         &(v->num_verts)); ERR;
    err = ncmpi_inq_varid(ncid, "num_complete_cells", &varids[1]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[1], start, count,
         &(v->num_complete_cells)); ERR;
    err = ncmpi_inq_varid(ncid, "tot_num_cell_faces", &varids[2]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[2], start, count,
         &(v->tot_num_cell_faces)); ERR;
    err = ncmpi_inq_varid(ncid, "tot_num_face_verts", &varids[3]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[3], start, count,
         &(v->tot_num_face_verts)); ERR;
    err = ncmpi_inq_varid(ncid, "num_orig_particles", &varids[4]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[4], start, count,
         &(v->num_orig_particles)); ERR;
    err = ncmpi_inq_varid(ncid, "neighbors", &varids[21]); ERR;
    err = ncmpi_inq_var(ncid, varids[21], 0, &type, &ndims,
      dimids, &natts);

    /* block bounds */
    start[0] = start_block_ofst + b;
    start[1] = 0;
    count[0] = 1;
    count[1] = 3;
    err = ncmpi_inq_varid(ncid, "mins", &varids[11]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[11], start, count,
           v->mins); ERR;
    err = ncmpi_inq_varid(ncid, "maxs", &varids[12]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[12], start, count,
           v->maxs); ERR;

    /* save_verts */
    start[0] = 0;
    count[0] = *tot_blocks;
    err = ncmpi_get_vara_longlong_all(ncid, varids[5], start, count,
              block_ofsts); ERR;
    v->save_verts = (float *)malloc(v->num_verts * 3 * sizeof(float));
    start[0] = block_ofsts[start_block_ofst + b];
    start[1] = 0;
    count[0] = v->num_verts;
    count[1] = 3;
    err = ncmpi_inq_varid(ncid, "save_verts", &varids[13]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[13], start, count,
           v->save_verts); ERR;

    /* sites */
    start[0] = 0;
    count[0] = *tot_blocks;
    err = ncmpi_get_vara_longlong_all(ncid, varids[9], start, count,
              block_ofsts); ERR;
    v->sites = (float *)malloc(v->num_orig_particles * 3 * sizeof(float));
    start[0] = block_ofsts[start_block_ofst + b];
    start[1] = 0;
    count[0] = v->num_orig_particles;
    count[1] = 3;
    err = ncmpi_inq_varid(ncid, "sites", &varids[14]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[14], start, count,
           v->sites); ERR;

    /* complete cells */
    start[0] = 0;
    count[0] = *tot_blocks;
    err = ncmpi_get_vara_longlong_all(ncid, varids[6], start, count,
              block_ofsts); ERR;
    v->complete_cells = (int *)malloc(v->num_complete_cells * sizeof(int));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->num_complete_cells;
    err = ncmpi_inq_varid(ncid, "complete_cells", &varids[15]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[15], start, count,
         v->complete_cells); ERR;

    /* areas, uses same block offsets as complete cells */
    v->areas = (float *)malloc(v->num_complete_cells * sizeof(float));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->num_complete_cells;
    err = ncmpi_inq_varid(ncid, "areas", &varids[16]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[16], start, count,
           v->areas); ERR;

    /* volumes, uses same block offsets as complete cells */
    v->vols = (float *)malloc(v->num_complete_cells * sizeof(float));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->num_complete_cells;
    err = ncmpi_inq_varid(ncid, "vols", &varids[17]); ERR;
    err = ncmpi_get_vara_float_all(ncid, varids[17], start, count,
           v->vols); ERR;

    /* num_cell_faces, uses same block offsets as complete cells */
    v->num_cell_faces = (int *)malloc(v->num_complete_cells * sizeof(int));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->num_complete_cells;
    err = ncmpi_inq_varid(ncid, "num_cell_faces", &varids[18]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[18], start, count,
         v->num_cell_faces); ERR;

    /* num_face_verts */
    start[0] = 0;
    count[0] = *tot_blocks;
    err = ncmpi_get_vara_longlong_all(ncid, varids[7], start, count,
              block_ofsts); ERR;
    v->num_face_verts = (int *)malloc(v->tot_num_cell_faces * sizeof(int));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->tot_num_cell_faces;
    err = ncmpi_inq_varid(ncid, "num_face_verts", &varids[19]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[19], start, count,
         v->num_face_verts); ERR;

    /* face_verts */
    start[0] = 0;
    count[0] = *tot_blocks;
    err = ncmpi_get_vara_longlong_all(ncid, varids[8], start, count,
              block_ofsts); ERR;
    v->face_verts = (int *)malloc(v->tot_num_face_verts * sizeof(int));
    start[0] = block_ofsts[start_block_ofst + b];
    count[0] = v->tot_num_face_verts;
    err = ncmpi_inq_varid(ncid, "face_verts", &varids[20]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[20], start, count,
         v->face_verts); ERR;

    /* neighbors */
    MPI_Offset n; /* temporary 64-bit version of number of neighbors */
    err = ncmpi_inq_varid(ncid, "neighbors", &varids[21]); ERR;
    err = ncmpi_inq_var(ncid, varids[2], 0, &type, &ndims,
      dims, &natts); ERR;
    err = ncmpi_inq_dimlen(ncid, dims[0], &n); ERR;
    num_neighbors[b] = n;
    neighbors[b] = (int *)malloc(num_neighbors[b] * sizeof(int));
    start[0] = start_block_ofst + b;
    count[0] = num_neighbors[b];
    err = ncmpi_get_vara_int_all(ncid, varids[21], start, count,
         neighbors[b]); ERR;

    /* gids */
    start[0] = start_block_ofst + b;
    count[0] = 1;
    err = ncmpi_inq_varid(ncid, "g_block_ids", &varids[22]); ERR;
    err = ncmpi_get_vara_int_all(ncid, varids[22], start, count,
         &gids[b]); ERR;

    (*vblocks)[b] = v;

  }

  /* cleanup */
  err = ncmpi_close(ncid); ERR;
  free(block_ofsts);
#endif
}
Exemple #5
0
/*----< main() >--------------------------------------------------------------*/
int main(int argc, char **argv)
{
    int i, j, c, err, rank, nprocs, verbose, quiet;
    int ncid1, ndims1, nvars1, natts1, unlimdimid1, *dimids1;
    int ncid2, ndims2, nvars2, natts2, unlimdimid2, *dimids2;
    char *name1, *name2;
    MPI_Offset *shape=NULL, varsize, *start=NULL;
    MPI_Offset attlen1, dimlen1, attlen2, dimlen2;
    nc_type type1, type2;
    MPI_Comm comm=MPI_COMM_WORLD;
    int nvars, check_header, check_variable_list, check_entire_file;
    long long numVarDIFF=0, numHeadDIFF=0, varDIFF, numDIFF;
    struct vspec var_list;
    extern char *optarg;
    extern int optind;
    MPI_Info info;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(comm, &nprocs);
    MPI_Comm_rank(comm, &rank);

    progname            = argv[0];
    verbose             = 0;
    quiet               = 0;
    check_header        = 0;
    check_variable_list = 0;
    check_entire_file   = 0;
    var_list.names      = NULL;
    var_list.nvars      = 0;

    while ((c = getopt(argc, argv, "bhqv:")) != -1)
        switch(c) {
            case 'h':               /* compare header only */
                check_header = 1;
                break;
            case 'v':               /* variable names */
                /* make list of names of variables specified */
                get_var_names(optarg, &var_list);
                check_variable_list = 1;
                break;
            case 'b':
                verbose = 1;
                break;
            case 'q':
                quiet = 1;
                break;
            case '?':
                usage(rank, argv[0]);
                break;
        }

    /* quiet overwrites verbose */
    if (quiet) verbose = 0;

    if (argc - optind != 2) usage(rank, argv[0]);

    if (check_header == 0 && check_variable_list == 0) {
        check_entire_file = 1;
        check_header      = 1;
    }

    name1   = (char*) malloc(NC_MAX_NAME);
    if (!name1) OOM_ERROR
    name2   = (char*) malloc(NC_MAX_NAME);
    if (!name2) OOM_ERROR

    /* Nov. 18, 2014 -- disable subfiling as it does not correctly handle the
     * cases when  nprocs < num_subfiles */
    MPI_Info_create (&info);
    MPI_Info_set (info, "pnetcdf_subfiling", "disable");

    /* open files */
    err = ncmpi_open(comm, argv[optind], NC_NOWRITE, info, &ncid1);
    HANDLE_ERROR
    err = ncmpi_open(comm, argv[optind+1], NC_NOWRITE, info, &ncid2);
    HANDLE_ERROR

    MPI_Info_free(&info);

    /* check header */
    if (check_header && rank == 0) { /* only root checks header */
        int attnump;

        err = ncmpi_inq(ncid1, &ndims1, &nvars1, &natts1, &unlimdimid1);
        HANDLE_ERROR
        err = ncmpi_inq(ncid2, &ndims2, &nvars2, &natts2, &unlimdimid2);
        HANDLE_ERROR
        if (ndims1 != ndims2) { /* check number of dimensions if equal */
            if (!quiet) printf("DIFF: number of dimensions (%d) != (%d)\n",ndims1, ndims2);
            numHeadDIFF++;
        }
        else if (verbose)
            printf("SAME: number of dimensions (%d)\n",ndims1);
        if (nvars1 != nvars2) { /* check number of variables if equal */
            if (!quiet) printf("DIFF: number of variables (%d) != (%d)\n",nvars1, nvars2);
            numHeadDIFF++;
        }
        else if (verbose)
            printf("SAME: number of variables (%d)\n",nvars1);
        if (natts1 != natts2) { /* check number of global attributes if equal */
            if (!quiet) printf("DIFF: number of global attributes (%d) != (%d)\n",natts1, natts2);
            numHeadDIFF++;
        }
        else if (verbose)
            printf("SAME: number of global attributes (%d)\n",natts1);

        /* Compare global attributes, assume CHAR attributes. */
        for (i=0; i<natts1; i++) { /* check what's in file1 also in file2 */
            err = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name1);
            HANDLE_ERROR
            /* find the attr with the same name from ncid2 */
            err = ncmpi_inq_attid(ncid2, NC_GLOBAL, name1, &attnump);
            if (err == NC_ENOTATT) {
                if (!quiet) printf("DIFF: global attribute \"%s\" not found in file %s\n",
                       name1,argv[optind+1]);
                numHeadDIFF++;
                continue;
            }

            err = ncmpi_inq_att(ncid1, NC_GLOBAL, name1, &type1, &attlen1);
            HANDLE_ERROR
            err = ncmpi_inq_att(ncid2, NC_GLOBAL, name1, &type2, &attlen2);
            HANDLE_ERROR
            if (type1 != type2) {
                if (!quiet) printf("DIFF: global attribute \"%s\" data type (%s) != (%s)\n",
                       name1,get_type(type1),get_type(type2));
                numHeadDIFF++;
                continue;
            }
            else if (verbose) {
                printf("Global attribute \"%s\":\n",name1);
                printf("\tSAME: data type (%s)\n",get_type(type1));
            }

            if (attlen1 != attlen2) {
                if (!quiet) printf("DIFF: global attribute \"%s\" length (%lld) != (%lld)\n",
                       name1,attlen1,attlen2);
                numHeadDIFF++;
                continue;
            }
            else if (verbose)
                printf("\tSAME: length (%lld)\n",attlen1);

            switch (type1) {
                case NC_CHAR:   CHECK_GLOBAL_ATT_DIFF(char,   ncmpi_get_att_text,      NC_CHAR)
                case NC_SHORT:  CHECK_GLOBAL_ATT_DIFF(short,  ncmpi_get_att_short,     NC_SHORT)
                case NC_INT:    CHECK_GLOBAL_ATT_DIFF(int,    ncmpi_get_att_int,       NC_INT)
                case NC_FLOAT:  CHECK_GLOBAL_ATT_DIFF(float,  ncmpi_get_att_float,     NC_FLOAT)
                case NC_DOUBLE: CHECK_GLOBAL_ATT_DIFF(double, ncmpi_get_att_double,    NC_DOUBLE)
                case NC_UBYTE:  CHECK_GLOBAL_ATT_DIFF(ubyte,  ncmpi_get_att_uchar,     NC_UBYTE)
                case NC_USHORT: CHECK_GLOBAL_ATT_DIFF(ushort, ncmpi_get_att_ushort,    NC_USHORT)
                case NC_UINT:   CHECK_GLOBAL_ATT_DIFF(uint,   ncmpi_get_att_uint,      NC_UINT)
                case NC_INT64:  CHECK_GLOBAL_ATT_DIFF(int64,  ncmpi_get_att_longlong,  NC_INT64)
                case NC_UINT64: CHECK_GLOBAL_ATT_DIFF(uint64, ncmpi_get_att_ulonglong, NC_UINT64)
                default: ; /* TODO: handle unexpected types */
            }
        }
        for (i=0; i<natts2; i++) { /* check attributes in file2 but not in file1 */
            err = ncmpi_inq_attname(ncid2, NC_GLOBAL, i, name2);
            HANDLE_ERROR
            /* find the attr with the same name from ncid1 */
            if (ncmpi_inq_attid(ncid1, NC_GLOBAL, name2, &attnump) == NC_ENOTATT) {
                numHeadDIFF++;
                if (!quiet) printf("DIFF: global attribute \"%s\" not found in file %s\n",
                       name1,argv[optind]);
            }
        }

        /* Compare dimension */
        if (ndims1 && verbose)
            printf("Dimension:\n");

        for (i=0; i<ndims1; i++) { /* check dimensions in file1 also in file2 */
            int dimid;
            err = ncmpi_inq_dim(ncid1, i, name1, &dimlen1);
            HANDLE_ERROR
            /* find the dim with the same name from ncid2 */
            err = ncmpi_inq_dimid(ncid2, name1, &dimid);
            if (err == NC_EBADDIM) {
                if (!quiet) printf("DIFF: dimension \"%s\" not found in file %s\n",
                       name1,argv[optind+1]);
                numHeadDIFF++;
                continue;
            }

            err = ncmpi_inq_dimlen(ncid2, dimid, &dimlen2);
            HANDLE_ERROR
            if (dimlen1 != dimlen2) {
                /* cast to quiet warning on 32 bit platforms */
                if (!quiet) printf("DIFF: dimension \"%s\" length (%lld) != (%lld)\n",
                       name1,(long long int)dimlen1,(long long int)dimlen2);
                numHeadDIFF++;
            }
            else if (verbose)
                printf("\tSAME: dimension \"%s\" length (%lld)\n",
                       name1,(long long int)dimlen1);
        }
        for (i=0; i<ndims2; i++) { /* check dimensions in file2 but not in file1 */
            int dimid;
            err = ncmpi_inq_dim(ncid2, i, name2, &dimlen2);
            HANDLE_ERROR
            /* find the dim with the same name from ncid1 */
            if (ncmpi_inq_dimid(ncid2, name1, &dimid) == NC_EBADDIM) {
                if (!quiet) printf("DIFF: dimension \"%s\" not found in file %s\n",
                       name1,argv[optind]);
                numHeadDIFF++;
            }
        }

        /* Compare variables' metadata */
        for (i=0; i<nvars1; i++) {
            int varid;
            err = ncmpi_inq_varndims(ncid1, i, &ndims1); HANDLE_ERROR
            dimids1 = (int*) malloc((size_t)ndims1 * SIZEOF_INT);
            if (!dimids1) OOM_ERROR
            err = ncmpi_inq_var(ncid1, i, name1, &type1, &ndims1, dimids1, &natts1);
            HANDLE_ERROR
            /* find the variable with the same name from ncid2 */
            err = ncmpi_inq_varid(ncid2, name1, &varid);
            if (err == NC_ENOTVAR) {
                if (!quiet) printf("DIFF: variable \"%s\" not found in file %s\n",
                       name1,argv[optind+1]);
                numHeadDIFF++;
                numVarDIFF++;
                continue;
            }
            err = ncmpi_inq_varndims(ncid2, varid, &ndims2); HANDLE_ERROR
            dimids2 = (int*) malloc((size_t)ndims2 * SIZEOF_INT);
            if (!dimids2) OOM_ERROR
            err = ncmpi_inq_var(ncid2, varid, name2, &type2, &ndims2, dimids2, &natts2);
            HANDLE_ERROR

            if (type1 != type2) {
                if (!quiet) printf("DIFF: variable \"%s\" data type (%s) != (%s)\n",
                       name1,get_type(type1),get_type(type2));
                numHeadDIFF++;
            }
            else if (verbose) {
                printf("Variable \"%s\":\n",name1);
                printf("\tSAME: data type (%s)\n",get_type(type1));
            }

            if (ndims1 != ndims2) {
                if (!quiet) printf("DIFF: variable \"%s\" number of dimensions (%d) != (%d)\n",
                       name1,ndims1,ndims2);
                numHeadDIFF++;
            }
            else {
                if (verbose)
                    printf("\tSAME: number of dimensions (%d)\n",ndims1);

                for (j=0; j<ndims1; j++) { /* check variable's dimensionality */
                    char dimname1[NC_MAX_NAME], dimname2[NC_MAX_NAME];
                    /* get dim name for each dim ID */
                    err = ncmpi_inq_dim(ncid1, dimids1[j], dimname1, &dimlen1);
                    HANDLE_ERROR
                    err = ncmpi_inq_dim(ncid1, dimids2[j], dimname2, &dimlen2);
                    HANDLE_ERROR
                    if (verbose)
                        printf("\tdimension %d:\n",j);
                    if (strcmp(dimname1, dimname2) != 0) {
                        if (!quiet) printf("DIFF: variable \"%s\" of type \"%s\" dimension %d's name (%s) != (%s)\n",
                               name1,get_type(type1),j,dimname1,dimname2);
                        numHeadDIFF++;
                    }
                    else if (verbose)
                        printf("\t\tSAME: name (%s)\n",dimname1);
                    if (dimlen1 != dimlen2) {
                        if (!quiet) printf("DIFF: variable \"%s\" of type \"%s\" dimension %d's length (%lld) != (%lld)\n",
                               name1,get_type(type1),j,(long long int)dimlen1,(long long int)dimlen2);
                        numHeadDIFF++;
                    }
                    else if (verbose)
                        printf("\t\tSAME: length (%lld)\n",(long long int)dimlen1);
                }
            }

            if (natts1 != natts2) {
                if (!quiet) printf("DIFF: variable \"%s\" number of attributes (%d) != (%d)\n",
                       name1,natts1,natts2);
                numHeadDIFF++;
            }
            else if (verbose)
                printf("\tSAME: number of attributes (%d)\n",natts1);

            /* var attributes, assume CHAR attributes */
            for (j=0; j<natts1; j++) {
                char attrname[NC_MAX_NAME];
                err = ncmpi_inq_attname(ncid1, i, j, attrname);
                HANDLE_ERROR
                err = ncmpi_inq_att(ncid1, i, attrname, &type1, &attlen1);
                HANDLE_ERROR
                /* find the variable attr with the same name from ncid2 */
                err = ncmpi_inq_att(ncid2, varid, attrname, &type2, &attlen2);
                if (err == NC_ENOTATT) {
                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" not found in file %s\n",
                           name1,attrname,argv[optind+1]);
                    numHeadDIFF++;
                    continue;
                }
                if (verbose)
                    printf("\tattribute \"%s\":\n",attrname);

                if (type1 != type2) {
                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" data type (%s) != (%s)\n",
                           name1,attrname,get_type(type1),get_type(type2));
                    numHeadDIFF++;
                    continue; /* skip this attribute */
                }
                else if (verbose)
                    printf("\t\tSAME: data type (%s)\n",get_type(type1));
                if (attlen1 != attlen2) {
                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" length (%lld) != (%lld)\n",
                           name1,attrname,(long long int)attlen1,(long long int)attlen2);
                    numHeadDIFF++;
                    continue; /* skip this attribute */
                }
                else if (verbose)
                    printf("\t\tSAME: length (%lld)\n",(long long int)attlen1);

                switch (type1) {
                    case NC_CHAR:   CHECK_VAR_ATT_DIFF(char,   ncmpi_get_att_text,      NC_CHAR)
                    case NC_SHORT:  CHECK_VAR_ATT_DIFF(short,  ncmpi_get_att_short,     NC_SHORT)
                    case NC_INT:    CHECK_VAR_ATT_DIFF(int,    ncmpi_get_att_int,       NC_INT)
                    case NC_FLOAT:  CHECK_VAR_ATT_DIFF(float,  ncmpi_get_att_float,     NC_FLOAT)
                    case NC_DOUBLE: CHECK_VAR_ATT_DIFF(double, ncmpi_get_att_double,    NC_DOUBLE)
                    case NC_UBYTE:  CHECK_VAR_ATT_DIFF(ubyte,  ncmpi_get_att_uchar,     NC_UBYTE)
                    case NC_USHORT: CHECK_VAR_ATT_DIFF(ushort, ncmpi_get_att_ushort,    NC_USHORT)
                    case NC_UINT:   CHECK_VAR_ATT_DIFF(uint,   ncmpi_get_att_uint,      NC_UINT)
                    case NC_INT64:  CHECK_VAR_ATT_DIFF(int64,  ncmpi_get_att_longlong,  NC_INT64)
                    case NC_UINT64: CHECK_VAR_ATT_DIFF(uint64, ncmpi_get_att_ulonglong, NC_UINT64)
                    default: ; /* TODO: handle unexpected types */
                }
            }
            for (j=0; j<natts2; j++) {
                char attrname[NC_MAX_NAME];
                err = ncmpi_inq_attname(ncid2, varid, j, attrname);
                HANDLE_ERROR
                /* find the variable attr with the same name from ncid1 */
                err = ncmpi_inq_att(ncid1, i, attrname, &type1, &attlen1);
                if (err == NC_ENOTATT) {
                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" not found in file %s\n",
                           name1,attrname,argv[optind]);
                    numHeadDIFF++;
                }
            }
            free(dimids1);
            free(dimids2);
        }
        for (i=0; i<nvars2; i++) { /* check variables in file2 but not in file1 */
            int varid;
            err = ncmpi_inq_varname(ncid2, i, name2);
            HANDLE_ERROR
            /* find the variable with the same name from ncid1 */
            err = ncmpi_inq_varid(ncid1, name2, &varid);
            if (err == NC_ENOTVAR) {
                if (!quiet) printf("DIFF: variable \"%s\" not found in file %s\n",
                       name2,argv[optind]);
                numHeadDIFF++;
                numVarDIFF++;
            }
        }
    }