예제 #1
0
파일: tst_small.c 프로젝트: LaHaine/ohpc
/* 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;
}
예제 #2
0
파일: nc4attr.c 프로젝트: nschloe/netcdf-c
/* Read an attribute of any type, with type conversion. This may be
 * called by any of the nc_get_att_* functions. */
int
nc4_get_att_tc(int ncid, int varid, const char *name, nc_type mem_type,
	       int mem_type_is_long, void *ip)
{
   NC *nc;
   NC_HDF5_FILE_INFO_T *h5;

   LOG((3, "nc4_get_att_tc: ncid 0x%x varid %d name %s mem_type %d",
	ncid, varid, name, mem_type));

   /* Find metadata. */
   if (!(nc = nc4_find_nc_file(ncid,NULL)))
      return NC_EBADID;

   /* get netcdf-4 metadata */
   h5 = NC4_DATA(nc);
   assert(h5);

#if 0 /*def USE_PNETCDF*/
   /* Take care of files created/opened with parallel-netcdf library. */
   if (h5->pnetcdf_file)
   {
      if (mem_type == NC_UBYTE)
	 mem_type = NC_BYTE;

      switch(mem_type)
      {
	 case NC_BYTE:
	    return ncmpi_get_att_schar(nc->int_ncid, varid, name, ip);
	 case NC_CHAR:
	    return ncmpi_get_att_text(nc->int_ncid, varid, name, ip);
	 case NC_SHORT:
	    return ncmpi_get_att_short(nc->int_ncid, varid, name, ip);
	 case NC_INT:
	    if (mem_type_is_long)
	       return ncmpi_get_att_long(nc->int_ncid, varid, name, ip);
	    else
	       return ncmpi_get_att_int(nc->int_ncid, varid, name, ip);
	 case NC_FLOAT:
	    return ncmpi_get_att_float(nc->int_ncid, varid, name, ip);
	 case NC_DOUBLE:
	    return ncmpi_get_att_double(nc->int_ncid, varid, name, ip);
	 case NC_NAT:
	 default:
	    return NC_EBADTYPE;
      }
   }
#endif /* USE_PNETCDF */

   return nc4_get_att(ncid, nc, varid, name, NULL, mem_type,
		      NULL, NULL, mem_type_is_long, ip);
}
예제 #3
0
파일: tst_small.c 프로젝트: LaHaine/ohpc
/* Test a small file with one record var, which grows, and has
 * attributes. */
static int
test_one_growing_with_att(const char *testfile, int cmode)
{
   int err, ncid, dimid, varid;
   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 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); 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;
      err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR
      sprintf(att_name, "a_%d", data[r]);
      err=ncmpi_redef(ncid); ERR
      err=ncmpi_put_att_text(ncid, varid, att_name, 1, &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_get_att_text(ncid, varid, att_name, &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;
}
예제 #4
0
파일: tst_small.c 프로젝트: LaHaine/ohpc
static int
test_small_atts(const char *testfile, int cmode)
{
   int ncid, err;
   char att[MAX_LEN + 1], att_in[MAX_LEN + 1], source[MAX_LEN + 1] = "0123456";
   int ndims, nvars, natts, unlimdimid;
   MPI_Offset len_in;
   int t, f;
   
   /* Run this with and without fill mode. */
   for (f = 0; f < 2; f++)
   {
      /* Create small files with an attribute that grows by one each
       * time. */
      for (t = 1; t < MAX_LEN; t++)
      {
	 /* Create null-terminated text string of correct length. */
	 strncpy(att, source, t);
         att[t] = '\0';
	 
	 /* Create a file with one attribute. */
         err = ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
	 err = ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, t + 1, att); ERR
	 if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); 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(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
	 if (ndims != 0 && nvars != 0 && natts != 1 && unlimdimid != -1) {printf("Error at line %d\n",__LINE__);return 1;}
	 err=ncmpi_inq_attlen(ncid, NC_GLOBAL, ATT_NAME, &len_in); ERR
	 if (len_in != t + 1) {printf("Error at line %d\n",__LINE__);return 1;}
	 err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, att_in); ERR
	 if (strncmp(att_in, att, t)) {printf("Error at line %d\n",__LINE__);return 1;}
	 err=ncmpi_close(ncid); ERR
      }
   }
   return 0;
}
예제 #5
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;
}
예제 #6
0
파일: tst_norm.c 프로젝트: LaHaine/ohpc
static
int tst_norm(char *filename, int cmode)
{
   int ncid, dimid, varid;
   int dimids[NDIMS];

   /* unnormalized UTF-8 encoding for Unicode 8-character "Hello" in Greek: */
   unsigned char uname_utf8[] = {
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x83,		/* COMBINING TILDE */
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x88,		/* COMBINING DIAERESIS */
       0x41,              	/* LATIN CAPITAL LETTER A */
       0xCC, 0x8A,		/* COMBINING RING ABOVE */
       0x43,			/* LATIN CAPITAL LETTER C */
       0xCC, 0xA7,		/* COMBINING CEDILLA */
       0x45,			/* LATIN CAPITAL LETTER E */
       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
       0x45,			/* LATIN CAPITAL LETTER E */
       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
       0x45,			/* LATIN CAPITAL LETTER E */
       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
       0x45,			/* LATIN CAPITAL LETTER E */
       0xCC, 0x88,		/* COMBINING DIAERESIS */
       0x49,			/* LATIN CAPITAL LETTER I */
       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
       0x49,			/* LATIN CAPITAL LETTER I */
       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
       0x49,			/* LATIN CAPITAL LETTER I */
       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
       0x49,			/* LATIN CAPITAL LETTER I */
       0xCC, 0x88,		/* COMBINING DIAERESIS */
       0x4E,			/* LATIN CAPITAL LETTER N */
       0xCC, 0x83,		/* COMBINING TILDE */
       0x00
   };

   /* NFC normalized UTF-8 encoding for same Unicode string: */
   unsigned char nname_utf8[] = {
       0xC3, 0x80,	        /* LATIN CAPITAL LETTER A WITH GRAVE */
       0xC3, 0x81,	        /* LATIN CAPITAL LETTER A WITH ACUTE */
       0xC3, 0x82,	        /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
       0xC3, 0x83,	        /* LATIN CAPITAL LETTER A WITH TILDE */
       0xC3, 0x84,		/* LATIN CAPITAL LETTER A WITH DIAERESIS */
       0xC3, 0x85,		/* LATIN CAPITAL LETTER A WITH RING ABOVE */
       0xC3, 0x87,		/* LATIN CAPITAL LETTER C WITH CEDILLA */
       0xC3, 0x88,		/* LATIN CAPITAL LETTER E WITH GRAVE */
       0xC3, 0x89,		/* LATIN CAPITAL LETTER E WITH ACUTE */
       0xC3, 0x8A,		/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
       0xC3, 0x8B,		/* LATIN CAPITAL LETTER E WITH DIAERESIS */
       0xC3, 0x8C,		/* LATIN CAPITAL LETTER I WITH GRAVE */
       0xC3, 0x8D,		/* LATIN CAPITAL LETTER I WITH ACUTE */
       0xC3, 0x8E,		/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
       0xC3, 0x8F,		/* LATIN CAPITAL LETTER I WITH DIAERESIS */
       0xC3, 0x91,	        /* LATIN CAPITAL LETTER N WITH TILDE */
       0x00
   };

/* Unnormalized name used for dimension, variable, and attribute value */
#define UNAME ((char *) uname_utf8)
#define UNAMELEN (sizeof uname_utf8)
/* Normalized name */
#define NNAME ((char *) nname_utf8)
#define NNAMELEN (sizeof nname_utf8)

   char name_in[UNAMELEN + 1], strings_in[UNAMELEN + 1];
   nc_type att_type;
   MPI_Offset att_len;
   int err, dimid_in, varid_in, attnum_in;
   int attvals[] = {42};
#define ATTNUM ((sizeof attvals)/(sizeof attvals[0]))

   err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR

   /* Define dimension with unnormalized Unicode UTF-8 encoded name */
   err = ncmpi_def_dim(ncid, UNAME, NX, &dimid); ERR
   dimids[0] = dimid;

   /* Define variable with same name */
   err = ncmpi_def_var(ncid, UNAME, NC_CHAR, NDIMS, dimids, &varid); ERR

   /* Create string attribute with same value */
   err = ncmpi_put_att_text(ncid, varid, UNITS, UNAMELEN, UNAME); ERR

   /* Create int attribute with same name */
   err = ncmpi_put_att_int(ncid, varid, UNAME, NC_INT, ATTNUM, attvals); ERR

   /* Try to create dimension and variable with NFC-normalized
    * version of same name.  These should fail, as unnormalized name
    * should have been normalized in library, so these are attempts to
    * create duplicate netCDF objects. */
   if ((err = ncmpi_def_dim(ncid, NNAME, NX, &dimid)) != NC_ENAMEINUSE) {
       printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err);
       return 1;
   }

   if ((err=ncmpi_def_var(ncid, NNAME, NC_CHAR, NDIMS, dimids, &varid)) != NC_ENAMEINUSE) {
       printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err);
       return 1;
   }
   err = ncmpi_enddef(ncid); ERR

   /* Write string data, UTF-8 encoded, to the file */
   err = ncmpi_put_var_text_all(ncid, varid, UNAME); ERR
   err = ncmpi_close(ncid); ERR

   /* Check it out. */
   err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
   err = ncmpi_inq_varid(ncid, UNAME, &varid); ERR
   err = ncmpi_inq_varname(ncid, varid, name_in); ERR
   err = strncmp(NNAME, name_in, NNAMELEN); ERR
   err = ncmpi_inq_varid(ncid, NNAME, &varid_in); ERR
   if ((err = ncmpi_inq_dimid(ncid, UNAME, &dimid_in)) || dimid != dimid_in)
       {printf("Error at line %d\n",__LINE__);return 1;}
   if ((err = ncmpi_inq_dimid(ncid, NNAME, &dimid_in)) || dimid != dimid_in)
       {printf("Error at line %d\n",__LINE__);return 1;}
   err = ncmpi_inq_att(ncid, varid, UNITS, &att_type, &att_len); ERR
   if ( att_type != NC_CHAR || att_len != UNAMELEN)
       {printf("Error at line %d\n",__LINE__);return 1;}
   err = ncmpi_get_att_text(ncid, varid, UNITS, strings_in); ERR
   strings_in[UNAMELEN] = '\0';
   err = strncmp(UNAME, strings_in, UNAMELEN); ERR
   if ((err = ncmpi_inq_attid(ncid, varid, UNAME, &attnum_in)) || ATTNUM != attnum_in)
       {printf("Error at line %d\n",__LINE__);return 1;}
   if ((err = ncmpi_inq_attid(ncid, varid, NNAME, &attnum_in)) || ATTNUM != attnum_in)
       {printf("Error at line %d\n",__LINE__);return 1;}
   err = ncmpi_close(ncid); ERR

   return 0;
}