/** * Test the darray functionality. Create a netCDF file with 4 * dimensions and 1 PIO_INT variable, and use darray to write some * data. * * @param iosysid the IO system ID. * @param ioid the ID of the decomposition. * @param num_flavors the number of IOTYPES available in this build. * @param flavor array of available iotypes. * @param my_rank rank of this task. * @param provide_fill 1 if fillvalue should be provided to PIOc_write_darray(). * @returns 0 for success, error code otherwise. */ int test_darray(int iosysid, int ioid, int num_flavors, int *flavor, int my_rank, int provide_fill) { char filename[PIO_MAX_NAME + 1]; /* Name for the output files. */ int dimids[NDIM]; /* The dimension IDs. */ int ncid; /* The ncid of the netCDF file. */ int ncid2; /* The ncid of the re-opened netCDF file. */ int varid; /* The ID of the netCDF varable. */ int ret; /* Return code. */ PIO_Offset arraylen = 16; int int_fillvalue = NC_FILL_INT; void *fillvalue = NULL; int test_data[arraylen]; int test_data2[arraylen]; int test_data_in[arraylen]; /* Initialize some data. */ for (int f = 0; f < arraylen; f++) { test_data[f] = my_rank * 10 + f; test_data2[f] = 2 * (my_rank * 10 + f); } /* Are we providing a fill value? */ if (provide_fill) fillvalue = &int_fillvalue; /* Use PIO to create the example file in each of the four * available ways. */ for (int fmt = 0; fmt < num_flavors; fmt++) { /* Create the filename. */ sprintf(filename, "data_%s_iotype_%d.nc", TEST_NAME, flavor[fmt]); /* Create the netCDF output file. */ if ((ret = PIOc_createfile(iosysid, &ncid, &flavor[fmt], filename, PIO_CLOBBER))) ERR(ret); /* Turn on fill mode. */ if ((ret = PIOc_set_fill(ncid, NC_FILL, NULL))) ERR(ret); /* Define netCDF dimensions and variable. */ for (int d = 0; d < NDIM; d++) if ((ret = PIOc_def_dim(ncid, dim_name[d], (PIO_Offset)dim_len[d], &dimids[d]))) ERR(ret); /* Define a variable. */ if ((ret = PIOc_def_var(ncid, VAR_NAME, PIO_INT, NDIM, dimids, &varid))) ERR(ret); /* End define mode. */ if ((ret = PIOc_enddef(ncid))) ERR(ret); /* Set the value of the record dimension. */ if ((ret = PIOc_setframe(ncid, varid, 0))) ERR(ret); /* Write the data. */ if ((ret = PIOc_write_darray(ncid, varid, ioid, arraylen, test_data, fillvalue))) ERR(ret); /* Set the value of the record dimension to the second record. */ if ((ret = PIOc_setframe(ncid, varid, 1))) ERR(ret); /* Write the data for the second record. */ if ((ret = PIOc_write_darray(ncid, varid, ioid, arraylen, test_data2, fillvalue))) ERR(ret); /* Close the netCDF file. */ if ((ret = PIOc_closefile(ncid))) ERR(ret); /* Reopen the file. */ if ((ret = PIOc_openfile(iosysid, &ncid2, &flavor[fmt], filename, PIO_NOWRITE))) ERR(ret); /* Set the value of the record dimension. */ if ((ret = PIOc_setframe(ncid2, varid, 0))) ERR(ret); /* Read the data. */ if ((ret = PIOc_read_darray(ncid2, varid, ioid, arraylen, test_data_in))) ERR(ret); /* Check the results. */ for (int f = 0; f < arraylen; f++) if (test_data_in[f] != test_data[f]) return ERR_WRONG; /* Set the value of the record dimension to the second record. */ if ((ret = PIOc_setframe(ncid2, varid, 1))) ERR(ret); /* Read the data. */ if ((ret = PIOc_read_darray(ncid2, varid, ioid, arraylen, test_data_in))) ERR(ret); /* Check the results. */ for (int f = 0; f < arraylen; f++) if (test_data_in[f] != test_data2[f]) return ERR_WRONG; /* Close the netCDF file. */ if ((ret = PIOc_closefile(ncid2))) ERR(ret); } return PIO_NOERR; }
/* Run tests for darray functions. */ int main(int argc, char **argv) { int my_rank; int ntasks; int num_flavors; /* Number of PIO netCDF flavors in this build. */ int flavor[NUM_FLAVORS]; /* iotypes for the supported netCDF IO flavors. */ MPI_Comm test_comm; /* A communicator for this test. */ int ret; /* Return code. */ /* Initialize test. */ if ((ret = pio_test_init2(argc, argv, &my_rank, &ntasks, MIN_NTASKS, MIN_NTASKS, -1, &test_comm))) ERR(ERR_INIT); if ((ret = PIOc_set_iosystem_error_handling(PIO_DEFAULT, PIO_RETURN_ERROR, NULL))) return ret; /* Only do something on max_ntasks tasks. */ if (my_rank < TARGET_NTASKS) { int iosysid; /* The ID for the parallel I/O system. */ int ioproc_stride = 1; /* Stride in the mpi rank between io tasks. */ int ioproc_start = 0; /* Zero based rank of first processor to be used for I/O. */ int wioid, rioid; int maplen = MAPLEN; MPI_Offset wcompmap[MAPLEN]; MPI_Offset rcompmap[MAPLEN]; int rearranger[NUM_REARRANGERS_TO_TEST] = {PIO_REARR_BOX, PIO_REARR_SUBSET}; /* Data we will write for each type. */ signed char byte_data[MAPLEN]; char char_data[MAPLEN]; short short_data[MAPLEN]; int int_data[MAPLEN]; float float_data[MAPLEN]; double double_data[MAPLEN]; #ifdef _NETCDF4 unsigned char ubyte_data[MAPLEN]; unsigned short ushort_data[MAPLEN]; unsigned int uint_data[MAPLEN]; long long int64_data[MAPLEN]; unsigned long long uint64_data[MAPLEN]; #endif /* _NETCDF4 */ /* Expected results for each type. */ signed char byte_expected[MAPLEN]; char char_expected[MAPLEN]; short short_expected[MAPLEN]; int int_expected[MAPLEN]; float float_expected[MAPLEN]; double double_expected[MAPLEN]; #ifdef _NETCDF4 unsigned char ubyte_expected[MAPLEN]; unsigned short ushort_expected[MAPLEN]; unsigned int uint_expected[MAPLEN]; long long int64_expected[MAPLEN]; unsigned long long uint64_expected[MAPLEN]; #endif /* _NETCDF4 */ /* Custom fill value for each type. */ signed char byte_fill = -2; char char_fill = 2; short short_fill = -2; int int_fill = -2; float float_fill = -2; double double_fill = -2; #ifdef _NETCDF4 unsigned char ubyte_fill = 2; unsigned short ushort_fill = 2; unsigned int uint_fill = 2; long long int64_fill = 2; unsigned long long uint64_fill = 2; #endif /* _NETCDF4 */ /* Default fill value for each type. */ signed char byte_default_fill = NC_FILL_BYTE; char char_default_fill = NC_FILL_CHAR; short short_default_fill = NC_FILL_SHORT; int int_default_fill = NC_FILL_INT; float float_default_fill = NC_FILL_FLOAT; double double_default_fill = NC_FILL_DOUBLE; #ifdef _NETCDF4 unsigned char ubyte_default_fill = NC_FILL_UBYTE; unsigned short ushort_default_fill = NC_FILL_USHORT; unsigned int uint_default_fill = NC_FILL_UINT; long long int64_default_fill = NC_FILL_INT64; unsigned long long uint64_default_fill = NC_FILL_UINT64; #endif /* _NETCDF4 */ int ret; /* Return code. */ /* Set up the compmaps. Don't forget these are 1-based * numbers, like in Fortran! */ for (int i = 0; i < MAPLEN; i++) { wcompmap[i] = i % 2 ? my_rank * MAPLEN + i + 1 : 0; /* Even values missing. */ rcompmap[i] = my_rank * MAPLEN + i + 1; } /* Figure out iotypes. */ if ((ret = get_iotypes(&num_flavors, flavor))) ERR(ret); /* Test for each rearranger. */ for (int r = 0; r < NUM_REARRANGERS_TO_TEST; r++) { /* Initialize the PIO IO system. This specifies how * many and which processors are involved in I/O. */ if ((ret = PIOc_Init_Intracomm(test_comm, NUM_IO_PROCS, ioproc_stride, ioproc_start, rearranger[r], &iosysid))) return ret; /* Test with and without custom fill values. */ for (int fv = 0; fv < NUM_TEST_CASES_FILLVALUE; fv++) { #ifndef _NETCDF4 #define NUM_TYPES 6 int test_type[NUM_TYPES] = {PIO_BYTE, PIO_CHAR, PIO_SHORT, PIO_INT, PIO_FLOAT, PIO_DOUBLE}; #else #define NUM_TYPES 11 int test_type[NUM_TYPES] = {PIO_BYTE, PIO_CHAR, PIO_SHORT, PIO_INT, PIO_FLOAT, PIO_DOUBLE, PIO_UBYTE, PIO_USHORT, PIO_UINT, PIO_INT64, PIO_UINT64}; #endif /* _NETCDF4 */ /* Determine what data to write. Put value of 42 into * array elements that will not get written. Due to * the decomposition, these will be replaced by fill * values. */ for (int i = 0; i < MAPLEN; i++) { byte_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; char_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; short_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; int_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; float_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; double_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; #ifdef _NETCDF4 ubyte_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; ushort_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; uint_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; int64_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; uint64_data[i] = i % 2 ? my_rank * MAPLEN + i + 1 : TEST_VAL_42; #endif /* _NETCDF4 */ } /* Determine what data to expect from the test. For * even values of i, the fill value will be used, and * it may be custom or default fill value. */ for (int i = 0; i < MAPLEN; i++) { byte_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? byte_default_fill : byte_fill); char_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? char_default_fill : char_fill); short_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? short_default_fill : short_fill); int_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? int_default_fill : int_fill); float_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? float_default_fill : float_fill); double_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? double_default_fill : double_fill); #ifdef _NETCDF4 ubyte_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? ubyte_default_fill : ubyte_fill); ushort_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? ushort_default_fill : ushort_fill); uint_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? uint_default_fill : uint_fill); int64_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? int64_default_fill : int64_fill); uint64_expected[i] = i % 2 ? my_rank * MAPLEN + i + 1 : (fv ? uint64_default_fill : uint64_fill); #endif /* _NETCDF4 */ } /* Test for each available type. */ for (int t = 0; t < NUM_TYPES; t++) { void *expected; void *fill; void *data; int ncid, dimid, varid; char filename[NC_MAX_NAME + 1]; switch (test_type[t]) { case PIO_BYTE: expected = byte_expected; fill = fv ? &byte_default_fill : &byte_fill; data = byte_data; break; case PIO_CHAR: expected = char_expected; fill = fv ? &char_default_fill : &char_fill; data = char_data; break; case PIO_SHORT: expected = short_expected; fill = fv ? &short_default_fill : &short_fill; data = short_data; break; case PIO_INT: expected = int_expected; fill = fv ? &int_default_fill : &int_fill; data = int_data; break; case PIO_FLOAT: expected = float_expected; fill = fv ? &float_default_fill : &float_fill; data = float_data; break; case PIO_DOUBLE: expected = double_expected; fill = fv ? &double_default_fill : &double_fill; data = double_data; break; #ifdef _NETCDF4 case PIO_UBYTE: expected = ubyte_expected; fill = fv ? &ubyte_default_fill : &ubyte_fill; data = ubyte_data; break; case PIO_USHORT: expected = ushort_expected; fill = fv ? &ushort_default_fill : &ushort_fill; data = ushort_data; break; case PIO_UINT: expected = uint_expected; fill = fv ? &uint_default_fill : &uint_fill; data = uint_data; break; case PIO_INT64: expected = int64_expected; fill = fv ? &int64_default_fill : &int64_fill; data = int64_data; break; case PIO_UINT64: expected = uint64_expected; fill = fv ? &uint64_default_fill : &uint64_fill; data = uint64_data; break; #endif /* _NETCDF4 */ default: return ERR_AWFUL; } /* Initialize decompositions. */ if ((ret = PIOc_InitDecomp(iosysid, test_type[t], NDIM1, dim_len, maplen, wcompmap, &wioid, &rearranger[r], NULL, NULL))) return ret; if ((ret = PIOc_InitDecomp(iosysid, test_type[t], NDIM1, dim_len, maplen, rcompmap, &rioid, &rearranger[r], NULL, NULL))) return ret; /* Create the test file in each of the available iotypes. */ for (int fmt = 0; fmt < num_flavors; fmt++) { PIO_Offset type_size; void *data_in; /* Byte type doesn't work with pnetcdf. */ if (flavor[fmt] == PIO_IOTYPE_PNETCDF && (test_type[t] == PIO_BYTE || test_type[t] == PIO_CHAR)) continue; /* NetCDF-4 types only work with netCDF-4 formats. */ if (test_type[t] > PIO_DOUBLE && flavor[fmt] != PIO_IOTYPE_NETCDF4C && flavor[fmt] != PIO_IOTYPE_NETCDF4P) continue; /* Put together filename. */ sprintf(filename, "%s_iotype_%d_rearr_%d_type_%d.nc", TEST_NAME, flavor[fmt], rearranger[r], test_type[t]); /* Create file. */ if ((ret = PIOc_createfile(iosysid, &ncid, &flavor[fmt], filename, NC_CLOBBER))) return ret; /* Define metadata. */ if ((ret = PIOc_def_dim(ncid, DIM_NAME, dim_len[0], &dimid))) return ret; if ((ret = PIOc_def_var(ncid, VAR_NAME, test_type[t], NDIM1, &dimid, &varid))) return ret; if ((ret = PIOc_put_att(ncid, varid, FILL_VALUE_NAME, test_type[t], 1, fill))) return ret; if ((ret = PIOc_enddef(ncid))) return ret; /* Write some data. */ if ((ret = PIOc_write_darray(ncid, varid, wioid, MAPLEN, data, fill))) return ret; if ((ret = PIOc_sync(ncid))) return ret; /* What is size of type? */ if ((ret = PIOc_inq_type(ncid, test_type[t], NULL, &type_size))) return ret; /* Allocate space to read data into. */ if (!(data_in = malloc(type_size * MAPLEN))) return PIO_ENOMEM; /* Read the data. */ if ((ret = PIOc_read_darray(ncid, varid, rioid, MAPLEN, data_in))) return ret; /* Check results. */ if (memcmp(data_in, expected, type_size * MAPLEN)) return ERR_AWFUL; /* Release storage. */ free(data_in); /* Close file. */ if ((ret = PIOc_closefile(ncid))) return ret; } /* next iotype */ /* Free decompositions. */ if ((ret = PIOc_freedecomp(iosysid, wioid))) return ret; if ((ret = PIOc_freedecomp(iosysid, rioid))) return ret; } /* next type */ } /* next fill value test case */ } /* next rearranger */ /* Finalize PIO system. */ if ((ret = PIOc_finalize(iosysid))) return ret; } /* endif my_rank < TARGET_NTASKS */ /* Finalize the MPI library. */ if ((ret = pio_test_finalize(&test_comm))) return ret; printf("%d %s SUCCESS!!\n", my_rank, TEST_NAME); return 0; }
/** * Test the darray functionality. Create a netCDF file with 3 * dimensions and 3 variable, and use PIOc_write_darray_multi() to * write one record of data to all three vars at once. * * @param iosysid the IO system ID. * @param ioid the ID of the decomposition. * @param num_flavors the number of IOTYPES available in this build. * @param flavor array of available iotypes. * @param my_rank rank of this task. * @param pio_type the type of the data. * @returns 0 for success, error code otherwise. */ int test_darray(int iosysid, int ioid, int num_flavors, int *flavor, int my_rank, int pio_type) { #define NUM_TEST_CASES_WRT_MULTI 2 #define NUM_TEST_CASES_FILLVALUE 2 char filename[PIO_MAX_NAME + 1]; /* Name for the output files. */ int dimids[NDIM]; /* The dimension IDs. */ int ncid; /* The ncid of the netCDF file. */ int ncid2; /* The ncid of the re-opened netCDF file. */ int varid[NVAR]; /* The IDs of the netCDF varables. */ int other_varid; /* The IDs of a var of different type. */ int wrong_varid[NVAR]; /* These will not work. */ PIO_Offset arraylen = 4; /* Amount of data from each task. */ void *fillvalue; /* Pointer to fill value. */ void *test_data; /* Pointer to test data we will write. */ void *test_data_in; /* Pointer to buffer we will read into. */ int ret; /* Return code. */ /* Default fill value array for each type. */ signed char byte_fill[NVAR] = {NC_FILL_BYTE, NC_FILL_BYTE, NC_FILL_BYTE}; char char_fill[NVAR] = {NC_FILL_CHAR, NC_FILL_CHAR, NC_FILL_CHAR}; short short_fill[NVAR] = {NC_FILL_SHORT, NC_FILL_SHORT, NC_FILL_SHORT}; int int_fill[NVAR] = {NC_FILL_INT, NC_FILL_INT, NC_FILL_INT}; float float_fill[NVAR] = {NC_FILL_FLOAT, NC_FILL_FLOAT, NC_FILL_FLOAT}; double double_fill[NVAR] = {NC_FILL_DOUBLE, NC_FILL_DOUBLE, NC_FILL_DOUBLE}; #ifdef _NETCDF4 unsigned char ubyte_fill[NVAR] = {NC_FILL_UBYTE, NC_FILL_UBYTE, NC_FILL_UBYTE}; unsigned short ushort_fill[NVAR] = {NC_FILL_USHORT, NC_FILL_USHORT, NC_FILL_USHORT}; unsigned int uint_fill[NVAR] = {NC_FILL_UINT, NC_FILL_UINT, NC_FILL_UINT}; long long int64_fill[NVAR] = {NC_FILL_INT64, NC_FILL_INT64, NC_FILL_INT64}; unsigned long long uint64_fill[NVAR] = {NC_FILL_UINT64, NC_FILL_UINT64, NC_FILL_UINT64}; #endif /* _NETCDF4 */ /* Test data we will write. */ signed char test_data_byte[arraylen * NVAR]; char test_data_char[arraylen * NVAR]; short test_data_short[arraylen * NVAR]; int test_data_int[arraylen * NVAR]; float test_data_float[arraylen * NVAR]; double test_data_double[arraylen * NVAR]; #ifdef _NETCDF4 unsigned char test_data_ubyte[arraylen * NVAR]; unsigned short test_data_ushort[arraylen * NVAR]; unsigned int test_data_uint[arraylen * NVAR]; long long test_data_int64[arraylen * NVAR]; unsigned long long test_data_uint64[arraylen * NVAR]; #endif /* _NETCDF4 */ /* We will read test data into these buffers. */ signed char test_data_byte_in[arraylen]; char test_data_char_in[arraylen]; short test_data_short_in[arraylen]; int test_data_int_in[arraylen]; float test_data_float_in[arraylen]; double test_data_double_in[arraylen]; #ifdef _NETCDF4 unsigned char test_data_ubyte_in[arraylen]; unsigned short test_data_ushort_in[arraylen]; unsigned int test_data_uint_in[arraylen]; long long test_data_int64_in[arraylen]; unsigned long long test_data_uint64_in[arraylen]; #endif /* _NETCDF4 */ /* Initialize a big blob of test data for NVAR vars. */ for (int f = 0; f < arraylen * NVAR; f++) { test_data_byte[f] = my_rank * 1 + f; test_data_char[f] = my_rank * 2 + f; test_data_short[f] = my_rank * 5 + f; test_data_int[f] = my_rank * 10 + f; test_data_float[f] = my_rank * 10 + f + 0.5; test_data_double[f] = my_rank * 100000 + f + 0.5; #ifdef _NETCDF4 test_data_ubyte[f] = my_rank * 3 + f; test_data_ushort[f] = my_rank * 9 + f; test_data_uint[f] = my_rank * 100 + f; test_data_int64[f] = my_rank * 10000 + f; test_data_uint64[f] = my_rank * 100000 + f; #endif /* _NETCDF4 */ } /* Use PIO to create the example file in each of the four * available ways. */ for (int fmt = 0; fmt < num_flavors; fmt++) { /* 1-byte types not working with pnetcdf. */ if (flavor[fmt] == PIO_IOTYPE_PNETCDF && (pio_type == PIO_BYTE || pio_type == PIO_CHAR)) continue; /* NetCDF-4 types only work with netCDF-4. */ if (pio_type > PIO_DOUBLE && (flavor[fmt] != PIO_IOTYPE_NETCDF4C && flavor[fmt] != PIO_IOTYPE_NETCDF4P)) continue; /* Add a couple of extra tests for the * PIOc_write_darray_multi() function. */ for (int test_multi = 0; test_multi < NUM_TEST_CASES_WRT_MULTI; test_multi++) { /* Test with/without providing a fill value to PIOc_write_darray(). */ for (int provide_fill = 0; provide_fill < NUM_TEST_CASES_FILLVALUE; provide_fill++) { /* Create the filename. */ sprintf(filename, "data_%s_iotype_%d_pio_type_%d_test_multi_%d_provide_fill_%d.nc", TEST_NAME, flavor[fmt], pio_type, test_multi, provide_fill); /* Select the fill value and data. */ switch (pio_type) { case PIO_BYTE: fillvalue = provide_fill ? byte_fill : NULL; test_data = test_data_byte; test_data_in = test_data_byte_in; break; case PIO_CHAR: fillvalue = provide_fill ? char_fill : NULL; test_data = test_data_char; test_data_in = test_data_char_in; break; case PIO_SHORT: fillvalue = provide_fill ? short_fill : NULL; test_data = test_data_short; test_data_in = test_data_short_in; break; case PIO_INT: fillvalue = provide_fill ? int_fill : NULL; test_data = test_data_int; test_data_in = test_data_int_in; break; case PIO_FLOAT: fillvalue = provide_fill ? float_fill : NULL; test_data = test_data_float; test_data_in = test_data_float_in; break; case PIO_DOUBLE: fillvalue = provide_fill ? double_fill : NULL; test_data = test_data_double; test_data_in = test_data_double_in; break; #ifdef _NETCDF4 case PIO_UBYTE: fillvalue = provide_fill ? ubyte_fill : NULL; test_data = test_data_ubyte; test_data_in = test_data_ubyte_in; break; case PIO_USHORT: fillvalue = provide_fill ? ushort_fill : NULL; test_data = test_data_ushort; test_data_in = test_data_ushort_in; break; case PIO_UINT: fillvalue = provide_fill ? uint_fill : NULL; test_data = test_data_uint; test_data_in = test_data_uint_in; break; case PIO_INT64: fillvalue = provide_fill ? int64_fill : NULL; test_data = test_data_int64; test_data_in = test_data_int64_in; break; case PIO_UINT64: fillvalue = provide_fill ? uint64_fill : NULL; test_data = test_data_uint64; test_data_in = test_data_uint64_in; break; #endif /* _NETCDF4 */ default: ERR(ERR_WRONG); } /* Create the netCDF output file. */ if ((ret = PIOc_createfile(iosysid, &ncid, &flavor[fmt], filename, PIO_CLOBBER))) ERR(ret); /* Define netCDF dimensions and variable. */ for (int d = 0; d < NDIM; d++) if ((ret = PIOc_def_dim(ncid, dim_name[d], (PIO_Offset)dim_len[d], &dimids[d]))) ERR(ret); /* Define a variable. */ for (int v = 0; v < NVAR; v++) if ((ret = PIOc_def_var(ncid, var_name[v], pio_type, NDIM, dimids, &varid[v]))) ERR(ret); /* Define a variable of a different type, to test error handling. */ int other_pio_type = pio_type < 5 ? pio_type + 1 : PIO_INT; if ((ret = PIOc_def_var(ncid, "OTHER_VAR", other_pio_type, NDIM, dimids, &other_varid))) ERR(ret); /* Leave a note. */ if ((ret = PIOc_put_att_text(ncid, NC_GLOBAL, NOTE_NAME, strlen(NOTE), NOTE))) ERR(ret); int num_stooges = TOTAL_NUMBER_OF_STOOGES; if ((ret = PIOc_put_att_int(ncid, NC_GLOBAL, TOTAL_NUMBER_OF_STOOGES_NAME, PIO_INT, 1, &num_stooges))) ERR(ret); /* End define mode. */ if ((ret = PIOc_enddef(ncid))) ERR(ret); /* Set the value of the record dimension. */ if ((ret = PIOc_setframe(ncid, varid[0], 0))) ERR(ret); int frame[NVAR] = {0, 0, 0}; int flushtodisk = test_multi; /* This will not work, because we mix var types. */ wrong_varid[0] = varid[0]; wrong_varid[1] = varid[1]; wrong_varid[0] = other_varid; // if (PIOc_write_darray_multi(ncid, wrong_varid, ioid, NVAR, arraylen, test_data, frame, // fillvalue, flushtodisk) != PIO_EINVAL) // ERR(ERR_WRONG); /* Write the data with the _multi function. */ if ((ret = PIOc_write_darray_multi(ncid, varid, ioid, NVAR, arraylen, test_data, frame, fillvalue, flushtodisk))) ERR(ret); /* Close the netCDF file. */ if ((ret = PIOc_closefile(ncid))) ERR(ret); /* Reopen the file. */ if ((ret = PIOc_openfile(iosysid, &ncid2, &flavor[fmt], filename, PIO_NOWRITE))) ERR(ret); /* Now use read_darray on each var in turn and make * sure we get correct data. */ for (int v = 0; v < NVAR; v++) { /* Set the value of the record dimension. */ if ((ret = PIOc_setframe(ncid2, varid[v], 0))) ERR(ret); /* Read the data. */ if ((ret = PIOc_read_darray(ncid2, varid[v], ioid, arraylen, test_data_in))) ERR(ret); /* Check the results. */ for (int f = 0; f < arraylen; f++) { switch (pio_type) { case PIO_BYTE: if (test_data_byte_in[f] != test_data_byte[f + arraylen * v]) return ERR_WRONG; break; case PIO_CHAR: if (test_data_char_in[f] != test_data_char[f + arraylen * v]) return ERR_WRONG; break; case PIO_SHORT: if (test_data_short_in[f] != test_data_short[f + arraylen * v]) return ERR_WRONG; break; case PIO_INT: if (test_data_int_in[f] != test_data_int[f + arraylen * v]) return ERR_WRONG; break; case PIO_FLOAT: if (test_data_float_in[f] != test_data_float[f + arraylen * v]) return ERR_WRONG; break; case PIO_DOUBLE: if (test_data_double_in[f] != test_data_double[f + arraylen * v]) return ERR_WRONG; break; #ifdef _NETCDF4 case PIO_UBYTE: if (test_data_ubyte_in[f] != test_data_ubyte[f + arraylen * v]) return ERR_WRONG; break; case PIO_USHORT: if (test_data_ushort_in[f] != test_data_ushort[f + arraylen * v]) return ERR_WRONG; break; case PIO_UINT: if (test_data_uint_in[f] != test_data_uint[f + arraylen * v]) return ERR_WRONG; break; case PIO_INT64: if (test_data_int64_in[f] != test_data_int64[f + arraylen * v]) return ERR_WRONG; break; case PIO_UINT64: if (test_data_uint64_in[f] != test_data_uint64[f + arraylen * v]) return ERR_WRONG; break; #endif /* _NETCDF4 */ default: ERR(ERR_WRONG); } } } /* Close the netCDF file. */ if ((ret = PIOc_closefile(ncid2))) ERR(ret); } /* next fillvalue test case */ } /* next test multi */ } /* next iotype */ return PIO_NOERR; }
/* @brief Check the output file. * * Use netCDF to check that the output is as expected. * * @param ntasks The number of processors running the example. * @param filename The name of the example file to check. * * @return 0 if example file is correct, non-zero otherwise. */ int check_file(int iosysid, int ntasks, char *filename, int iotype, int elements_per_pe, int my_rank, int ioid) { int ncid; /* File ID from netCDF. */ int ndims; /* Number of dimensions. */ int nvars; /* Number of variables. */ int ngatts; /* Number of global attributes. */ int unlimdimid; /* ID of unlimited dimension. */ int natts; /* Number of variable attributes. */ nc_type xtype; /* NetCDF data type of this variable. */ int ret; /* Return code for function calls. */ int dimids[NDIM3]; /* Dimension ids for this variable. */ char var_name[NC_MAX_NAME]; /* Name of the variable. */ /* size_t start[NDIM3]; /\* Zero-based index to start read. *\/ */ /* size_t count[NDIM3]; /\* Number of elements to read. *\/ */ /* int buffer[DIM_LEN_X]; /\* Buffer to read in data. *\/ */ /* int expected[DIM_LEN_X]; /\* Data values we expect to find. *\/ */ /* Open the file. */ if ((ret = PIOc_openfile_retry(iosysid, &ncid, &iotype, filename, 0, 0))) return ret; printf("opened file %s ncid = %d\n", filename, ncid); /* Check the metadata. */ if ((ret = PIOc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid))) return ret; /* Check the dimensions. */ if (ndims != NDIM3 || nvars != 1 || ngatts != 0 || unlimdimid != 0) return ERR_BAD; for (int d = 0; d < NDIM3; d++) { char my_dim_name[NC_MAX_NAME]; PIO_Offset dimlen; if ((ret = PIOc_inq_dim(ncid, d, my_dim_name, &dimlen))) return ret; if (dimlen != (d ? dim_len[d] : NUM_TIMESTEPS) || strcmp(my_dim_name, dim_name[d])) return ERR_BAD; } /* Check the variable. */ if ((ret = PIOc_inq_var(ncid, 0, var_name, &xtype, &ndims, dimids, &natts))) return ret; if (xtype != NC_INT || ndims != NDIM3 || dimids[0] != 0 || dimids[1] != 1 || dimids[2] != 2 || natts != 0) return ERR_BAD; /* Allocate storage for sample data. */ int buffer[elements_per_pe]; int buffer_in[elements_per_pe]; /* Check each timestep. */ for (int t = 0; t < NUM_TIMESTEPS; t++) { int varid = 0; /* There's only one var in sample file. */ /* This is the data we expect for this timestep. */ for (int i = 0; i < elements_per_pe; i++) buffer[i] = 100 * t + START_DATA_VAL + my_rank; /* Read one record. */ if ((ret = PIOc_setframe(ncid, varid, t))) ERR(ret); if ((ret = PIOc_read_darray(ncid, varid, ioid, elements_per_pe, buffer_in))) return ret; /* Check the results. */ for (int i = 0; i < elements_per_pe; i++) if (buffer_in[i] != buffer[i]) return ERR_BAD; } /* Close the file. */ if ((ret = PIOc_closefile(ncid))) return ret; /* Everything looks good! */ return 0; }