/* Test a small file with one var and one att. */ static int test_one_with_att(const char *testfile, int cmode) { int err, ncid, dimid, varid; char data = 'h', data_in; int ndims, nvars, natts, unlimdimid; MPI_Offset start[NDIMS], count[NDIMS]; /* Create a file with one ulimited dimensions, and one var. */ err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, 1, &data); ERR err=ncmpi_enddef(ncid); ERR /* Write one record of var data, a single character. */ count[0] = 1; start[0] = 0; err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data); ERR /* We're done! */ err=ncmpi_close(ncid); ERR /* Reopen the file and check it. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;} err=ncmpi_get_var_text_all(ncid, varid, &data_in); ERR if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;} err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, &data_in); ERR if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;} err=ncmpi_close(ncid); ERR return 0; }
/* Test a small file with two record vars, which grow, and has * attributes added. */ static int test_two_growing_with_att(const char *testfile, int cmode) { int err, ncid, dimid, varid[NUM_VARS]; char data[MAX_RECS], data_in; char att_name[NC_MAX_NAME + 1]; MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in; int v, r; /* Create a file with one ulimited dimensions, and one var. */ err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid[0]); ERR err=ncmpi_def_var(ncid, VAR_NAME2, NC_CHAR, 1, &dimid, &varid[1]); ERR err=ncmpi_close(ncid); ERR /* Create some phoney data. */ for (data[0] = 'a', r = 1; r < MAX_RECS; r++) data[r] = data[r - 1] + 1; /* Normally one would not close and reopen the file for each * record, nor add an attribute each time I add a record, but I am * giving the library a little work-out here... */ for (r = 0; r < MAX_RECS; r++) { /* Write one record of var data, a single character. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR count[0] = 1; start[0] = r; sprintf(att_name, "a_%d", data[r]); for (v = 0; v < NUM_VARS; v++) { err=ncmpi_put_vara_text_all(ncid, varid[v], start, count, &data[r]); ERR err=ncmpi_redef(ncid); ERR err=ncmpi_put_att_text(ncid, varid[v], att_name, 1, &data[r]); ERR err=ncmpi_enddef(ncid); ERR } err=ncmpi_close(ncid); ERR /* Reopen the file and check it. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;} index[0] = r; err=ncmpi_begin_indep_data(ncid); ERR for (v = 0; v < NUM_VARS; v++) { err=ncmpi_get_var1_text(ncid, varid[v], index, &data_in); ERR if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;} } err=ncmpi_close(ncid); ERR } /* Next record. */ return 0; }
/* Test a small file with an unlimited dimension. NOTE: Normally I * write a NULL terminator for my attributes and text strings, but * this reproduces a bug that a fortran user sent us. So string data * are written to the file without null terminators. - Ed */ static int test_small_unlim(const char *testfile, int cmode) { int i, err, ncid, dimids[NDIMS], varid; char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN]; int ndims, nvars, natts, unlimdimid; MPI_Offset start[NDIMS], count[NDIMS]; /* Create null-terminated text strings of correct length. */ /*for (i = 0; i < NUM_VALS; i++) strcpy(data[i], source);*/ strcpy(data[0], "2005-04-11_12:00:00"); strcpy(data[1], "2005-04-11_13:00:00"); /* Create a file with two dimensions, one unlimited, and one * var, and a global att. */ err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, dimids); ERR err=ncmpi_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1]); ERR err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 2, dimids, &varid); ERR err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE); ERR err=ncmpi_enddef(ncid); ERR /* Write some records of var data. */ count[0] = 1; count[1] = STR_LEN; start[1] = 0; for (start[0] = 0; start[0] < NUM_VALS; start[0]++) { err=ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]); ERR } /* We're done! */ err=ncmpi_close(ncid); ERR /* Reopen the file and check it. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;} err=ncmpi_get_var_text_all(ncid, varid, (char *)data_in); ERR for (i = 0; i < NUM_VALS; i++) /* if (strncmp(data[i], data_in[i], STR_LEN)) {printf("Error at line %d\n",__LINE__);return 1;} */ if (strncmp(data[i], data_in[i], STR_LEN)) { printf("i=%d data=%s data_in=%s\n",i,data[i],data_in[i]); } err=ncmpi_close(ncid); ERR return 0; }
/* Test a small file with one record var, which grows. */ static int test_one_growing(const char *testfile, int cmode) { int err, ncid, dimid, varid; char data[MAX_RECS], data_in; MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in; int r, f; /* Create some phoney data. */ for (data[0] = 'a', r = 1; r < MAX_RECS; r++) data[r] = data[r - 1] + 1; /* Run this with and without fill mode. */ for (f = 0; f < 2; f++) { /* Create a file with one ulimited dimensions, and one var. */ err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR err=ncmpi_close(ncid); ERR /* Normally one would not close and reopen the file for each * record, but I am giving the library a little work-out here... */ for (r = 0; r < MAX_RECS; r++) { /* Write one record of var data, a single character. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR /* if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR} */ count[0] = 1; start[0] = r; err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR err=ncmpi_close(ncid); ERR /* Reopen the file and check it. */ err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;} index[0] = r; err=ncmpi_begin_indep_data(ncid); ERR err=ncmpi_get_var1_text(ncid, 0, index, &data_in); ERR if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;} err=ncmpi_close(ncid); ERR } /* Next record. */ } return 0; }
/* write out variable's data from in-memory structure */ void load_netcdf(void *rec_start) { int i, idim; int stat = NC_NOERR; MPI_Offset *start, *count; char *charvalp = NULL; short *shortvalp = NULL; int *intvalp = NULL; float *floatvalp = NULL; double *doublevalp = NULL; unsigned char *ubytevalp = NULL; unsigned short *ushortvalp = NULL; unsigned int *uintvalp = NULL; long long *int64valp = NULL; unsigned long long *uint64valp = NULL; MPI_Offset total_size; /* load values into variable */ switch (vars[varnum].type) { case NC_CHAR: case NC_BYTE: charvalp = (char *) rec_start; break; case NC_SHORT: shortvalp = (short *) rec_start; break; case NC_INT: intvalp = (int *) rec_start; break; case NC_FLOAT: floatvalp = (float *) rec_start; break; case NC_DOUBLE: doublevalp = (double *) rec_start; break; case NC_UBYTE: ubytevalp = (unsigned char *) rec_start; break; case NC_USHORT: ushortvalp = (unsigned short *) rec_start; break; case NC_UINT: uintvalp = (unsigned int *) rec_start; break; case NC_INT64: int64valp = (long long *) rec_start; break; case NC_UINT64: uint64valp = (unsigned long long *) rec_start; break; default: derror("Unhandled type %d\n", vars[varnum].type); break; } start = (MPI_Offset*) malloc(vars[varnum].ndims * 2 * sizeof(MPI_Offset)); count = start + vars[varnum].ndims; if (vars[varnum].ndims > 0) { /* initialize start to upper left corner (0,0,0,...) */ start[0] = 0; if (vars[varnum].dims[0] == rec_dim) { count[0] = vars[varnum].nrecs; } else { count[0] = dims[vars[varnum].dims[0]].size; } } for (idim = 1; idim < vars[varnum].ndims; idim++) { start[idim] = 0; count[idim] = dims[vars[varnum].dims[idim]].size; } total_size = nctypesize(vars[varnum].type); for (idim=0; idim<vars[varnum].ndims; idim++) total_size *= count[idim]; /* If the total put size is more than 2GB, then put one subarray at a time. * Here the subarray is from 1, 2, ... ndims, except 0. * This is not a perfect solution. To be improved. */ if (total_size > INT_MAX) { MPI_Offset nchunks=count[0]; MPI_Offset subarray_nelems=1; for (idim=1; idim<vars[varnum].ndims; idim++) subarray_nelems *= count[idim]; count[0] = 1; switch (vars[varnum].type) { case NC_BYTE: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_schar_all(ncid, varnum, start, count, (signed char *)charvalp); check_err(stat, "ncmpi_put_vara_schar_all", __func__, __LINE__, __FILE__); charvalp += subarray_nelems; } break; case NC_CHAR: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_text_all(ncid, varnum, start, count, charvalp); check_err(stat, "ncmpi_put_vara_text_all", __func__, __LINE__, __FILE__); charvalp += subarray_nelems; } break; case NC_SHORT: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_short_all(ncid, varnum, start, count, shortvalp); check_err(stat, "ncmpi_put_vara_short_all", __func__, __LINE__, __FILE__); shortvalp += subarray_nelems; } break; case NC_INT: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_int_all(ncid, varnum, start, count, intvalp); check_err(stat, "ncmpi_put_vara_int_all", __func__, __LINE__, __FILE__); intvalp += subarray_nelems; } break; case NC_FLOAT: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_float_all(ncid, varnum, start, count, floatvalp); check_err(stat, "ncmpi_put_vara_float_all", __func__, __LINE__, __FILE__); floatvalp += subarray_nelems; } break; case NC_DOUBLE: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_double_all(ncid, varnum, start, count, doublevalp); check_err(stat, "ncmpi_put_vara_double_all", __func__, __LINE__, __FILE__); doublevalp += subarray_nelems; } break; case NC_UBYTE: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_uchar_all(ncid, varnum, start, count, ubytevalp); check_err(stat, "ncmpi_put_vara_uchar_all", __func__, __LINE__, __FILE__); ubytevalp += subarray_nelems; } break; case NC_USHORT: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_ushort_all(ncid, varnum, start, count, ushortvalp); check_err(stat, "ncmpi_put_vara_ushort_all", __func__, __LINE__, __FILE__); ushortvalp += subarray_nelems; } break; case NC_UINT: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_uint_all(ncid, varnum, start, count, uintvalp); check_err(stat, "ncmpi_put_vara_uint_all", __func__, __LINE__, __FILE__); uintvalp += subarray_nelems; } break; case NC_INT64: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_longlong_all(ncid, varnum, start, count, int64valp); check_err(stat, "ncmpi_put_vara_longlong_all", __func__, __LINE__, __FILE__); int64valp += subarray_nelems; } break; case NC_UINT64: for (i=0; i<nchunks; i++) { start[0] = i; stat = ncmpi_put_vara_ulonglong_all(ncid, varnum, start, count, uint64valp); check_err(stat, "ncmpi_put_vara_ulonglong_all", __func__, __LINE__, __FILE__); uint64valp += subarray_nelems; } break; default: derror("Unhandled type %d\n", vars[varnum].type); break; } } else { switch (vars[varnum].type) { case NC_BYTE: stat = ncmpi_put_vara_schar_all(ncid, varnum, start, count, (signed char *)charvalp); check_err(stat, "ncmpi_put_vara_schar_all", __func__, __LINE__, __FILE__); break; case NC_CHAR: stat = ncmpi_put_vara_text_all(ncid, varnum, start, count, charvalp); check_err(stat, "ncmpi_put_vara_text_all", __func__, __LINE__, __FILE__); break; case NC_SHORT: stat = ncmpi_put_vara_short_all(ncid, varnum, start, count, shortvalp); check_err(stat, "ncmpi_put_vara_short_all", __func__, __LINE__, __FILE__); break; case NC_INT: stat = ncmpi_put_vara_int_all(ncid, varnum, start, count, intvalp); check_err(stat, "ncmpi_put_vara_int_all", __func__, __LINE__, __FILE__); break; case NC_FLOAT: stat = ncmpi_put_vara_float_all(ncid, varnum, start, count, floatvalp); check_err(stat, "ncmpi_put_vara_float_all", __func__, __LINE__, __FILE__); break; case NC_DOUBLE: stat = ncmpi_put_vara_double_all(ncid, varnum, start, count, doublevalp); check_err(stat, "ncmpi_put_vara_double_all", __func__, __LINE__, __FILE__); break; case NC_UBYTE: stat = ncmpi_put_vara_uchar_all(ncid, varnum, start, count, ubytevalp); check_err(stat, "ncmpi_put_vara_uchar_all", __func__, __LINE__, __FILE__); break; case NC_USHORT: stat = ncmpi_put_vara_ushort_all(ncid, varnum, start, count, ushortvalp); check_err(stat, "ncmpi_put_vara_ushort_all", __func__, __LINE__, __FILE__); break; case NC_UINT: stat = ncmpi_put_vara_uint_all(ncid, varnum, start, count, uintvalp); check_err(stat, "ncmpi_put_vara_uint_all", __func__, __LINE__, __FILE__); break; case NC_INT64: stat = ncmpi_put_vara_longlong_all(ncid, varnum, start, count, int64valp); check_err(stat, "ncmpi_put_vara_longlong_all", __func__, __LINE__, __FILE__); break; case NC_UINT64: stat = ncmpi_put_vara_ulonglong_all(ncid, varnum, start, count, uint64valp); check_err(stat, "ncmpi_put_vara_ulonglong_all", __func__, __LINE__, __FILE__); break; default: derror("Unhandled type %d\n", vars[varnum].type); break; } } free(start); }