Beispiel #1
0
/**
 * 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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
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;
}
Beispiel #4
0
/* @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;
}