Index: /tags/v1-0-3/test/nc_test/depend =================================================================== --- /tags/v1-0-3/test/nc_test/depend (revision 208) +++ /tags/v1-0-3/test/nc_test/depend (revision 208) @@ -0,0 +1,25 @@ +error.o: error.c +nc_test.o: $(srcdir)/../../src/lib/pnetcdf.h +nc_test.o: error.h +nc_test.o: nc_test.c +nc_test.o: tests.h +test_get.o: $(srcdir)/../../src/lib/pnetcdf.h +test_get.o: error.h +test_get.o: test_get.c +test_get.o: tests.h +test_put.o: $(srcdir)/../../src/lib/pnetcdf.h +test_put.o: error.h +test_put.o: test_put.c +test_put.o: tests.h +test_read.o: $(srcdir)/../../src/lib/pnetcdf.h +test_read.o: error.h +test_read.o: test_read.c +test_read.o: tests.h +test_write.o: $(srcdir)/../../src/lib/pnetcdf.h +test_write.o: error.h +test_write.o: test_write.c +test_write.o: tests.h +util.o: $(srcdir)/../../src/lib/pnetcdf.h +util.o: error.h +util.o: tests.h +util.o: util.c Index: /tags/v1-0-3/test/nc_test/error.h =================================================================== --- /tags/v1-0-3/test/nc_test/error.h (revision 430) +++ /tags/v1-0-3/test/nc_test/error.h (revision 430) @@ -0,0 +1,35 @@ +/********************************************************************* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header $ + *********************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Print error message to stderr, don't exit */ +extern void error (const char *fmt, ...) +#ifdef _GNUC_ +__attribute__ ((format (printf, 1, 2))) +#endif +; + + +void print(const char *fmt, ...) +#ifdef _GNUC_ +__attribute__ ((format (printf, 1, 2))) +#endif +; + + +extern int ifFail(const int expr, const int line, const char *file); + +extern void +print_n_size_t(size_t nelems, const MPI_Offset *array); + +#ifdef __cplusplus +} +#endif + +#define IF(EXPR) if (ifFail(EXPR, __LINE__, __FILE__)) Index: /tags/v1-0-3/test/nc_test/nc_test.c =================================================================== --- /tags/v1-0-3/test/nc_test/nc_test.c (revision 535) +++ /tags/v1-0-3/test/nc_test/nc_test.c (revision 535) @@ -0,0 +1,342 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include +#include "tests.h" + +/* + * Test driver for netCDF-3 interface. This program performs tests against + * the netCDF-3 specification for all user-level functions in an + * implementation of the netCDF library. + * + * Unless invoked with "-r" (read_only) option, must be invoked from a + * directory in which the invoker has write permission. + * + * Files: + * The read-only tests read files: + * test.nc (see below) + * test_get.c (used merely as an example of a non-netCDF file) + * + * The write tests + * read test.nc (see below) + * write scratch.nc (deleted after each test) + * + * The file test.nc is created by running ncmpi_test with the -c (create) option. + * It is described by the following global variables. + */ + + +/* + * global variables (defined by command line processing in main()) + * related use of CDF-1 vs CDF-2 file formats + */ +int use_cdf2 = 0; /* 0: use CDF-1, 1: use CDF-2 */ +int extra_flags = 0; /* if using CDF-2 format, will be set to NC_64BIT_OFFSET */ + +/* + * global variables (defined by function init_gvars) describing file test.nc + */ +char dim_name[NDIMS][3]; +MPI_Offset dim_len[NDIMS]; +char var_name[NVARS][2+MAX_RANK]; +ncmpi_type var_type[NVARS]; +size_t var_rank[NVARS]; +int var_dimid[NVARS][MAX_RANK]; +MPI_Offset var_shape[NVARS][MAX_RANK]; +size_t var_nels[NVARS]; +size_t var_natts[NVARS]; +char att_name[NVARS][MAX_NATTS][2]; +char gatt_name[NGATTS][3]; +ncmpi_type att_type[NVARS][NGATTS]; +ncmpi_type gatt_type[NGATTS]; +size_t att_len[NVARS][MAX_NATTS]; +size_t gatt_len[NGATTS]; + +/* + * command-line options + */ +static int create_file; /* if 1, create file test.nc */ +int read_only; /* if 1, don't try to change files */ +int verbose; /* if 1, print details of tests */ +int max_nmpt; /* max. number of messages per test */ + +/* + * Misc. global variables + */ +int nfails; /* number of failures in specific test */ +static char *progname; +char testfile[] = "test.nc"; /* read-only testfile */ +char scratch[] = "scratch.nc"; /* writable scratch file */ +MPI_Comm comm = MPI_COMM_WORLD; /* mpi communicator for parallel-netcdf */ + +static void +usage(void) +{ + error("%s [-hrv] [-n ]\n", progname); + error(" [-h] Print help\n" ); + error(" [-c] Create file test.nc (Do not do tests)\n" ); + error(" [-r] Just do read-only tests\n" ); + error(" [-v] Verbose mode\n" ); + error(" [-2] (with -c) create file with CDF-2 format\n" ); + error(" [-n ] max. number of messages per test (Default: 8)\n"); +} + +#define NC_TEST(func) \ + print( "*** Testing " #func " ... ");\ + nfails = 0;\ + test_ ## func();\ + nfailsTotal += nfails;\ + if (verbose) \ + print("\n"); \ + if ( nfails == 0) \ + print( "ok\n");\ + else\ + print( "\n\t### %d FAILURES TESTING %s! ###\n", nfails, #func) + + +#if 1 /* both CRAY MPP and OSF/1 Alpha systems need this */ +#include +#endif /* T90 */ + +int +main(int argc, char *argv[]) +{ + extern char *optarg; + int c; + int nfailsTotal = 0; /* total number of failures */ + +#if 1 /* both CRAY MPP and OSF/1 Alpha systems need this */ + /* + * Some of the extreme test assignments in this program trigger + * floating point exceptions on CRAY T90 + */ + (void) signal(SIGFPE, SIG_IGN); +#endif + + MPI_Init(&argc, &argv); + + progname = argv[0]; + create_file = 0; /* file test.nc will normally already exist */ + read_only = 0; /* assume may write in test dir as default */ + verbose = 0; + max_nmpt = 8; + while ((c = getopt(argc, argv, "c2hrvn:")) != EOF) + switch(c) { + case 'c': /* Create file test.nc */ + create_file = 1; + break; + case 'r': /* just perform read-only tests */ + read_only = 1; + break; + case 'v': /* verbose mode */ + verbose = 1; + break; + case 'n': /* verbose mode */ + max_nmpt = atoi(optarg); + break; + case '2': + use_cdf2 = 1; + extra_flags = NC_64BIT_OFFSET; + break; + case 'h': + case '?': + usage(); + return 1; + } + + /* Initialize global variables defining test file */ + init_gvars(); + + if ( create_file ) { + write_file(testfile); + MPI_Finalize(); + return nfailsTotal > 0; + } + + /* delete any existing scratch netCDF file */ + if ( ! read_only ) + ncmpi_delete(scratch, MPI_INFO_NULL); + + /* Test read-only functions, using pregenerated test-file */ + NC_TEST(ncmpi_strerror); + NC_TEST(ncmpi_open); + NC_TEST(ncmpi_close); + NC_TEST(ncmpi_inq); + NC_TEST(ncmpi_inq_dimid); + NC_TEST(ncmpi_inq_dim); + NC_TEST(ncmpi_inq_dimlen); + NC_TEST(ncmpi_inq_dimname); + NC_TEST(ncmpi_inq_varid); + NC_TEST(ncmpi_inq_var); + NC_TEST(ncmpi_inq_natts); + NC_TEST(ncmpi_inq_ndims); + NC_TEST(ncmpi_inq_nvars); + NC_TEST(ncmpi_inq_unlimdim); + NC_TEST(ncmpi_inq_vardimid); + NC_TEST(ncmpi_inq_varname); + NC_TEST(ncmpi_inq_varnatts); + NC_TEST(ncmpi_inq_varndims); + NC_TEST(ncmpi_inq_vartype); + NC_TEST(ncmpi_get_var_text); + NC_TEST(ncmpi_get_var_uchar); + NC_TEST(ncmpi_get_var_schar); + NC_TEST(ncmpi_get_var_short); + NC_TEST(ncmpi_get_var_int); + NC_TEST(ncmpi_get_var_long); + NC_TEST(ncmpi_get_var_float); + NC_TEST(ncmpi_get_var_double); + NC_TEST(ncmpi_get_var1_text); + NC_TEST(ncmpi_get_var1_uchar); + NC_TEST(ncmpi_get_var1_schar); + NC_TEST(ncmpi_get_var1_short); + NC_TEST(ncmpi_get_var1_int); + NC_TEST(ncmpi_get_var1_long); + NC_TEST(ncmpi_get_var1_float); + NC_TEST(ncmpi_get_var1_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_get_var1); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_get_vara_text); + NC_TEST(ncmpi_get_vara_uchar); + NC_TEST(ncmpi_get_vara_schar); + NC_TEST(ncmpi_get_vara_short); + NC_TEST(ncmpi_get_vara_int); + NC_TEST(ncmpi_get_vara_long); + NC_TEST(ncmpi_get_vara_float); + NC_TEST(ncmpi_get_vara_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_get_vara); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_get_vars_text); + NC_TEST(ncmpi_get_vars_uchar); + NC_TEST(ncmpi_get_vars_schar); + NC_TEST(ncmpi_get_vars_short); + NC_TEST(ncmpi_get_vars_int); + NC_TEST(ncmpi_get_vars_long); + NC_TEST(ncmpi_get_vars_float); + NC_TEST(ncmpi_get_vars_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_get_vars); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_get_varm_text); + NC_TEST(ncmpi_get_varm_uchar); + NC_TEST(ncmpi_get_varm_schar); + NC_TEST(ncmpi_get_varm_short); + NC_TEST(ncmpi_get_varm_int); + NC_TEST(ncmpi_get_varm_long); + NC_TEST(ncmpi_get_varm_float); + NC_TEST(ncmpi_get_varm_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_get_varm); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_get_att_text); + NC_TEST(ncmpi_get_att_uchar); + NC_TEST(ncmpi_get_att_schar); + NC_TEST(ncmpi_get_att_short); + NC_TEST(ncmpi_get_att_int); + NC_TEST(ncmpi_get_att_long); + NC_TEST(ncmpi_get_att_float); + NC_TEST(ncmpi_get_att_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_get_att); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_inq_att); + NC_TEST(ncmpi_inq_attname); + NC_TEST(ncmpi_inq_attid); + NC_TEST(ncmpi_inq_attlen); + NC_TEST(ncmpi_inq_atttype); + + /* Test write functions */ + if (! read_only) { + NC_TEST(ncmpi_create); + NC_TEST(ncmpi_redef); + /* NC_TEST(ncmpi_enddef); *//* redundant */ + NC_TEST(ncmpi_sync); + NC_TEST(ncmpi_abort); + NC_TEST(ncmpi_def_dim); + NC_TEST(ncmpi_rename_dim); + NC_TEST(ncmpi_def_var); + NC_TEST(ncmpi_put_var_text); + NC_TEST(ncmpi_put_var_uchar); + NC_TEST(ncmpi_put_var_schar); + NC_TEST(ncmpi_put_var_short); + NC_TEST(ncmpi_put_var_int); + NC_TEST(ncmpi_put_var_long); + NC_TEST(ncmpi_put_var_float); + NC_TEST(ncmpi_put_var_double); + NC_TEST(ncmpi_put_var1_text); + NC_TEST(ncmpi_put_var1_uchar); + NC_TEST(ncmpi_put_var1_schar); + NC_TEST(ncmpi_put_var1_short); + NC_TEST(ncmpi_put_var1_int); + NC_TEST(ncmpi_put_var1_long); + NC_TEST(ncmpi_put_var1_float); + NC_TEST(ncmpi_put_var1_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_put_var1); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_put_vara_text); + NC_TEST(ncmpi_put_vara_uchar); + NC_TEST(ncmpi_put_vara_schar); + NC_TEST(ncmpi_put_vara_short); + NC_TEST(ncmpi_put_vara_int); + NC_TEST(ncmpi_put_vara_long); + NC_TEST(ncmpi_put_vara_float); + NC_TEST(ncmpi_put_vara_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_put_vara); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_put_vars_text); + NC_TEST(ncmpi_put_vars_uchar); + NC_TEST(ncmpi_put_vars_schar); + NC_TEST(ncmpi_put_vars_short); + NC_TEST(ncmpi_put_vars_int); + NC_TEST(ncmpi_put_vars_long); + NC_TEST(ncmpi_put_vars_float); + NC_TEST(ncmpi_put_vars_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_put_vars); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_put_varm_text); + NC_TEST(ncmpi_put_varm_uchar); + NC_TEST(ncmpi_put_varm_schar); + NC_TEST(ncmpi_put_varm_short); + NC_TEST(ncmpi_put_varm_int); + NC_TEST(ncmpi_put_varm_long); + NC_TEST(ncmpi_put_varm_float); + NC_TEST(ncmpi_put_varm_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_put_varm); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_rename_var); + NC_TEST(ncmpi_put_att_text); + NC_TEST(ncmpi_put_att_uchar); + NC_TEST(ncmpi_put_att_schar); + NC_TEST(ncmpi_put_att_short); + NC_TEST(ncmpi_put_att_int); + NC_TEST(ncmpi_put_att_long); + NC_TEST(ncmpi_put_att_float); + NC_TEST(ncmpi_put_att_double); +#ifdef TEST_VOIDSTAR + NC_TEST(ncmpi_put_att); +#endif /* TEST_VOIDSTAR */ + NC_TEST(ncmpi_copy_att); + NC_TEST(ncmpi_rename_att); + NC_TEST(ncmpi_del_att); + NC_TEST(ncmpi_set_fill); + + NC_TEST(ncmpi_delete); + } + + MPI_Finalize(); + + print( "\nNOTE: parallel-netcdf expects to see 2 failures"); + print( "\nTotal number of failures: %d\n", nfailsTotal); + if (nfailsTotal == 2) + return 0; + else + return nfailsTotal > 0; +} Index: /tags/v1-0-3/test/nc_test/Makefile.in =================================================================== --- /tags/v1-0-3/test/nc_test/Makefile.in (revision 414) +++ /tags/v1-0-3/test/nc_test/Makefile.in (revision 414) @@ -0,0 +1,82 @@ +# Makefile for netCDF (semi)exhaustive test. +# +# $Id$ + +srcdir = @srcdir@ +VPATH = @srcdir@ + +include ../../macros.make +# M4FLAGS = -s -B7168 +# CC = cc -fullwarn -woff 1209,1506 + + +INCLUDES = -I$(srcdir)/../../src/lib -I$(srcdir) + +ld_math = $(MATHLIB) + +SRCS = nc_test.c \ + error.c \ + test_get.c \ + test_put.c \ + test_read.c \ + test_write.c \ + util.c + +OBJS = $(SRCS:.c=.o) + +lib_netcdf = ../../src/lib/libpnetcdf.a +ld_netcdf = -L../../src/lib -lpnetcdf + +time_log = times + +GARBAGE = nc_test test.nc scratch.nc lint.out $(time_log) + +PACKING_LIST = $(SRCS) \ + test_get.m4 \ + test_put.m4 \ + error.h \ + tests.h \ + depend \ + Makefile + +all: nc_test + +test: nc_test test.nc + ./nc_test + @echo '*** Success ***' + +readonly: nc_test test.nc + ./nc_test -r + +test.nc: nc_test + ./nc_test -c + +install: + +uninstall: + + +nc_test: $(OBJS) $(lib_netcdf) + $(LINK.c) $(OBJS) $(ld_netcdf) $(ld_math) $(LIBS) + +test_get.c: test_get.m4 + +test_put.c: test_put.m4 + +nctime: nctime.o $(lib_netcdf) + $(LINK.c) nctime.o $(ld_netcdf) $(ld_math) $(LIBS) + +time: nctime + time ./nctime 24 13 19 17 > $(time_log) + awk -f timesum.awk < $(time_log) + +saber_src: + #load -C $(CPPFLAGS) $(SRCS) $(ld_netcdf) $(ld_math) $(LIBS) + +# This simple testing target ensures that the test files are present +testing: test.nc nc_test + rm -f scratch.nc + ./nc_test && ./nc_test -c -2 && ./nc_test + +include $(srcdir)/../../rules.make +include $(srcdir)/depend Index: /tags/v1-0-3/test/nc_test/test_put.m4 =================================================================== --- /tags/v1-0-3/test/nc_test/test_put.m4 (revision 560) +++ /tags/v1-0-3/test/nc_test/test_put.m4 (revision 560) @@ -0,0 +1,1152 @@ +dnl This is m4 source. +dnl Process using m4 to produce 'C' language file. +dnl +dnl If you see this line, you can ignore the next one. +/* Do not edit this file. It is produced from the corresponding .m4 source */ +dnl +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +undefine(`index')dnl +dnl dnl dnl +dnl +dnl Macros +dnl +dnl dnl dnl +dnl +dnl Upcase(str) +dnl +define(`Upcase',dnl +`dnl +translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl +dnl dnl dnl +dnl +dnl NCT_ITYPE(type) +dnl +define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl +dnl + +#include "tests.h" + +dnl HASH(TYPE) +dnl +define(`HASH',dnl +`dnl +/* + * ensure hash value within range for internal TYPE + */ +static +double +hash_$1( + const ncmpi_type type, + const int rank, + const MPI_Offset *index, + const nct_itype itype) +{ + const double min = $1_min; + const double max = $1_max; + + return MAX(min, MIN(max, hash4( type, rank, index, itype))); +} +')dnl + +HASH(text) +HASH(uchar) +HASH(schar) +HASH(short) +HASH(int) +HASH(long) +HASH(float) +HASH(double) + + +dnl CHECK_VARS(TYPE) +dnl +define(`CHECK_VARS',dnl +`dnl +/* + * check all vars in file which are (text/numeric) compatible with TYPE + */ +static +void +check_vars_$1(const char *filename) +{ + int ncid; /* netCDF id */ + MPI_Offset index[MAX_RANK]; + int err; /* status */ + int d; + int i; + size_t j; + $1 value; + ncmpi_type datatype; + int ndims; + int dimids[MAX_RANK]; + double expect; + char name[NC_MAX_NAME]; + MPI_Offset length; + int canConvert; /* Both text or both numeric */ + int nok = 0; /* count of valid comparisons */ + + err = ncmpi_open(comm, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + if (canConvert) { + err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL); + IF (err) + error("ncmpi_inq_var: %s", ncmpi_strerror(err)); + IF (strcmp(name, var_name[i]) != 0) + error("Unexpected var_name"); + IF (datatype != var_type[i]) + error("Unexpected type"); + IF (ndims != var_rank[i]) + error("Unexpected rank"); + for (j = 0; j < ndims; j++) { + err = ncmpi_inq_dim(ncid, dimids[j], 0, &length); + IF (err) + error("ncmpi_inq_dim: %s", ncmpi_strerror(err)); + IF (length != var_shape[i][j]) + error("Unexpected shape"); + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 2"); + expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1)); + ncmpi_begin_indep_data(ncid); + err = ncmpi_get_var1_$1(ncid, i, index, &value); + if (inRange3(expect,datatype,NCT_ITYPE($1))) { + if (expect >= $1_min && expect <= $1_max) { + IF (err) { + error("ncmpi_get_var1_$1: %s", ncmpi_strerror(err)); + } else { + IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) { + error("Var value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("index:"); + for (d = 0; d < var_rank[i]; d++) + error(" %d", index[d]); + error(", expect: %g, ", expect); + error("got: %g", (double) value); + } + } else { + ++nok; + } + } + } + } + ncmpi_end_indep_data(ncid); + } + } + } + err = ncmpi_close (ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +CHECK_VARS(text) +CHECK_VARS(uchar) +CHECK_VARS(schar) +CHECK_VARS(short) +CHECK_VARS(int) +CHECK_VARS(long) +CHECK_VARS(float) +CHECK_VARS(double) + + +dnl CHECK_ATTS(TYPE) numeric only +dnl +define(`CHECK_ATTS',dnl +`dnl +/* + * check all attributes in file which are (text/numeric) compatible with TYPE + * ignore any attributes containing values outside range of TYPE + */ +static +void +check_atts_$1(int ncid) +{ + int err; /* status */ + int i; + int j; + MPI_Offset k; + $1 value[MAX_NELS]; + ncmpi_type datatype; + double expect[MAX_NELS]; + MPI_Offset length; + size_t nInExtRange; /* number values within external range */ + size_t nInIntRange; /* number values within internal range */ + int canConvert; /* Both text or both numeric */ + int nok = 0; /* count of valid comparisons */ + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + if (canConvert) { + err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length); + IF (err) + error("ncmpi_inq_att: %s", ncmpi_strerror(err)); + IF (datatype != ATT_TYPE(i,j)) + error("ncmpi_inq_att: unexpected type"); + IF (length != ATT_LEN(i,j)) + error("ncmpi_inq_att: unexpected length"); + assert(length <= MAX_NELS); + nInIntRange = nInExtRange = 0; + for (k = 0; k < length; k++) { + expect[k] = hash4( datatype, -1, &k, NCT_ITYPE($1)); + if (inRange3(expect[k], datatype, NCT_ITYPE($1))) { + ++nInExtRange; + if (expect[k] >= $1_min && expect[k] <= $1_max) + ++nInIntRange; + } + } + err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value); + if (nInExtRange == length && nInIntRange == length) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (k = 0; k < length; k++) { + if (inRange3(expect[k],datatype,NCT_ITYPE($1)) + && expect[k] >= $1_min && expect[k] <= $1_max) { + IF (!equal(value[k],expect[k],datatype,NCT_ITYPE($1))) { + error("att. value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("att_name: %s, ", ATT_NAME(i,j)); + error("element number: %d ", k); + error("expect: %g, ", expect[k]); + error("got: %g", (double) value[k]); + } + } else { + nok++; + } + } + } + } + } + } + + print_nok(nok); +} +')dnl + +CHECK_ATTS(text) +CHECK_ATTS(uchar) +CHECK_ATTS(schar) +CHECK_ATTS(short) +CHECK_ATTS(int) +CHECK_ATTS(long) +CHECK_ATTS(float) +CHECK_ATTS(double) + + +dnl TEST_NC_PUT_VAR1(TYPE) +dnl +define(`TEST_NC_PUT_VAR1',dnl +`dnl +void +test_ncmpi_put_var1_$1(void) +{ + int ncid; + int i; + int j; + int err; + MPI_Offset index[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + $1 value = 5; /* any value would do - only for error cases */ + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + ncmpi_begin_indep_data(ncid); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + for (j = 0; j < var_rank[i]; j++) + index[j] = 0; + err = ncmpi_put_var1_$1(BAD_ID, i, index, &value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_var1_$1(ncid, BAD_VARID, index, &value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + index[j] = var_shape[i][j]; + err = ncmpi_put_var1_$1(ncid, i, index, &value); + IF (canConvert && err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + index[j] = 0; + } + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 1"); + value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1)); + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_var1_$1(ncid, i, NULL, &value); + else + err = ncmpi_put_var1_$1(ncid, i, index, &value); + if (canConvert) { + if (inRange3(value, var_type[i],NCT_ITYPE($1))) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) { + error("Range error: status = %d", err); + error("\n\t\tfor type %s value %.17e %ld", + s_ncmpi_type(var_type[i]), + (double)value, (long)value); + } + } + } else { + IF (err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + ncmpi_end_indep_data(ncid); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + check_vars_$1(scratch); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_VAR1(text) +TEST_NC_PUT_VAR1(uchar) +TEST_NC_PUT_VAR1(schar) +TEST_NC_PUT_VAR1(short) +TEST_NC_PUT_VAR1(int) +TEST_NC_PUT_VAR1(long) +TEST_NC_PUT_VAR1(float) +TEST_NC_PUT_VAR1(double) + + +dnl TEST_NC_PUT_VAR(TYPE) +dnl +define(`TEST_NC_PUT_VAR',dnl +`dnl +void +test_ncmpi_put_var_$1(void) +{ + int ncid; + int varid; + int i; + int j; + int err; + int nels; + MPI_Offset index[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + $1 value[MAX_NELS]; + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + ncmpi_begin_indep_data(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + err = ncmpi_put_var_$1(BAD_ID, i, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_var_$1(ncid, BAD_VARID, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + nels *= var_shape[i][j]; + } + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 1"); + value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + } + err = ncmpi_put_var_$1(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM) + error("range error: status = %d", err); + } + } else { /* should flag wrong type even if nothing to write */ + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + ncmpi_end_indep_data(ncid); + + /* Preceeding has written nothing for record variables, now try */ + /* again with more than 0 records */ + + /* Write record number NRECS to force writing of preceding records */ + /* Assumes variable cr is char vector with UNLIMITED dimension */ + err = ncmpi_inq_varid(ncid, "cr", &varid); + IF (err) + error("ncmpi_inq_varid: %s", ncmpi_strerror(err)); + index[0] = NRECS-1; + ncmpi_begin_indep_data(ncid); + err = ncmpi_put_var1_text(ncid, varid, index, "x"); + IF (err) + error("ncmpi_put_var1_text: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + if (var_dimid[i][0] == RECDIM) { /* only test record variables here */ + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + err = ncmpi_put_var_$1(BAD_ID, i, value); + + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + nels *= var_shape[i][j]; + } + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 1"); + value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + } + err = ncmpi_put_var_$1(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("range error: status = %d", err); + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + ncmpi_end_indep_data(ncid); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + check_vars_$1(scratch); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_VAR(text) +TEST_NC_PUT_VAR(uchar) +TEST_NC_PUT_VAR(schar) +TEST_NC_PUT_VAR(short) +TEST_NC_PUT_VAR(int) +TEST_NC_PUT_VAR(long) +TEST_NC_PUT_VAR(float) +TEST_NC_PUT_VAR(double) + + +dnl TEST_NC_PUT_VARA(TYPE) +dnl +define(`TEST_NC_PUT_VARA',dnl +`dnl +void +test_ncmpi_put_vara_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int err; + int nslabs; + int nels; + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + $1 value[MAX_NELS]; + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + value[0] = 0; + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EINVALCOORDS) + error("bad start: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + } + } + /* Check correct error returned even when nothing to put */ + for (j = 0; j < var_rank[i]; j++) { + edge[j] = 0; + } + err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + edge[j] = 1; /* added by Jianwei, fix NC_EINVALCOORDS bug */ + err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EINVALCOORDS) + error("bad start: status = %d", err); + start[j] = 0; + edge[j] = 0; /* added by Jianwei, restore the original value */ + } + } + err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value); + if (canConvert) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ECHAR) + error("wrong type: status = %d", err); + } + for (j = 0; j < var_rank[i]; j++) { + edge[j] = 1; + } + + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], edge, index); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + } + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_vara_$1_all(ncid, i, NULL, NULL, value); + else + err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value); + if (canConvert) { + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("range error: status = %d", err); + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + check_vars_$1(scratch); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_VARA(text) +TEST_NC_PUT_VARA(uchar) +TEST_NC_PUT_VARA(schar) +TEST_NC_PUT_VARA(short) +TEST_NC_PUT_VARA(int) +TEST_NC_PUT_VARA(long) +TEST_NC_PUT_VARA(float) +TEST_NC_PUT_VARA(double) + + +dnl TEST_NC_PUT_VARS(TYPE) +dnl +define(`TEST_NC_PUT_VARS',dnl +`dnl +void +test_ncmpi_put_vars_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int nels; + int nslabs; + int nstarts; /* number of different starts */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + $1 value[MAX_NELS]; + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + err = ncmpi_put_vars_$1_all(BAD_ID, i, start, edge, stride, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value); + if(!canConvert) { + IF(err != NC_ECHAR) + error("conversion: status = %d", err); + } else { + IF(err != NC_EINVALCOORDS) + error("bad start: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } +*/ + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + value[j] = hash_$1(var_type[i], var_rank[i], index2, + NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + } + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_vars_$1_all(ncid, i, NULL, NULL, stride, value); + else + err = ncmpi_put_vars_$1_all(ncid, i, index, count, stride, value); + if (canConvert) { + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("range error: status = %d", err); + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + check_vars_$1(scratch); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_VARS(text) +TEST_NC_PUT_VARS(uchar) +TEST_NC_PUT_VARS(schar) +TEST_NC_PUT_VARS(short) +TEST_NC_PUT_VARS(int) +TEST_NC_PUT_VARS(long) +TEST_NC_PUT_VARS(float) +TEST_NC_PUT_VARS(double) + + +dnl TEST_NC_PUT_VARM(TYPE) +dnl +define(`TEST_NC_PUT_VARM',dnl +`dnl +void +test_ncmpi_put_varm_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int nels; + int nslabs; + int nstarts; /* number of different starts */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + MPI_Offset imap[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + int allInExtRange; /* all values within external range? */ + $1 value[MAX_NELS]; + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + imap[j] = 1; + } + err = ncmpi_put_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value); + if (!canConvert) { + IF(err != NC_ECHAR) + error("conversion: status = %d", err); + } else { + IF (err != NC_EINVALCOORDS) + error("bad start: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } +*/ + if (var_rank[i] > 0) { + j = var_rank[i] - 1; + imap[j] = 1; + for (; j > 0; j--) + imap[j-1] = imap[j] * count[j]; + } + for (allInExtRange = 1, j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + value[j] = hash_$1(var_type[i], var_rank[i], index2, + NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[j], var_type[i], NCT_ITYPE($1)); + } + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value); + else + err = ncmpi_put_varm_$1_all(ncid,i,index,count,stride,imap,value); + if (canConvert) { + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("range error: status = %d", err); + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + check_vars_$1(scratch); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_VARM(text) +TEST_NC_PUT_VARM(uchar) +TEST_NC_PUT_VARM(schar) +TEST_NC_PUT_VARM(short) +TEST_NC_PUT_VARM(int) +TEST_NC_PUT_VARM(long) +TEST_NC_PUT_VARM(float) +TEST_NC_PUT_VARM(double) + + +void +test_ncmpi_put_att_text(void) +{ + int ncid; + int i; + int j; + MPI_Offset k; + int err; + text value[MAX_NELS]; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + + { + const char *const tval = "value for bad name"; + const size_t tval_len = strlen(tval); + + err = ncmpi_put_att_text(ncid, 0, "", tval_len, tval); + IF (err != NC_EBADNAME) + error("should be NC_EBADNAME: status = %d", err); + } + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + if (ATT_TYPE(i,j) == NC_CHAR) { + assert(ATT_LEN(i,j) <= MAX_NELS); + err = ncmpi_put_att_text(BAD_ID, i, ATT_NAME(i,j), ATT_LEN(i,j), + value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_att_text(ncid, BAD_VARID, ATT_NAME(i,j), + ATT_LEN(i,j), value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (k = 0; k < ATT_LEN(i,j); k++) { + value[k] = hash(ATT_TYPE(i,j), -1, &k); + } + err = ncmpi_put_att_text(ncid, i, ATT_NAME(i,j), + ATT_LEN(i,j), value); + IF (err) { + error("%s", ncmpi_strerror(err)); + } + } + } + } + + check_atts_text(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +dnl TEST_NC_PUT_ATT(TYPE) numeric only +dnl +define(`TEST_NC_PUT_ATT',dnl +`dnl +void +test_ncmpi_put_att_$1(void) +{ + int ncid; + int i; + int j; + MPI_Offset k; + int err; + $1 value[MAX_NELS]; + int allInExtRange; /* all values within external range? */ + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + if (!(ATT_TYPE(i,j) == NC_CHAR)) { + assert(ATT_LEN(i,j) <= MAX_NELS); + err = ncmpi_put_att_$1(BAD_ID, i, ATT_NAME(i,j), ATT_TYPE(i,j), + ATT_LEN(i,j), value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), + ATT_TYPE(i,j), ATT_LEN(i,j), value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), BAD_TYPE, + ATT_LEN(i,j), value); + IF (err != NC_EBADTYPE) + error("bad type: status = %d", err); + for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) { + value[k] = hash_$1(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); + allInExtRange = allInExtRange + && inRange3(value[k], ATT_TYPE(i,j), NCT_ITYPE($1)); + } + err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), + ATT_LEN(i,j), value); + if (allInExtRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("range error: status = %d", err); + } + } + } + } + + check_atts_$1(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +')dnl + +TEST_NC_PUT_ATT(uchar) +TEST_NC_PUT_ATT(schar) +TEST_NC_PUT_ATT(short) +TEST_NC_PUT_ATT(int) +TEST_NC_PUT_ATT(long) +TEST_NC_PUT_ATT(float) +TEST_NC_PUT_ATT(double) + Index: /tags/v1-0-3/test/nc_test/tests.h =================================================================== --- /tags/v1-0-3/test/nc_test/tests.h (revision 433) +++ /tags/v1-0-3/test/nc_test/tests.h (revision 433) @@ -0,0 +1,437 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#define NO_NETCDF_2 1 +#include "pnetcdf.h" +#include +#include "error.h" + +#if defined(_CRAY) && !defined(_CRAYIEEE) +#define CRAYFLOAT 1 /* CRAY Floating point */ +#elif defined(_SX) && defined(_FLOAT2) /* NEC SUPER-UX in CRAY mode */ +#define CRAYFLOAT 1 /* CRAY Floating point */ +#endif + + /* Limits of external types (based on those in ncx.h) */ + +#define X_CHAR_MIN CHAR_MIN +#define X_CHAR_MAX CHAR_MAX +#define X_BYTE_MIN (-128) +#define X_BYTE_MAX 127 +#define X_SHORT_MIN SHRT_MIN +#define X_SHORT_MAX SHRT_MAX +#define X_INT_MIN INT_MIN +#define X_INT_MAX INT_MAX +#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 +/* FLT_MAX < X_FLOAT_MAX */ +#define X_FLOAT_MAX FLT_MAX +#else +#define X_FLOAT_MAX 3.40282347e+38f +#endif +#define X_FLOAT_MIN (-X_FLOAT_MAX) +#if defined(CRAYFLOAT) && CRAYFLOAT != 0 +/* ldexp(1. - ldexp(.5 , -46), 1024) */ +#define X_DOUBLE_MAX 1.79769313486230e+308 +#else +/* scalb(1. - scalb(.5 , -52), 1024) */ +#define X_DOUBLE_MAX DBL_MAX +#endif +#define X_DOUBLE_MIN -(DBL_MAX) + + +#if defined(_SX) && _SX != 0 /* NEC SUPER UX */ +#if _INT64 +#undef INT_MAX /* workaround cpp bug */ +#define INT_MAX X_INT_MAX +#undef INT_MIN /* workaround cpp bug */ +#define INT_MIN X_INT_MIN +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX X_INT_MAX +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN X_INT_MIN +#elif _LONG64 +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX 4294967295L +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN -4294967295L +#endif +#endif /* _SX */ + + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif /* MAX */ + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +#ifndef ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#endif /* ABS */ + + + /* Parameters of test data */ + +#define NTYPES 6 +#define NDIMS 5 +#define NVARS 136 +#define NRECS 2 +#define NGATTS NTYPES +#define RECDIM 0 +#define MAX_RANK 3 +#define MAX_NELS 64 +#define MAX_DIM_LEN 4 +#define MAX_NATTS 3 + + + /* Limits of internal types */ + +#define text_min CHAR_MIN +#define uchar_min 0 +#define schar_min SCHAR_MIN +#define short_min SHRT_MIN +#define int_min INT_MIN +#define long_min LONG_MIN +#define float_min (-FLT_MAX) +#define double_min (-DBL_MAX) + +#define text_max CHAR_MAX +#define uchar_max UCHAR_MAX +#define schar_max SCHAR_MAX +#define short_max SHRT_MAX +#define int_max INT_MAX +#define long_max LONG_MAX +#define float_max FLT_MAX +#define double_max DBL_MAX + + + + /* Examples of invalid argument values */ + +#define BAD_ID -1 /* invalid netCDF ID */ +#define BAD_DIMID -1 /* invalid dim ID */ +#define BAD_VARID -2 /* invalid var ID */ +#define BAD_ATTNUM -1 /* invalid att number */ +#define BAD_TYPE (ncmpi_type) 0 /* invalid data type */ +#define BAD_FILLMODE -1 /* invalid fill mode */ +#define BAD_NAME "a/b" /* invalid name */ +#define BAD_DEFAULT_FORMAT 12 /* invalid default format */ + +#define LEN_OF(array) ((sizeof array) / (sizeof array[0])) + +#ifdef __cplusplus +extern "C" { +#endif + + + /* Non-standard internal types */ + +typedef char text; +typedef signed char schar; +#if !defined(uchar) && !defined(__osf__) && !defined(_AIX) +typedef unsigned char uchar; +#endif + + + + /* Global variables - filenames */ + +extern char testfile[]; /* netCDF read-only test data */ +extern char scratch[]; /* netCDF test file for writing */ + + /* Global variables - command-line arguments */ + +extern int read_only; /* if 1, don't try to change files */ +extern int verbose; /* if 1, print details of tests */ +extern int nfails; /* number of failures in specific test */ +extern int use_cdf2; /* if 1, use CDF-2 format (offset >2GB ) */ +extern int extra_flags; /* if using CDF-2, need extra flags for create*/ +extern int max_nmpt; /* max number of messages per test */ + + + /* Global variables - test data */ + +extern char dim_name[NDIMS][3]; +extern MPI_Offset dim_len[NDIMS]; +extern char var_name[NVARS][2+MAX_RANK]; +extern ncmpi_type var_type[NVARS]; +extern size_t var_rank[NVARS]; +extern int var_dimid[NVARS][MAX_RANK]; +extern MPI_Offset var_shape[NVARS][MAX_RANK]; +extern size_t var_nels[NVARS]; +extern size_t var_natts[NVARS]; +extern char att_name[NVARS][MAX_NATTS][2]; +extern char gatt_name[NGATTS][3]; +extern ncmpi_type att_type[NVARS][NGATTS]; +extern ncmpi_type gatt_type[NGATTS]; +extern size_t att_len[NVARS][MAX_NATTS]; +extern size_t gatt_len[NGATTS]; + +/* Global variables: MPI data */ +extern MPI_Comm comm; + + /* Macros for accessing attribute test data */ + /* varid is -1 for NC_GLOBAL so can do global atts in same loop */ + +#define VARID(varid) (varid < 0 ? NC_GLOBAL : varid) +#define NATTS(varid) (varid < 0 ? NGATTS : var_natts[varid]) +#define ATT_NAME(varid,j) (varid < 0 ? gatt_name[j] : att_name[varid][j]) +#define ATT_TYPE(varid,j) (varid < 0 ? gatt_type[j] : att_type[varid][j]) +#define ATT_LEN(varid,j) (varid < 0 ? gatt_len[j] : att_len[varid][j]) + +extern const char *s_ncmpi_type(ncmpi_type); + +extern void test_ncmpi_strerror(void); +extern void test_ncmpi_open(void); +extern void test_ncmpi_close(void); +extern void test_ncmpi_delete(void); + +extern void test_ncmpi_inq(void); +extern void test_ncmpi_inq_natts(void); +extern void test_ncmpi_inq_ndims(void); +extern void test_ncmpi_inq_nvars(void); +extern void test_ncmpi_inq_unlimdim(void); + +extern void test_ncmpi_inq_dimid(void); +extern void test_ncmpi_inq_dim(void); +extern void test_ncmpi_inq_dimlen(void); +extern void test_ncmpi_inq_dimname(void); + +extern void test_ncmpi_inq_varid(void); +extern void test_ncmpi_inq_vardimid(void); +extern void test_ncmpi_inq_varname(void); +extern void test_ncmpi_inq_varnatts(void); +extern void test_ncmpi_inq_varndims(void); +extern void test_ncmpi_inq_vartype(void); +extern void test_ncmpi_inq_var(void); + +extern void test_ncmpi_get_var_double(void); +extern void test_ncmpi_get_var_float(void); +extern void test_ncmpi_get_var_int(void); +extern void test_ncmpi_get_var_long(void); +extern void test_ncmpi_get_var_schar(void); +extern void test_ncmpi_get_var_short(void); +extern void test_ncmpi_get_var_text(void); +extern void test_ncmpi_get_var_uchar(void); +extern void test_ncmpi_get_var(void); + +extern void test_ncmpi_get_var1_double(void); +extern void test_ncmpi_get_var1_float(void); +extern void test_ncmpi_get_var1_int(void); +extern void test_ncmpi_get_var1_long(void); +extern void test_ncmpi_get_var1_schar(void); +extern void test_ncmpi_get_var1_short(void); +extern void test_ncmpi_get_var1_text(void); +extern void test_ncmpi_get_var1_uchar(void); +extern void test_ncmpi_get_var1(void); + +extern void test_ncmpi_get_vara_double(void); +extern void test_ncmpi_get_vara_float(void); +extern void test_ncmpi_get_vara_int(void); +extern void test_ncmpi_get_vara_long(void); +extern void test_ncmpi_get_vara_schar(void); +extern void test_ncmpi_get_vara_short(void); +extern void test_ncmpi_get_vara_text(void); +extern void test_ncmpi_get_vara_uchar(void); +extern void test_ncmpi_get_vara(void); + +extern void test_ncmpi_get_vars(void); +extern void test_ncmpi_get_vars_double(void); +extern void test_ncmpi_get_vars_float(void); +extern void test_ncmpi_get_vars_int(void); +extern void test_ncmpi_get_vars_long(void); +extern void test_ncmpi_get_vars_schar(void); +extern void test_ncmpi_get_vars_short(void); +extern void test_ncmpi_get_vars_text(void); +extern void test_ncmpi_get_vars_uchar(void); +extern void test_ncmpi_get_vars(void); + +extern void test_ncmpi_get_varm(void); +extern void test_ncmpi_get_varm_double(void); +extern void test_ncmpi_get_varm_float(void); +extern void test_ncmpi_get_varm_int(void); +extern void test_ncmpi_get_varm_long(void); +extern void test_ncmpi_get_varm_schar(void); +extern void test_ncmpi_get_varm_short(void); +extern void test_ncmpi_get_varm_text(void); +extern void test_ncmpi_get_varm_uchar(void); +extern void test_ncmpi_get_varm(void); + +extern void test_ncmpi_get_att(void); +extern void test_ncmpi_get_att_double(void); +extern void test_ncmpi_get_att_float(void); +extern void test_ncmpi_get_att_int(void); +extern void test_ncmpi_get_att_long(void); +extern void test_ncmpi_get_att_schar(void); +extern void test_ncmpi_get_att_short(void); +extern void test_ncmpi_get_att_text(void); +extern void test_ncmpi_get_att_uchar(void); + +extern void test_ncmpi_put_var_double(void); +extern void test_ncmpi_put_var_float(void); +extern void test_ncmpi_put_var_int(void); +extern void test_ncmpi_put_var_long(void); +extern void test_ncmpi_put_var_schar(void); +extern void test_ncmpi_put_var_short(void); +extern void test_ncmpi_put_var_text(void); +extern void test_ncmpi_put_var_uchar(void); +extern void test_ncmpi_put_var(void); + +extern void test_ncmpi_put_var1_double(void); +extern void test_ncmpi_put_var1_float(void); +extern void test_ncmpi_put_var1_int(void); +extern void test_ncmpi_put_var1_long(void); +extern void test_ncmpi_put_var1_schar(void); +extern void test_ncmpi_put_var1_short(void); +extern void test_ncmpi_put_var1_text(void); +extern void test_ncmpi_put_var1_uchar(void); +extern void test_ncmpi_put_var1(void); + +extern void test_ncmpi_put_vara_double(void); +extern void test_ncmpi_put_vara_float(void); +extern void test_ncmpi_put_vara_int(void); +extern void test_ncmpi_put_vara_long(void); +extern void test_ncmpi_put_vara_schar(void); +extern void test_ncmpi_put_vara_short(void); +extern void test_ncmpi_put_vara_text(void); +extern void test_ncmpi_put_vara_uchar(void); +extern void test_ncmpi_put_vara(void); + +extern void test_ncmpi_put_vars_double(void); +extern void test_ncmpi_put_vars_float(void); +extern void test_ncmpi_put_vars_int(void); +extern void test_ncmpi_put_vars_long(void); +extern void test_ncmpi_put_vars_schar(void); +extern void test_ncmpi_put_vars_short(void); +extern void test_ncmpi_put_vars_text(void); +extern void test_ncmpi_put_vars_uchar(void); +extern void test_ncmpi_put_vars(void); + +extern void test_ncmpi_put_varm_double(void); +extern void test_ncmpi_put_varm_float(void); +extern void test_ncmpi_put_varm_int(void); +extern void test_ncmpi_put_varm_long(void); +extern void test_ncmpi_put_varm_schar(void); +extern void test_ncmpi_put_varm_short(void); +extern void test_ncmpi_put_varm_text(void); +extern void test_ncmpi_put_varm_uchar(void); +extern void test_ncmpi_put_varm(void); + +extern void test_ncmpi_put_att(void); +extern void test_ncmpi_put_att_double(void); +extern void test_ncmpi_put_att_float(void); +extern void test_ncmpi_put_att_int(void); +extern void test_ncmpi_put_att_long(void); +extern void test_ncmpi_put_att_schar(void); +extern void test_ncmpi_put_att_short(void); +extern void test_ncmpi_put_att_text(void); +extern void test_ncmpi_put_att_uchar(void); + +extern void test_ncmpi_create(void); +extern void test_ncmpi_redef(void); +extern void test_ncmpi_enddef(void); +extern void test_ncmpi_sync(void); +extern void test_ncmpi_abort(void); +extern void test_ncmpi_def_dim(void); +extern void test_ncmpi_rename_dim(void); +extern void test_ncmpi_def_var(void); +extern void test_ncmpi_rename_var(void); +extern void test_ncmpi_copy_att(void); + +extern void test_ncmpi_inq_att(void); +extern void test_ncmpi_inq_attname(void); +extern void test_ncmpi_inq_attid(void); +extern void test_ncmpi_inq_attlen(void); +extern void test_ncmpi_inq_atttype(void); + +extern void test_ncmpi_rename_att(void); +extern void test_ncmpi_del_att(void); +extern void test_ncmpi_set_fill(void); +extern void test_ncmpi_set_default_format(void); + +void print_nok(int nok); + +int inRange(const double value, const ncmpi_type datatype); + +/* + * internal types + */ +typedef enum { + NCT_UNSPECIFIED = 0, + NCT_UCHAR = 1, /* unsigned char */ + NCT_TEXT = 16, /* char */ +#define NCT_CHAR NCT_TEXT + NCT_SCHAR = 17, /* signed char */ + NCT_SHORT = 18, /* short */ + NCT_INT = 20, /* int */ + NCT_LONG = 22, /* long */ + NCT_FLOAT = 36, /* float */ + NCT_DOUBLE = 40 /* double */ +} nct_itype; + +int inRange3(const double value, const ncmpi_type datatype, const nct_itype itype); + +int equal(const double x, const double y, ncmpi_type extType, nct_itype itype); + +int int_vec_eq(const int *v1, const int *v2, const int n); + +int roll( int n ); + +int +toMixedBase( + size_t number, /* number to be converted to mixed base */ + size_t length, + const MPI_Offset base[], /* dimensioned [length], base[0] ignored */ + MPI_Offset result[]); /* dimensioned [length] */ + +size_t +fromMixedBase( + size_t length, + MPI_Offset number[], /* dimensioned [length] */ + MPI_Offset base[]); /* dimensioned [length], base[0] ignored */ + +int nc2dbl ( const ncmpi_type datatype, const void *p, double *result); + +int dbl2nc ( const double d, const ncmpi_type datatype, void *p); + +double hash( const ncmpi_type type, const int rank, const MPI_Offset *index ); + +double hash4( + const ncmpi_type type, + const int rank, + const MPI_Offset *index, + const nct_itype itype); + +void init_gvars(void); + +void def_dims(int ncid); + +void def_vars(int ncid); + +void put_atts(int ncid); + +void put_vars(int ncid); + +void write_file(char *filename); + +void check_dims(int ncid); + +void check_vars(int ncid); + +void check_atts(int ncid); + +void check_file(char *filename); + +#ifdef __cplusplus +} +#endif Index: /tags/v1-0-3/test/nc_test/error.c =================================================================== --- /tags/v1-0-3/test/nc_test/error.c (revision 366) +++ /tags/v1-0-3/test/nc_test/error.c (revision 366) @@ -0,0 +1,79 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include /* because gcc 2.7.2.2 doesn't define size_t */ + /* in and it cannot hurt */ +#include +#include + +#include + +extern int nfails; /* number of failures in specific test */ +extern int max_nmpt; /* max. number of messages per test */ + +/* Prototypes */ +void error(const char *fmt, ...); +void print(const char *fmt, ...); +int ifFail(const int expr, const int line, const char *file); +void print_n_size_t(size_t nelems, const MPI_Offset *array); + +/* + * Use for logging error conditions + */ +void +error(const char *fmt, ...) +{ + va_list args ; + + va_start(args, fmt) ; + if (nfails <= max_nmpt) + (void) vfprintf(stderr,fmt,args) ; + va_end(args) ; +} + +/* + * Use for general printing (other than error conditions) + * This also currently goes to stderr, but this could change + */ +void +print(const char *fmt, ...) +{ + va_list args ; + + va_start(args, fmt) ; + (void) vfprintf(stderr,fmt,args) ; + va_end(args) ; +} + +/* + * Called by macro IF + */ +int +ifFail(const int expr, const int line, const char *file) +{ + if (expr) { + ++nfails; + error("\n\tFAILURE at line %d of %s: ", line, file); + } + return expr; +} + +/* TODO: + * This diagnostic doesn't fit very well with the diagnostic message + * "architecture" of this program. + */ +void +print_n_size_t(size_t nelems, const MPI_Offset *array) +{ + fprintf(stderr, "["); + while(nelems-- > 0) + { + fprintf(stderr, "%ld", (long)*array++); + if(nelems > 0) + fprintf(stderr, " "); + } + fprintf(stderr, "]"); +} Index: /tags/v1-0-3/test/nc_test/test_write.c =================================================================== --- /tags/v1-0-3/test/nc_test/test_write.c (revision 560) +++ /tags/v1-0-3/test/nc_test/test_write.c (revision 560) @@ -0,0 +1,2043 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include "tests.h" +#include "math.h" + + +/* + * Test ncmpi_create + * For mode in NC_NOCLOBBER|extra_flags, NC_CLOBBER, MPI_INFO_NULL do: + * create netcdf file 'scratch.nc' with no data, close it + * test that it can be opened, do ncmpi_inq to check nvars = 0, etc. + * Try again in NC_NOCLOBBER|extra_flags mode, check error return + * On exit, delete this file + */ +void +test_ncmpi_create(void) +{ + int clobber; /* 0 for NC_NOCLOBBER|extra_flags, 1 for NC_CLOBBER, MPI_INFO_NULL */ + int err; + int ncid; + int ndims; /* number of dimensions */ + int nvars; /* number of variables */ + int ngatts; /* number of global attributes */ + int recdim; /* id of unlimited dimension */ + + for (clobber = 0; clobber < 2; clobber++) { + err = ncmpi_create(comm, scratch, clobber ? NC_CLOBBER|extra_flags : NC_NOCLOBBER, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_create: %s", ncmpi_strerror(err)); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_open(comm, scratch, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &recdim); + IF (err) + error("ncmpi_inq: %s", ncmpi_strerror(err)); + else IF (ndims != 0) + error("ncmpi_inq: wrong number of dimensions returned, %d", ndims); + else IF (nvars != 0) + error("ncmpi_inq: wrong number of variables returned, %d", nvars); + else IF (ngatts != 0) + error("ncmpi_inq: wrong number of global atts returned, %d", ngatts); + else IF (recdim != -1) + error("ncmpi_inq: wrong record dimension ID returned, %d", recdim); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + } + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err != NC_EEXIST) + error("attempt to overwrite file: status = %d", err); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_redef + * (In fact also tests ncmpi_enddef - called from test_ncmpi_enddef) + * BAD_ID + * attempt redef (error) & enddef on read-only file + * create file, define dims & vars. + * attempt put var (error) + * attempt redef (error) & enddef. + * put vars + * attempt def new dims (error) + * redef + * def new dims, vars. + * put atts + * enddef + * put vars + * close + * check file: vars & atts + */ +void +test_ncmpi_redef(void) +{ + int ncid; /* netcdf id */ + /* used to force effective test of ncio->move() in redef */ + size_t sizehint = 8192; + int dimid; /* dimension id */ + int varid; /* variable id */ + int varid1; /* variable id */ + int err; + const char * title = "Not funny"; + double var; + char name[NC_MAX_NAME]; + MPI_Offset length; + + /* BAD_ID tests */ + err = ncmpi_redef(BAD_ID); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_enddef(BAD_ID); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* read-only tests */ + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_redef(ncid); + IF (err != NC_EPERM) + error("ncmpi_redef in NC_NOWRITE, MPI_INFO_NULL mode: status = %d", err); + err = ncmpi_enddef(ncid); + IF (err != NC_ENOTINDEFINE) + error("ncmpi_redef in NC_NOWRITE, MPI_INFO_NULL mode: status = %d", err); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* tests using scratch file */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + /* err = ncmpi__create(scratch, NC_NOCLOBBER|extra_flags, 0, &sizehint, &ncid); */ + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + /* limit for ncio implementations which which have infinite chunksize */ + if(sizehint > 32768) + sizehint = 16384; + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = ncmpi_inq_varid(ncid, "d", &varid); + IF (err) + error("ncmpi_inq_varid: %s", ncmpi_strerror(err)); + var = 1.0; + ncmpi_begin_indep_data(ncid); + err = ncmpi_put_var1_double(ncid, varid, NULL, &var); + IF (err != NC_EINDEFINE) + error("ncmpi_put_var... in define mode: status = %d", err); + ncmpi_end_indep_data(ncid); + err = ncmpi_redef(ncid); + IF (err != NC_EINDEFINE) + error("ncmpi_redef in define mode: status = %d", err); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + put_vars(ncid); + err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid); + IF (err != NC_ENOTINDEFINE) + error("ncmpi_def_dim in define mode: status = %d", err); + err = ncmpi_redef(ncid); + IF (err) + error("ncmpi_redef: %s", ncmpi_strerror(err)); +#if 0 + err = ncmpi_set_fill(ncid, NC_NOFILL, NULL); + IF (err) + error("ncmpi_set_fill: %s", ncmpi_strerror(err)); +#endif + err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid); + IF (err) + error("ncmpi_def_dim: %s", ncmpi_strerror(err)); + err = ncmpi_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid); + IF (err) + error("ncmpi_def_var: %s", ncmpi_strerror(err)); + err = ncmpi_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1); + IF (err) + error("ncmpi_def_var: %s", ncmpi_strerror(err)); + { + int dimids[NDIMS +1]; + int ii = 0; + for(ii = 0; ii < NDIMS; ii++) + dimids[ii] = ii; + dimids[NDIMS] = dimid; + err = ncmpi_def_var(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1); + IF (err) + error("ncmpi_def_var: %s", ncmpi_strerror(err)); + } + err = ncmpi_put_att_text(ncid, NC_GLOBAL, "title", 1+strlen(title), title); + IF (err) + error("ncmpi_put_att_text: %s", ncmpi_strerror(err)); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + var = 1.0; + ncmpi_begin_indep_data(ncid); + err = ncmpi_put_var1_double(ncid, varid, NULL, &var); + IF (err) + error("ncmpi_put_var1_double: %s", ncmpi_strerror(err)); + ncmpi_end_indep_data(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* check scratch file written as expected */ + check_file(scratch); + err = ncmpi_open(comm, scratch, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_inq_dim(ncid, dimid, name, &length); + IF (err) + error("ncmpi_inq_dim: %s", ncmpi_strerror(err)); + IF (strcmp(name, "abc") != 0) + error("Unexpected dim name"); + IF (length != sizehint) + error("Unexpected dim length"); + ncmpi_begin_indep_data(ncid); + err = ncmpi_get_var1_double(ncid, varid, NULL, &var); + IF (err) + error("ncmpi_get_var1_double: %s", ncmpi_strerror(err)); + ncmpi_end_indep_data(ncid); + IF (var != 1.0) + error("ncmpi_get_var1_double: unexpected value"); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_enddef + * Simply calls test_ncmpi_redef which tests both ncmpi_redef & ncmpi_enddef + */ +void +test_ncmpi_enddef(void) +{ + test_ncmpi_redef(); +} + + +/* + * Test ncmpi_sync + * try with bad handle, check error + * try in define mode, check error + * try writing with one handle, reading with another on same netCDF + */ +void +test_ncmpi_sync(void) +{ + int ncidw; /* netcdf id for writing */ + int ncidr; /* netcdf id for reading */ + int err; + + /* BAD_ID test */ + err = ncmpi_sync(BAD_ID); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* create scratch file & try ncmpi_sync in define mode */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncidw); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_sync(ncidw); + IF (err != NC_EINDEFINE) + error("ncmpi_sync called in define mode: status = %d", err); + + /* write using same handle */ + def_dims(ncidw); + def_vars(ncidw); + put_atts(ncidw); + err = ncmpi_enddef(ncidw); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + put_vars(ncidw); + err = ncmpi_sync(ncidw); + IF (err) + error("ncmpi_sync of ncidw failed: %s", ncmpi_strerror(err)); + + /* open another handle, ncmpi_sync, read (check) */ + err = ncmpi_open(comm, scratch, NC_NOWRITE, MPI_INFO_NULL, &ncidr); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_sync(ncidr); + IF (err) + error("ncmpi_sync of ncidr failed: %s", ncmpi_strerror(err)); + check_dims(ncidr); + check_atts(ncidr); + check_vars(ncidr); + + /* close both handles */ + err = ncmpi_close(ncidr); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_close(ncidw); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_abort + * try with bad handle, check error + * try in define mode before anything written, check that file was deleted + * try after ncmpi_enddef, ncmpi_redef, define new dims, vars, atts + * try after writing variable + */ +void +test_ncmpi_abort(void) +{ + int ncid; /* netcdf id */ + int err; + int ndims; + int nvars; + int ngatts; + + /* BAD_ID test */ + err = ncmpi_abort(BAD_ID); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* create scratch file & try ncmpi_abort in define mode */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = ncmpi_abort(ncid); + IF (err) + error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err)); + err = ncmpi_close(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_delete(scratch, MPI_INFO_NULL); /* should already be deleted */ + IF (!err) + error("file %s should not exist", scratch); + + /* + * create scratch file + * do ncmpi_enddef & ncmpi_redef + * define new dims, vars, atts + * try ncmpi_abort: should restore previous state (no dims, vars, atts) + */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + err = ncmpi_redef(ncid); + IF (err) + error("ncmpi_redef: %s", ncmpi_strerror(err)); + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = ncmpi_abort(ncid); + IF (err) + error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err)); + err = ncmpi_close(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_open(comm, scratch, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_inq (ncid, &ndims, &nvars, &ngatts, NULL); + IF (err) + error("ncmpi_inq: %s", ncmpi_strerror(err)); + IF (ndims != 0) + error("ndims should be 0"); + IF (nvars != 0) + error("nvars should be 0"); + IF (ngatts != 0) + error("ngatts should be 0"); + err = ncmpi_close (ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* try ncmpi_abort in data mode - should just close */ + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + put_vars(ncid); + err = ncmpi_abort(ncid); + IF (err) + error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err)); + err = ncmpi_close(ncid); /* should already be closed */ + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + check_file(scratch); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_def_dim + * try with bad netCDF handle, check error + * try in data mode, check error + * check that returned id is one more than previous id + * try adding same dimension twice, check error + * try with illegal sizes, check error + * make sure unlimited size works, shows up in ncmpi_inq_unlimdim + * try to define a second unlimited dimension, check error + */ +void +test_ncmpi_def_dim(void) +{ + int ncid; + int err; /* status */ + int i; + int dimid; /* dimension id */ + MPI_Offset length; + + /* BAD_ID test */ + err = ncmpi_def_dim(BAD_ID, "abc", 8, &dimid); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* data mode test */ + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + err = ncmpi_def_dim(ncid, "abc", 8, &dimid); + IF (err != NC_ENOTINDEFINE) + error("bad ncid: status = %d", err); + + /* define-mode tests: unlimited dim */ + err = ncmpi_redef(ncid); + IF (err) + error("ncmpi_redef: %s", ncmpi_strerror(err)); + err = ncmpi_def_dim(ncid, dim_name[0], NC_UNLIMITED, &dimid); + IF (err) + error("ncmpi_def_dim: %s", ncmpi_strerror(err)); + IF (dimid != 0) + error("Unexpected dimid"); + err = ncmpi_inq_unlimdim(ncid, &dimid); + IF (err) + error("ncmpi_inq_unlimdim: %s", ncmpi_strerror(err)); + IF (dimid != 0) + error("Unexpected recdim"); + err = ncmpi_inq_dimlen(ncid, dimid, &length); + IF (length != 0) + error("Unexpected length"); + err = ncmpi_def_dim(ncid, "abc", NC_UNLIMITED, &dimid); + IF (err != NC_EUNLIMIT) + error("2nd unlimited dimension: status = %d", err); + + /* define-mode tests: remaining dims */ + for (i = 1; i < NDIMS; i++) { + err = ncmpi_def_dim(ncid, dim_name[i-1], dim_len[i], &dimid); + IF (err != NC_ENAMEINUSE) + error("duplicate name: status = %d", err); + err = ncmpi_def_dim(ncid, BAD_NAME, dim_len[i], &dimid); + IF (err != NC_EBADNAME) + error("bad name: status = %d", err); + err = ncmpi_def_dim(ncid, dim_name[i], NC_UNLIMITED-1, &dimid); + IF (err != NC_EDIMSIZE) + error("bad size: status = %d", err); + err = ncmpi_def_dim(ncid, dim_name[i], dim_len[i], &dimid); + IF (err) + error("ncmpi_def_dim: %s", ncmpi_strerror(err)); + IF (dimid != i) + error("Unexpected dimid"); + } + + /* Following just to expand unlimited dim */ + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + put_vars(ncid); + + /* Check all dims */ + check_dims(ncid); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_rename_dim + * try with bad netCDF handle, check error + * check that proper rename worked with ncmpi_inq_dim + * try renaming to existing dimension name, check error + * try with bad dimension handle, check error + */ +void +test_ncmpi_rename_dim(void) +{ + int ncid; + int err; /* status */ + char name[NC_MAX_NAME]; + + /* BAD_ID test */ + err = ncmpi_rename_dim(BAD_ID, 0, "abc"); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* main tests */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + err = ncmpi_rename_dim(ncid, BAD_DIMID, "abc"); + IF (err != NC_EBADDIM) + error("bad dimid: status = %d", err); + err = ncmpi_rename_dim(ncid, 2, "abc"); + IF (err) + error("ncmpi_rename_dim: %s", ncmpi_strerror(err)); + err = ncmpi_inq_dimname(ncid, 2, name); + IF (strcmp(name, "abc") != 0) + error("Unexpected name: %s", name); + err = ncmpi_rename_dim(ncid, 0, "abc"); + IF (err != NC_ENAMEINUSE) + error("duplicate name: status = %d", err); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_def_var + * try with bad netCDF handle, check error + * try with bad name, check error + * scalar tests: + * check that proper define worked with ncmpi_inq_var + * try redefining an existing variable, check error + * try with bad datatype, check error + * try with bad number of dimensions, check error + * try in data mode, check error + * check that returned id is one more than previous id + * try with bad dimension ids, check error + */ +void +test_ncmpi_def_var(void) +{ + int ncid; + int varid; + int err; /* status */ + int i; + int ndims; + int natts; + char name[NC_MAX_NAME]; + int dimids[MAX_RANK]; + ncmpi_type datatype; + + /* BAD_ID test */ + err = ncmpi_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* scalar tests */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid); + IF (err) + error("ncmpi_def_var: %s", ncmpi_strerror(err)); + err = ncmpi_inq_var(ncid, varid, name, &datatype, &ndims, dimids, &natts); + IF (err) + error("ncmpi_inq_var: %s", ncmpi_strerror(err)); + IF (strcmp(name, "abc") != 0) + error("Unexpected name: %s", name); + IF (datatype != NC_SHORT) + error("Unexpected datatype"); + IF (ndims != 0) + error("Unexpected rank"); + err = ncmpi_def_var(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid); + IF (err != NC_EBADNAME) + error("bad name: status = %d", err); + err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid); + IF (err != NC_ENAMEINUSE) + error("duplicate name: status = %d", err); + err = ncmpi_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid); + IF (err != NC_EBADTYPE) + error("bad type: status = %d", err); + err = ncmpi_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid); + IF (err != NC_EINVAL) + error("bad rank: status = %d", err); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + err = ncmpi_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid); + IF (err != NC_ENOTINDEFINE) + error("ncmpi_def_var called in data mode: status = %d", err); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); + + /* general tests using global vars */ + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + for (i = 0; i < NVARS; i++) { + err = ncmpi_def_var(ncid, var_name[i], var_type[i], var_rank[i], + var_dimid[i], &varid); + IF (err) + error("ncmpi_def_var: %s", ncmpi_strerror(err)); + IF (varid != i) + error("Unexpected varid"); + } + + /* try bad dim ids */ + dimids[0] = BAD_DIMID; + err = ncmpi_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid); + IF (err != NC_EBADDIM) + error("bad dim ids: status = %d", err); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +#ifdef TEST_VOIDSTAR +/* + * Test ncmpi_put_var1 + */ +void +test_ncmpi_put_var1(void) +{ + int ncid; + int i; + int j; + int err; + MPI_Offset index[MAX_RANK]; + double value; + double buf[1]; /* (void *) buffer */ + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + for (j = 0; j < var_rank[i]; j++) + index[j] = 0; + err = ncmpi_put_var1(BAD_ID, i, index, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_var1(ncid, BAD_VARID, index, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + index[j] = var_shape[i][j]; + err = ncmpi_put_var1(ncid, i, index, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + index[j] = 0; + } + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase"); + value = hash( var_type[i], var_rank[i], index); + if (inRange(value, var_type[i])) { + err = dbl2nc(value, var_type[i], buf); + IF (err) + error("error in dbl2nc"); + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_var1(ncid, i, NULL, buf); + else + err = ncmpi_put_var1(ncid, i, index, buf); + IF (err) + error("%s", ncmpi_strerror(err)); + } + } + } + + check_vars(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_put_vara + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Redefine buffer for each put. + * At end check all variables using check_vars + */ +void +test_ncmpi_put_vara(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int err; + int nels; + int nslabs; + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + err = ncmpi_put_vara(BAD_ID, i, start, edge, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_vara(ncid, BAD_VARID, start, edge, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_vara(ncid, i, start, edge, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_vara(ncid, i, start, edge, buf); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + p = (char *) buf; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], edge, index); + IF (err) + error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + value = hash( var_type[i], var_rank[i], index); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_vara(ncid, i, NULL, NULL, buf); + else + err = ncmpi_put_vara(ncid, i, start, edge, buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } + } + } + + check_vars(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_put_vars + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Redefine buffer for each put. + * At end check all variables using check_vars + */ +void +test_ncmpi_put_vars(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int nels; + int nslabs; + int nstarts; /* number of different starts */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + err = ncmpi_put_vars(BAD_ID, i, start, edge, stride, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_vars(ncid, BAD_VARID, start, edge, stride, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_put_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } + */ + p = (char *) buf; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + value = hash( var_type[i], var_rank[i], index2); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + if (var_rank[i] == 0 && i%2 == 0) + err = ncmpi_put_vars(ncid, i, NULL, NULL, NULL, buf); + else + err = ncmpi_put_vars(ncid, i, index, count, stride, buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } + } + } + } + + check_vars(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_put_varm + * Choose a random point dividing each dim into 2 parts + * Put 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Buffer is bit image of whole external variable. + * So all puts for a variable put different elements of buffer + * At end check all variables using check_vars + */ +void +test_ncmpi_put_varm(void) +{ + int ncid; + int i; + int j; + int k; + int m; + int err; + int nslabs; + int nstarts; /* number of different starts */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + MPI_Offset imap[MAX_RANK]; + MPI_Offset imap2[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double value; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = 0; i < NVARS; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + if (var_rank[i] > 0) { + j = var_rank[i] - 1; + imap[j] = nctypelen(var_type[i]); + for (; j > 0; j--) + imap[j-1] = imap[j] * var_shape[i][j]; + } + p = (char *) buf; + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase"); + value = hash( var_type[i], var_rank[i], index); + if (!inRange(value, var_type[i])) + value = 0; + err = dbl2nc(value, var_type[i], p); + IF (err) + error("error in dbl2nc"); + p += nctypelen(var_type[i]); + } + err = ncmpi_put_varm(BAD_ID, i, start, edge, stride, imap, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_varm(ncid, BAD_VARID, start, edge, stride, imap, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + err = ncmpi_put_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_put_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_put_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* put 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to put lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + imap2[j] = imap[j] * sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + if (var_rank[i] == 0 && i%2 == 0) { + err = ncmpi_put_varm(ncid, i, NULL, NULL, NULL, NULL, buf); + } else { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } + */ + j = fromMixedBase(var_rank[i], index, var_shape[i]); + p = (char *) buf + j * nctypelen(var_type[i]); + err = ncmpi_put_varm(ncid, i, index, count, stride, imap2, p); + } + IF (err) { + error("%s", ncmpi_strerror(err)); + } + } + } + } + + check_vars(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +#endif /* TEST_VOIDSTAR */ + + +/* + * Test ncmpi_rename_var + * try with bad netCDF handle, check error + * try with bad variable handle, check error + * try renaming to existing variable name, check error + * check that proper rename worked with ncmpi_inq_varid + * try in data mode, check error + */ +void +test_ncmpi_rename_var(void) +{ + int ncid; + int varid; + int err; + int i; + char name[NC_MAX_NAME]; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_rename_var(ncid, BAD_VARID, "newName"); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + def_dims(ncid); + def_vars(ncid); + + /* Prefix "new_" to each name */ + for (i = 0; i < NVARS; i++) { + err = ncmpi_rename_var(BAD_ID, i, "newName"); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_rename_var(ncid, i, var_name[NVARS-1]); + IF (err != NC_ENAMEINUSE) + error("duplicate name: status = %d", err); + (void) strcpy(name, "new_"); + (void) strcat(name, var_name[i]); + err = ncmpi_rename_var(ncid, i, name); + IF (err) + error("ncmpi_rename_var: %s", ncmpi_strerror(err)); + err = ncmpi_inq_varid(ncid, name, &varid); + IF (err) + error("ncmpi_inq_varid: %s", ncmpi_strerror(err)); + IF (varid != i) + error("Unexpected varid"); + } + + /* Change to data mode */ + /* Try making names even longer. Then restore original names */ + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + (void) strcpy(name, "even_longer_"); + (void) strcat(name, var_name[i]); + err = ncmpi_rename_var(ncid, i, name); + IF (err != NC_ENOTINDEFINE) + error("longer name in data mode: status = %d", err); + err = ncmpi_rename_var(ncid, i, var_name[i]); + IF (err) + error("ncmpi_rename_var: %s", ncmpi_strerror(err)); + err = ncmpi_inq_varid(ncid, var_name[i], &varid); + IF (err) + error("ncmpi_inq_varid: %s", ncmpi_strerror(err)); + IF (varid != i) + error("Unexpected varid"); + } + + put_vars(ncid); + check_vars(ncid); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +#ifdef TEST_VOIDSTAR +void +test_ncmpi_put_att(void) +{ + int ncid; + int varid; + int i; + int j; + MPI_Offset k; + int err; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + char *name; /* of att */ + ncmpi_type datatype; /* of att */ + size_t length; /* of att */ + double value; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + name = ATT_NAME(i,j); + datatype = ATT_TYPE(i,j); + length = ATT_LEN(i,j); + err = ncmpi_put_att(BAD_ID, varid, name, datatype, length, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_put_att(ncid, varid, BAD_NAME, datatype, length, buf); + IF (err != NC_EBADNAME) + error("bad name: status = %d", err); + err = ncmpi_put_att(ncid, BAD_VARID, name, datatype, length, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_put_att(ncid, varid, name, BAD_TYPE, length, buf); + IF (err != NC_EBADTYPE) + error("bad type: status = %d", err); + p = (char *) buf; + for (k = 0; k < length; k++) { + value = hash(datatype, -1, &k ); + if (!inRange(value, datatype)) + value = 0; + err = dbl2nc(value, datatype, p); + IF (err) + error("error in dbl2nc"); + p += nctypelen(datatype); + } + err = ncmpi_put_att(ncid, varid, name, datatype, length, buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } + } + } + + check_atts(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} +#endif /* TEST_VOIDSTAR */ + + +/* + * Test ncmpi_copy_att + * try with bad source or target netCDF handles, check error + * try with bad source or target variable handle, check error + * try with nonexisting attribute, check error + * check that NC_GLOBAL variable for source or target works + * check that new attribute put works with target in define mode + * check that old attribute put works with target in data mode + * check that changing type and length of an attribute work OK + * try with same ncid for source and target, different variables + * try with same ncid for source and target, same variable + */ +void +test_ncmpi_copy_att(void) +{ + int ncid_in; + int ncid_out; + int varid; + int err; + int i; + int j; + char *name; /* of att */ + ncmpi_type datatype; /* of att */ + MPI_Offset length; /* of att */ + char value; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid_in); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid_out); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid_out); + def_vars(ncid_out); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + name = ATT_NAME(i,j); + err = ncmpi_copy_att(ncid_in, BAD_VARID, name, ncid_out, varid); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, BAD_VARID); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_copy_att(BAD_ID, varid, name, ncid_out, varid); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_copy_att(ncid_in, varid, name, BAD_ID, varid); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_copy_att(ncid_in, varid, "noSuch", ncid_out, varid); + IF (err != NC_ENOTATT) + error("bad attname: status = %d", err); + err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, varid); + IF (err) + error("ncmpi_copy_att: %s", ncmpi_strerror(err)); + err = ncmpi_copy_att(ncid_out, varid, name, ncid_out, varid); + IF (err) + error("source = target: %s", ncmpi_strerror(err)); + } + } + + err = ncmpi_close(ncid_in); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* Close scratch. Reopen & check attributes */ + err = ncmpi_close(ncid_out); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_open(comm, scratch, NC_WRITE, MPI_INFO_NULL, &ncid_out); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + check_atts(ncid_out); + + /* + * change to define mode + * define single char. global att. ':a' with value 'A' + * This will be used as source for following copies + */ + err = ncmpi_redef(ncid_out); + IF (err) + error("ncmpi_redef: %s", ncmpi_strerror(err)); + err = ncmpi_put_att_text(ncid_out, NC_GLOBAL, "a", 1, "A"); + IF (err) + error("ncmpi_put_att_text: %s", ncmpi_strerror(err)); + + /* + * change to data mode + * Use scratch as both source & dest. + * try copy to existing att. change type & decrease length + * rename 1st existing att of each var (if any) 'a' + * if this att. exists them copy ':a' to it + */ + err = ncmpi_enddef(ncid_out); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) { + err = ncmpi_rename_att(ncid_out, i, att_name[i][0], "a"); + IF (err) + error("ncmpi_rename_att: %s", ncmpi_strerror(err)); + err = ncmpi_copy_att(ncid_out, NC_GLOBAL, "a", ncid_out, i); + IF (err) + error("ncmpi_copy_att: %s", ncmpi_strerror(err)); + } + } + err = ncmpi_close(ncid_out); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* Reopen & check */ + err = ncmpi_open(comm, scratch, NC_WRITE, MPI_INFO_NULL, &ncid_out); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) { + err = ncmpi_inq_att(ncid_out, i, "a", &datatype, &length); + IF (err) + error("ncmpi_inq_att: %s", ncmpi_strerror(err)); + IF (datatype != NC_CHAR) + error("Unexpected type"); + IF (length != 1) + error("Unexpected length"); + err = ncmpi_get_att_text(ncid_out, i, "a", &value); + IF (err) + error("ncmpi_get_att_text: %s", ncmpi_strerror(err)); + IF (value != 'A') + error("Unexpected value"); + } + } + + err = ncmpi_close(ncid_out); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_rename_att + * try with bad netCDF handle, check error + * try with bad variable handle, check error + * try with nonexisting att name, check error + * try renaming to existing att name, check error + * check that proper rename worked with ncmpi_inq_attid + * try in data mode, check error + */ +void +test_ncmpi_rename_att(void) +{ + int ncid; + int varid; + int err; + int i; + int j; + MPI_Offset k; + int attnum; + char *attname; + char name[NC_MAX_NAME]; + char oldname[NC_MAX_NAME]; + char newname[NC_MAX_NAME]; + int nok = 0; /* count of valid comparisons */ + ncmpi_type datatype; + ncmpi_type atttype; + MPI_Offset length; + size_t attlength; + char text[MAX_NELS]; + double value[MAX_NELS]; + double expect; + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_rename_att(ncid, BAD_VARID, "abc", "newName"); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + err = ncmpi_rename_att(BAD_ID, varid, attname, "newName"); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_rename_att(ncid, varid, "noSuch", "newName"); + IF (err != NC_ENOTATT) + error("bad attname: status = %d", err); + (void) strcpy(newname, "new_"); + (void) strcat(newname, attname); + err = ncmpi_rename_att(ncid, varid, attname, newname); + IF (err) + error("ncmpi_rename_att: %s", ncmpi_strerror(err)); + err = ncmpi_inq_attid(ncid, varid, newname, &attnum); + IF (err) + error("ncmpi_inq_attid: %s", ncmpi_strerror(err)); + IF (attnum != j) + error("Unexpected attnum"); + } + } + + /* Close. Reopen & check */ + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_open(comm, scratch, NC_WRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + atttype = ATT_TYPE(i,j); + attlength = ATT_LEN(i,j); + (void) strcpy(newname, "new_"); + (void) strcat(newname, attname); + err = ncmpi_inq_attname(ncid, varid, j, name); + IF (err) + error("ncmpi_inq_attname: %s", ncmpi_strerror(err)); + IF (strcmp(name, newname) != 0) + error("ncmpi_inq_attname: unexpected name"); + err = ncmpi_inq_att(ncid, varid, name, &datatype, &length); + IF (err) + error("ncmpi_inq_att: %s", ncmpi_strerror(err)); + IF (datatype != atttype) + error("ncmpi_inq_att: unexpected type"); + IF (length != attlength) + error("ncmpi_inq_att: unexpected length"); + if (datatype == NC_CHAR) { + err = ncmpi_get_att_text(ncid, varid, name, text); + IF (err) + error("ncmpi_get_att_text: %s", ncmpi_strerror(err)); + for (k = 0; k < attlength; k++) { + expect = hash(datatype, -1, &k); + IF (text[k] != expect) { + error("ncmpi_get_att_text: unexpected value"); + } else { + nok++; + } + } + } else { + err = ncmpi_get_att_double(ncid, varid, name, value); + IF (err) + error("ncmpi_get_att_double: %s", ncmpi_strerror(err)); + for (k = 0; k < attlength; k++) { + expect = hash(datatype, -1, &k); + if (inRange(expect, datatype)) { + IF (!equal(value[k],expect,datatype,NCT_DOUBLE)) { + error("ncmpi_get_att_double: unexpected value"); + } else { + nok++; + } + } + } + } + } + } + print_nok(nok); + + /* Now in data mode */ + /* Try making names even longer. Then restore original names */ + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + for (j = 0; j < NATTS(i); j++) { + attname = ATT_NAME(i,j); + (void) strcpy(oldname, "new_"); + (void) strcat(oldname, attname); + (void) strcpy(newname, "even_longer_"); + (void) strcat(newname, attname); + err = ncmpi_rename_att(ncid, varid, oldname, newname); + IF (err != NC_ENOTINDEFINE) + error("longer name in data mode: status = %d", err); + err = ncmpi_rename_att(ncid, varid, oldname, attname); + IF (err) + error("ncmpi_rename_att: %s", ncmpi_strerror(err)); + err = ncmpi_inq_attid(ncid, varid, attname, &attnum); + IF (err) + error("ncmpi_inq_attid: %s", ncmpi_strerror(err)); + IF (attnum != j) + error("Unexpected attnum"); + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_del_att + * try with bad netCDF handle, check error + * try with bad variable handle, check error + * try with nonexisting att name, check error + * check that proper delete worked using: + * ncmpi_inq_attid, ncmpi_inq_natts, ncmpi_inq_varnatts + */ +void +test_ncmpi_del_att(void) +{ + int ncid; + int err; + int i; + int j; + int attnum; + int natts; + int numatts; + int varid; + char *name; /* of att */ + + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + err = ncmpi_del_att(ncid, BAD_VARID, "abc"); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + numatts = NATTS(i); + for (j = 0; j < numatts; j++) { + name = ATT_NAME(i,j); + err = ncmpi_del_att(BAD_ID, varid, name); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_del_att(ncid, varid, "noSuch"); + IF (err != NC_ENOTATT) + error("bad attname: status = %d", err); + err = ncmpi_del_att(ncid, varid, name); + IF (err) + error("ncmpi_del_att: %s", ncmpi_strerror(err)); + err = ncmpi_inq_attid(ncid, varid, name, &attnum); + IF (err != NC_ENOTATT) + error("bad attname: status = %d", err); + if (i < 0) { + err = ncmpi_inq_natts(ncid, &natts); + IF (err) + error("ncmpi_inq_natts: %s", ncmpi_strerror(err)); + IF (natts != numatts-j-1) + error("natts: expected %d, got %d", numatts-j-1, natts); + } + err = ncmpi_inq_varnatts(ncid, varid, &natts); + IF (err) + error("ncmpi_inq_natts: %s", ncmpi_strerror(err)); + IF (natts != numatts-j-1) + error("natts: expected %d, got %d", numatts-j-1, natts); + } + } + + /* Close. Reopen & check no attributes left */ + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_open(comm, scratch, NC_WRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_inq_natts(ncid, &natts); + IF (err) + error("ncmpi_inq_natts: %s", ncmpi_strerror(err)); + IF (natts != 0) + error("natts: expected %d, got %d", 0, natts); + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + err = ncmpi_inq_varnatts(ncid, varid, &natts); + IF (err) + error("ncmpi_inq_natts: %s", ncmpi_strerror(err)); + IF (natts != 0) + error("natts: expected %d, got %d", 0, natts); + } + + /* restore attributes. change to data mode. try to delete */ + err = ncmpi_redef(ncid); + IF (err) + error("ncmpi_redef: %s", ncmpi_strerror(err)); + put_atts(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + varid = VARID(i); + numatts = NATTS(i); + for (j = 0; j < numatts; j++) { + name = ATT_NAME(i,j); + err = ncmpi_del_att(ncid, varid, name); + IF (err != NC_ENOTINDEFINE) + error("in data mode: status = %d", err); + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} + + +/* + * Test ncmpi_set_fill + * try with bad netCDF handle, check error + * try in read-only mode, check error + * try with bad new_fillmode, check error + * try in data mode, check error + * check that proper set to NC_FILL works for record & non-record variables + * (note that it is not possible to test NC_NOFILL mode!) + * close file & create again for test using attribute _FillValue + */ +void +test_ncmpi_set_fill(void) +{ + fprintf(stderr, "unimplemented"); +#if 0 + int ncid; + int varid; + int err; + int i; + int j; + int old_fillmode; + int nok = 0; /* count of valid comparisons */ + char text = 0; + double value = 0; + double fill; + MPI_Offset index[MAX_RANK]; + + /* bad ncid */ + err = ncmpi_set_fill(BAD_ID, NC_NOFILL, &old_fillmode); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + + /* try in read-only mode */ + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode); + IF (err != NC_EPERM) + error("read-only: status = %d", err); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + + /* create scratch */ + err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + + /* BAD_FILLMODE */ + err = ncmpi_set_fill(ncid, BAD_FILLMODE, &old_fillmode); + IF (err != NC_EINVAL) + error("bad fillmode: status = %d", err); + + /* proper calls */ + err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode); + IF (err) + error("ncmpi_set_fill: %s", ncmpi_strerror(err)); + IF (old_fillmode != NC_FILL) + error("Unexpected old fill mode: %d", old_fillmode); + err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode); + IF (err) + error("ncmpi_set_fill: %s", ncmpi_strerror(err)); + IF (old_fillmode != NC_NOFILL) + error("Unexpected old fill mode: %d", old_fillmode); + + /* define dims & vars */ + def_dims(ncid); + def_vars(ncid); + + /* Change to data mode. Set fillmode again */ + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode); + IF (err) + error("ncmpi_set_fill: %s", ncmpi_strerror(err)); + IF (old_fillmode != NC_FILL) + error("Unexpected old fill mode: %d", old_fillmode); + + /* Write record number NRECS to force writing of preceding records */ + /* Assumes variable cr is char vector with UNLIMITED dimension */ + err = ncmpi_inq_varid(ncid, "cr", &varid); + IF (err) + error("ncmpi_inq_varid: %s", ncmpi_strerror(err)); + index[0] = NRECS; + err = ncmpi_put_var1_text(ncid, varid, index, &text); + IF (err) + error("ncmpi_put_var1_text: %s", ncmpi_strerror(err)); + + /* get all variables & check all values equal default fill */ + for (i = 0; i < NVARS; i++) { + switch (var_type[i]) { + case NC_CHAR: fill = NC_FILL_CHAR; break; + case NC_BYTE: fill = NC_FILL_BYTE; break; + case NC_SHORT: fill = NC_FILL_SHORT; break; + case NC_INT: fill = NC_FILL_INT; break; + case NC_FLOAT: fill = NC_FILL_FLOAT; break; + case NC_DOUBLE: fill = NC_FILL_DOUBLE; break; + default: assert(0); + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase"); + if (var_type[i] == NC_CHAR) { + err = ncmpi_get_var1_text(ncid, i, index, &text); + IF (err) + error("ncmpi_get_var1_text failed: %s", ncmpi_strerror(err)); + value = text; + } else { + err = ncmpi_get_var1_double(ncid, i, index, &value); + IF (err) + error("ncmpi_get_var1_double failed: %s", ncmpi_strerror(err)); + } + IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON) + error("\n\t\tValue expected: %-23.17e,\n\t\t read: %-23.17e\n", + fill, value); + else + nok++; + } + } + + /* close scratch & create again for test using attribute _FillValue */ + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_create: %s", ncmpi_strerror(err)); + return; + } + def_dims(ncid); + def_vars(ncid); + + /* set _FillValue = 42 for all vars */ + text = fill = 42; + for (i = 0; i < NVARS; i++) { + if (var_type[i] == NC_CHAR) { + err = ncmpi_put_att_text(ncid, i, "_FillValue", 1, &text); + IF (err) + error("ncmpi_put_att_text: %s", ncmpi_strerror(err)); + } else { + err = ncmpi_put_att_double(ncid, i, "_FillValue",var_type[i],1,&fill); + IF (err) + error("ncmpi_put_att_double: %s", ncmpi_strerror(err)); + } + } + + /* data mode. write records */ + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + index[0] = NRECS; + err = ncmpi_put_var1_text(ncid, varid, index, &text); + IF (err) + error("ncmpi_put_var1_text: %s", ncmpi_strerror(err)); + + /* get all variables & check all values equal 42 */ + for (i = 0; i < NVARS; i++) { + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase"); + if (var_type[i] == NC_CHAR) { + err = ncmpi_get_var1_text(ncid, i, index, &text); + IF (err) + error("ncmpi_get_var1_text failed: %s", ncmpi_strerror(err)); + value = text; + } else { + err = ncmpi_get_var1_double(ncid, i, index, &value); + IF (err) + error("ncmpi_get_var1_double failed: %s", ncmpi_strerror(err)); + } + IF (value != fill) + error(" Value expected: %g, read: %g\n", fill, value); + else + nok++; + } + } + print_nok(nok); + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +#endif +} + + +/* This function gets the version of a netCDF file, 1 is for netCDF + classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format. +*/ +#define MAGIC_NUM_LEN 4 +static +int +ncmpi_get_file_version(char *path, int *version) +{ + FILE *fp; + char magic[MAGIC_NUM_LEN]; + + /* Need two valid pointers - check for NULL. */ + if (!version || !path) + return NC_EINVAL; + + /* Figure out if this is a netcdf or hdf5 file. */ + if (!(fp = fopen(path, "r")) || + fread(magic, MAGIC_NUM_LEN, 1, fp) != 1) + return errno; + fclose(fp); + if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) + { + if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || + magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT) + *version = magic[MAGIC_NUM_LEN-1]; + else + return NC_ENOTNC; + } + /* tomorrow, tomorrow, I love you tomorrow, you're always a day + away! */ + /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F') + *version = 3;*/ + return NC_NOERR; +} + +/* + * Test nc_set_default_format + * try with bad default format + * try with NULL old_formatp + * try in data mode, check error + * check that proper set to NC_FILL works for record & non-record variables + * (note that it is not possible to test NC_NOFILL mode!) + * close file & create again for test using attribute _FillValue + */ +void +test_ncmpi_set_default_format(void) +{ + int ncid; + int err; + int i; + int version; + int old_format; + + /* bad format */ + err = ncmpi_set_default_format(BAD_DEFAULT_FORMAT, &old_format); + IF (err != NC_EINVAL) + error("bad default format: status = %d", err); + + /* NULL old_formatp */ + err = ncmpi_set_default_format(NC_FORMAT_64BIT, NULL); + IF (err) + error("null old_fortmatp: status = %d", err); + + /* Cycle through available formats. */ + for(i=1; i<3; i++) + { + if ((err = ncmpi_set_default_format(i, NULL))) + error("setting classic format: status = %d", err); + if ((err=ncmpi_create(comm, scratch, NC_CLOBBER, MPI_INFO_NULL, &ncid))) + error("bad nc_create: status = %d", err); + if ((err=ncmpi_put_att_text(ncid, NC_GLOBAL, "testatt", + sizeof("blah"), "blah"))) + error("bad put_att: status = %d", err); + if ( (err=ncmpi_close(ncid))) + error("bad close: status = %d", err); + if ( (err = ncmpi_get_file_version(scratch, &version)) ) + error("bad file version = %d", err); + if (version != i) + error("bad file version = %d", err); + } + + /* Remove the left-over file. */ + if ((err = ncmpi_delete(scratch, MPI_INFO_NULL))) + error("remove of %s failed", scratch); +} + + + + +/* + * Test ncmpi_delete + * create netcdf file 'scratch.nc' with no data, close it + * delete the file + */ +void +test_ncmpi_delete(void) +{ + int err; + int ncid; + + err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) + error("error creating scratch file %s, status = %d\n", scratch,err); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + err = ncmpi_delete(scratch, MPI_INFO_NULL); + IF (err) + error("remove of %s failed", scratch); +} Index: /tags/v1-0-3/test/nc_test/test_read.c =================================================================== --- /tags/v1-0-3/test/nc_test/test_read.c (revision 560) +++ /tags/v1-0-3/test/nc_test/test_read.c (revision 560) @@ -0,0 +1,1607 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include "tests.h" + +/* + * Test ncmpi_strerror. + * Try on a bad error status. + * Test for each defined error status. + */ +void +test_ncmpi_strerror(void) +{ + int i; + const char *message; + + static const struct { + int status; + const char *msg; + } ncerrs[] = { + {NC_NOERR, "No error"}, + {NC_EBADID, "Not a netCDF id"}, + {NC_ENFILE, "Too many netCDF files open"}, + {NC_EEXIST, "netCDF file exists && NC_NOCLOBBER"}, + {NC_EINVAL, "Invalid argument"}, + {NC_EPERM, "Write to read only"}, + {NC_ENOTINDEFINE, "Operation not allowed in data mode"}, + {NC_EINDEFINE, "Operation not allowed in define mode"}, + {NC_EINVALCOORDS, "Index exceeds dimension bound"}, + {NC_EMAXDIMS, "NC_MAX_DIMS exceeded"}, + {NC_ENAMEINUSE, "String match to name in use"}, + {NC_ENOTATT, "Attribute not found"}, + {NC_EMAXATTS, "NC_MAX_ATTRS exceeded"}, + {NC_EBADTYPE, "Not a netCDF data type or _FillValue type mismatch"}, + {NC_EBADDIM, "Invalid dimension id or name"}, + {NC_EUNLIMPOS, "NC_UNLIMITED in the wrong index"}, + {NC_EMAXVARS, "NC_MAX_VARS exceeded"}, + {NC_ENOTVAR, "Variable not found"}, + {NC_EGLOBAL, "Action prohibited on NC_GLOBAL varid"}, + {NC_ENOTNC, "Not a netCDF file"}, + {NC_ESTS, "In Fortran, string too short"}, + {NC_EMAXNAME, "NC_MAX_NAME exceeded"}, + {NC_EUNLIMIT, "NC_UNLIMITED size already in use"}, + {NC_ENORECVARS, "nc_rec op when there are no record vars"}, + {NC_ECHAR, "Attempt to convert between text & numbers"}, + {NC_EEDGE, "Edge+start exceeds dimension bound"}, + {NC_ESTRIDE, "Illegal stride"}, + {NC_EBADNAME, "Attribute or variable name contains illegal characters"}, + {NC_ERANGE, "Numeric conversion not representable"}, + {NC_ENOMEM, "Memory allocation (malloc) failure"}, + {NC_EVARSIZE, "One or more variable sizes violate format constraints"}, + {NC_EDIMSIZE, "Invalid dimension size"} + + }; + + /* Try on a bad error status */ + message = ncmpi_strerror(-666);/* should fail */ + IF (strcmp(message, "Unknown Error") != 0) + error("ncmpi_strerror on bad error status returned: %s", message); + + /* Try on each legitimate error status */ + for (i=0; i> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + if (var_rank[i] == 0 && i%2 ) + err = ncmpi_get_vara(ncid, i, NULL, NULL, buf); + else + err = ncmpi_get_vara(ncid, i, start, edge, buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + for (j = 0; j < nels; j++) { + p = (char *) buf; + p += j * nctypelen(var_type[i]); + err = nc2dbl( var_type[i], p, & got ); + IF (err) + error("error in nc2dbl"); + err = toMixedBase(j, var_rank[i], edge, index); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + expect = hash(var_type[i], var_rank[i], index); + if (inRange(expect,var_type[i])) { + IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g", expect); + error("got: %g", got); + } + } else { + nok++; + } + } + } + } + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} + + +/* + * Test ncmpi_get_vars + * Choose a random point dividing each dim into 2 parts + * Get 2^rank (nslabs) slabs so defined + * Each get overwrites buffer, so check after each get. + */ +void +test_ncmpi_get_vars(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int nels; + int nslabs; + int nstarts; /* number of different starts */ + int nok = 0; /* total count of valid comparisons */ + int n; /* count of valid comparisons within var */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + err = ncmpi_get_vars(BAD_ID, i, start, edge, stride, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_vars(ncid, BAD_VARID, start, edge, stride, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = ncmpi_get_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_get_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_get_vars(ncid, i, start, edge, stride, buf); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + n = 0; + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } + */ + if (var_rank[i] == 0 && i%2 ) + err = ncmpi_get_vars(ncid, i, NULL, NULL, NULL, buf); + else + err = ncmpi_get_vars(ncid, i, index, count, stride, buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + for (j = 0; j < nels; j++) { + p = (char *) buf; + p += j * nctypelen(var_type[i]); + err = nc2dbl( var_type[i], p, & got ); + IF (err) + error("error in nc2dbl"); + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + expect = hash(var_type[i], var_rank[i], index2); + if (inRange(expect,var_type[i])) { + IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect); + error("got: %g ", got); + } + } else { + nok++; + } + } + n++; + } + } + } + } + IF (n != var_nels[i]) { + error("count != nels"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("count: %d, ", n); + error("nels: %d ", var_nels[i]); + } + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} + + +/* + * Test ncmpi_get_varm + * Choose a random point dividing each dim into 2 parts + * Get 2^rank (nslabs) slabs so defined + * Choose random stride from 1 to edge + * Buffer should end up being bit image of external variable. + * So all gets for a variable store in different elements of buffer + */ +void +test_ncmpi_get_varm(void) +{ + int ncid; + int i; + int j; + int k; + int m; + int err; + int nslabs; + int nstarts; /* number of different starts */ + int nok = 0; /* total count of valid comparisons */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + MPI_Offset imap[MAX_RANK]; + MPI_Offset imap2[MAX_RANK]; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + if (var_rank[i] > 0) { + j = var_rank[i] - 1; + imap[j] = nctypelen(var_type[i]); + for (; j > 0; j--) + imap[j-1] = imap[j] * var_shape[i][j]; + } + err = ncmpi_get_varm(BAD_ID, i, start, edge, stride, imap, buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_varm(ncid, BAD_VARID, start, edge, stride, imap, buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + imap2[j] = imap[j] * sstride[j]; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + if (var_rank[i] == 0 && i%2 ) { + err = ncmpi_get_varm(ncid, i, NULL, NULL, NULL, NULL, buf); + } else { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } + */ + j = fromMixedBase(var_rank[i], index, var_shape[i]); + p = (char *) buf + j * nctypelen(var_type[i]); + err = ncmpi_get_varm(ncid, i, index, count, stride, imap2, p); + } + IF (err) + error("%s", ncmpi_strerror(err)); + } + } + p = (char *) buf; + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase"); + expect = hash( var_type[i], var_rank[i], index); + err = nc2dbl( var_type[i], p, & got ); + IF (err) + error("error in nc2dbl"); + if (inRange(expect,var_type[i])) { + IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect); + error("got: %g ", got); + } + } else { + nok++; + } + } + p += nctypelen(var_type[i]); + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} + + +void +test_ncmpi_get_att(void) +{ + int ncid; + int i; + int j; + MPI_Offset k; + int err; + double buf[MAX_NELS]; /* (void *) buffer */ + char *p; /* (void *) pointer */ + double expect; + double got; + int nok = 0; /* count of valid comparisons */ + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_get_att(BAD_ID, i, ATT_NAME(i,j), buf); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_att(ncid, BAD_VARID, ATT_NAME(i,j), buf); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_get_att(ncid, i, "noSuch", buf); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + err = ncmpi_get_att(ncid, i, ATT_NAME(i,j), buf); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + for (k = 0; k < ATT_LEN(i,j); k++) { + expect = hash(ATT_TYPE(i,j), -1, &k ); + p = (char *) buf; + p += k * nctypelen(ATT_TYPE(i,j)); + err = nc2dbl( ATT_TYPE(i,j), p, &got ); + IF (err) + error("error in nc2dbl"); + if (inRange(expect,ATT_TYPE(i,j))) { + IF (!equal(got,expect,ATT_TYPE(i,j),NCT_DOUBLE)) { + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", + i >= 0 ? var_name[i] : "Global"); + error("att_name: %s, ", ATT_NAME(i,j)); + error("element number: %d\n", k); + error("expect: %-23.16e\n", expect); + error(" got: %-23.16e", got); + } + } else { + nok++; + } + } + } + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +#endif /* TEST_VOIDSTAR */ + + +void +test_ncmpi_inq_att(void) +{ + int ncid; + int i; + int j; + int err; + ncmpi_type t; + MPI_Offset n; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_att(BAD_ID, i, ATT_NAME(i,j), &t, &n); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_inq_att(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_inq_att(ncid, i, "noSuch", &t, &n); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &t, &n); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (t != ATT_TYPE(i,j)) + error("type not that expected"); + IF (n != ATT_LEN(i,j)) + error("length not that expected"); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + + +void +test_ncmpi_inq_attlen(void) +{ + int ncid; + int i; + int j; + int err; + MPI_Offset len; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + err = ncmpi_inq_attlen(ncid, i, "noSuch", &len); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_attlen(BAD_ID, i, ATT_NAME(i,j), &len); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_inq_attlen(ncid, BAD_VARID, ATT_NAME(i,j), &len); + IF (err != NC_ENOTVAR) + error("bad varid: status = %d", err); + err = ncmpi_inq_attlen(ncid, i, ATT_NAME(i,j), &len); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (len != ATT_LEN(i,j)) + error("len not that expected"); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + + +void +test_ncmpi_inq_atttype(void) +{ + int ncid; + int i; + int j; + int err; + ncmpi_type datatype; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + err = ncmpi_inq_atttype(ncid, i, "noSuch", &datatype); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_atttype(BAD_ID, i, ATT_NAME(i,j), &datatype); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_inq_atttype(ncid, BAD_VARID, ATT_NAME(i,j), &datatype); + IF (err != NC_ENOTVAR) + error("bad varid: status = %d", err); + err = ncmpi_inq_atttype(ncid, i, ATT_NAME(i,j), &datatype); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (datatype != ATT_TYPE(i,j)) + error("type not that expected"); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + + +void +test_ncmpi_inq_attname(void) +{ + int ncid; + int i; + int j; + int err; + char name[NC_MAX_NAME]; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + err = ncmpi_inq_attname(ncid, i, BAD_ATTNUM, name); + IF (err != NC_ENOTATT) + error("Bad attribute number: status = %d", err); + err = ncmpi_inq_attname(ncid, i, NATTS(i), name); + IF (err != NC_ENOTATT) + error("Bad attribute number: status = %d", err); + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_attname(BAD_ID, i, j, name); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_inq_attname(ncid, BAD_VARID, j, name); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_inq_attname(ncid, i, j, name); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (strcmp(ATT_NAME(i,j), name) != 0) + error("name not that expected"); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + + +void +test_ncmpi_inq_attid(void) +{ + int ncid; + int i; + int j; + int err; + int attnum; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + err = ncmpi_inq_attid(ncid, i, "noSuch", &attnum); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_attid(BAD_ID, i, ATT_NAME(i,j), &attnum); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_inq_attid(ncid, BAD_VARID, ATT_NAME(i,j), &attnum); + IF (err != NC_ENOTVAR) + error("bad varid: status = %d", err); + err = ncmpi_inq_attid(ncid, i, ATT_NAME(i,j), &attnum); + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (attnum != j) + error("attnum not that expected"); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + Index: /tags/v1-0-3/test/nc_test/README =================================================================== --- /tags/v1-0-3/test/nc_test/README (revision 474) +++ /tags/v1-0-3/test/nc_test/README (revision 474) @@ -0,0 +1,9 @@ +This test is ported from Unidata netCDF-3.5 to test the functionality +of the PnetCDF API C interface particularly on a single processor. + +The typical way to run the test includes two steps: + + (1) create test.nc by " ./nc_test -c" + (2) run the test by " ./nc_test -v" + + Index: /tags/v1-0-3/test/nc_test/test_get.m4 =================================================================== --- /tags/v1-0-3/test/nc_test/test_get.m4 (revision 423) +++ /tags/v1-0-3/test/nc_test/test_get.m4 (revision 423) @@ -0,0 +1,904 @@ +dnl This is m4 source. +dnl Process using m4 to produce 'C' language file. +dnl +dnl If you see this line, you can ignore the next one. +/* Do not edit this file. It is produced from the corresponding .m4 source */ +dnl +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +undefine(`index')dnl +dnl dnl dnl +dnl +dnl Macros +dnl +dnl dnl dnl +dnl +dnl Upcase(str) +dnl +define(`Upcase',dnl +`dnl +translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl +dnl dnl dnl +dnl +dnl NCT_ITYPE(type) +dnl +define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl +dnl + +#include "tests.h" + +dnl TEST_NC_GET_VAR1(TYPE) +dnl +define(`TEST_NC_GET_VAR1',dnl +`dnl +void +test_ncmpi_get_var1_$1(void) +{ + int ncid; + int i; + int j; + int err; + int nok = 0; /* count of valid comparisons */ + MPI_Offset index[MAX_RANK]; + double expect; + int canConvert; /* Both text or both numeric */ + $1 value; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + ncmpi_begin_indep_data(ncid); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + for (j = 0; j < var_rank[i]; j++) + index[j] = 0; + err = ncmpi_get_var1_$1(BAD_ID, i, index, &value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_var1_$1(ncid, BAD_VARID, index, &value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + index[j] = var_shape[i][j]; + err = ncmpi_get_var1_$1(ncid, i, index, &value); + if(!canConvert) { + IF(err != NC_ECHAR) + error("conversion: status = %d", err); + } else IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + index[j] = 0; + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 1"); + expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) ); + if (var_rank[i] == 0 && i%2 ) + err = ncmpi_get_var1_$1(ncid, i, NULL, &value); + else + err = ncmpi_get_var1_$1(ncid, i, index, &value); + if (canConvert) { + if (inRange3(expect,var_type[i], NCT_ITYPE($1))) { + if (expect >= $1_min && expect <= $1_max) { + IF (err) { + error("%s", ncmpi_strerror(err)); + } else { + IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) { + error("expected: %G, got: %G", expect, + (double) value); + } else { + nok++; + } + } + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + } else { + IF (err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + ncmpi_end_indep_data(ncid); + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_VAR1(text) +TEST_NC_GET_VAR1(uchar) +TEST_NC_GET_VAR1(schar) +TEST_NC_GET_VAR1(short) +TEST_NC_GET_VAR1(int) +TEST_NC_GET_VAR1(long) +TEST_NC_GET_VAR1(float) +TEST_NC_GET_VAR1(double) + + +dnl TEST_NC_GET_VAR(TYPE) +dnl +define(`TEST_NC_GET_VAR',dnl +`dnl +void +test_ncmpi_get_var_$1(void) +{ + int ncid; + int i; + int j; + int err; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + int nels; + int nok = 0; /* count of valid comparisons */ + MPI_Offset index[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + $1 value[MAX_NELS]; + double expect[MAX_NELS]; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + err = ncmpi_get_var_$1_all(BAD_ID, i, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_var_$1_all(ncid, BAD_VARID, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + nels *= var_shape[i][j]; + } + allInExtRange = allInIntRange = 1; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 1"); + expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { + allInIntRange = allInIntRange && expect[j] >= $1_min + && expect[j] <= $1_max; + } else { + allInExtRange = 0; + } + } + err = ncmpi_get_var_$1_all(ncid, i, value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (j = 0; j < nels; j++) { + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) + && expect[j] >= $1_min && expect[j] <= $1_max) { + IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g", expect[j]); + error("got: %g", (double) value[j]); + } + } else { + nok++; + } + } + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_VAR(text) +TEST_NC_GET_VAR(uchar) +TEST_NC_GET_VAR(schar) +TEST_NC_GET_VAR(short) +TEST_NC_GET_VAR(int) +TEST_NC_GET_VAR(long) +TEST_NC_GET_VAR(float) +TEST_NC_GET_VAR(double) + + +dnl TEST_NC_GET_VARA(TYPE) +dnl +define(`TEST_NC_GET_VARA',dnl +`dnl +void +test_ncmpi_get_vara_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int err; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + int nels; + int nslabs; + int nok = 0; /* count of valid comparisons */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + $1 value[MAX_NELS]; + double expect[MAX_NELS]; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + } + err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + } + /* Check non-scalars for correct error returned even when */ + /* there is nothing to get (edge[j]==0) */ + if(var_rank[i] > 0) { + for (j = 0; j < var_rank[i]; j++) { + edge[j] = 0; + } + err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + if (var_dimid[i][j] > 0) { /* skip record dim */ + start[j] = var_shape[i][j]; + edge[j] = 1; /* added by Jianwei, fix NC_EINVALCOORDS bug */ + err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value); + IF (canConvert && err != NC_EINVALCOORDS) + error("bad start: status = %d", err); + start[j] = 0; + edge[j] = 0; /* added by Jianwei, restore original value */ + } + } + err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value); + if (canConvert) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ECHAR) + error("wrong type: status = %d", err); + } + for (j = 0; j < var_rank[i]; j++) { + edge[j] = 1; + } + } /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + for (k = 0; k < nslabs; k++) { + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + nels *= edge[j]; + } + allInExtRange = allInIntRange = 1; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], edge, index); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index[d] += start[d]; + expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1)); + if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) { + allInIntRange = allInIntRange && expect[j] >= $1_min + && expect[j] <= $1_max; + } else { + allInExtRange = 0; + } + } + if (var_rank[i] == 0 && i%2) + err = ncmpi_get_vara_$1_all(ncid, i, NULL, NULL, value); + else + err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (j = 0; j < nels; j++) { + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) + && expect[j] >= $1_min && expect[j] <= $1_max) { + IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g", expect[j]); + error("got: %g", (double) value[j]); + } + } else { + nok++; + } + } + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_VARA(text) +TEST_NC_GET_VARA(uchar) +TEST_NC_GET_VARA(schar) +TEST_NC_GET_VARA(short) +TEST_NC_GET_VARA(int) +TEST_NC_GET_VARA(long) +TEST_NC_GET_VARA(float) +TEST_NC_GET_VARA(double) + + +dnl TEST_NC_GET_VARS(TYPE) +dnl +define(`TEST_NC_GET_VARS',dnl +`dnl +void +test_ncmpi_get_vars_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + int nels; + int nslabs; + int nstarts; /* number of different starts */ + int nok = 0; /* count of valid comparisons */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + $1 value[MAX_NELS]; + double expect[MAX_NELS]; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + } + err = ncmpi_get_vars_$1_all(BAD_ID, i, start, edge, stride, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value); + if(!canConvert) { + IF (err != NC_ECHAR) + error("conversion: status = %d", err); + } else { + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } +*/ + allInExtRange = allInIntRange = 1; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + expect[j] = hash4(var_type[i], var_rank[i], index2, + NCT_ITYPE($1)); + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { + allInIntRange = allInIntRange && expect[j] >= $1_min + && expect[j] <= $1_max; + } else { + allInExtRange = 0; + } + } + if (var_rank[i] == 0 && i%2 ) + err = ncmpi_get_vars_$1_all(ncid, i, NULL, NULL, NULL, value); + else + err = ncmpi_get_vars_$1_all(ncid, i, index, count, stride, value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (j = 0; j < nels; j++) { + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) + && expect[j] >= $1_min && expect[j] <= $1_max) { + IF (!equal(value[j],expect[j],var_type[i], + NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect[j]); + error("got: %g", (double) value[j]); + } + } else { + nok++; + } + } + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_VARS(text) +TEST_NC_GET_VARS(uchar) +TEST_NC_GET_VARS(schar) +TEST_NC_GET_VARS(short) +TEST_NC_GET_VARS(int) +TEST_NC_GET_VARS(long) +TEST_NC_GET_VARS(float) +TEST_NC_GET_VARS(double) + + +dnl TEST_NC_GET_VARM(TYPE) +dnl +define(`TEST_NC_GET_VARM',dnl +`dnl +void +test_ncmpi_get_varm_$1(void) +{ + int ncid; + int d; + int i; + int j; + int k; + int m; + int err; + int allInExtRange; /* all values within external range? */ + int allInIntRange; /* all values within internal range? */ + int nels; + int nslabs; + int nstarts; /* number of different starts */ + int nok = 0; /* count of valid comparisons */ + MPI_Offset start[MAX_RANK]; + MPI_Offset edge[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + MPI_Offset index2[MAX_RANK]; + MPI_Offset mid[MAX_RANK]; + MPI_Offset count[MAX_RANK]; + MPI_Offset sstride[MAX_RANK]; + MPI_Offset stride[MAX_RANK]; + MPI_Offset imap[MAX_RANK]; + int canConvert; /* Both text or both numeric */ + $1 value[MAX_NELS]; + double expect[MAX_NELS]; + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + for (i = 0; i < NVARS; i++) { + canConvert = (var_type[i] == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + assert(var_rank[i] <= MAX_RANK); + assert(var_nels[i] <= MAX_NELS); + for (j = 0; j < var_rank[i]; j++) { + start[j] = 0; + edge[j] = 1; + stride[j] = 1; + imap[j] = 1; + } + err = ncmpi_get_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + for (j = 0; j < var_rank[i]; j++) { + start[j] = var_shape[i][j]; + err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value); + if(!canConvert) { + IF (err != NC_ECHAR) + error("conversion: status = %d", err); + } else { + IF (err != NC_EINVALCOORDS) + error("bad index: status = %d", err); + start[j] = 0; + edge[j] = var_shape[i][j] + 1; + err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value); + IF (err != NC_EEDGE) + error("bad edge: status = %d", err); + edge[j] = 1; + stride[j] = 0; + err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value); + IF (err != NC_ESTRIDE) + error("bad stride: status = %d", err); + stride[j] = 1; + } + } + /* Choose a random point dividing each dim into 2 parts */ + /* get 2^rank (nslabs) slabs so defined */ + nslabs = 1; + for (j = 0; j < var_rank[i]; j++) { + mid[j] = roll( var_shape[i][j] ); + nslabs *= 2; + } + /* bits of k determine whether to get lower or upper part of dim */ + /* choose random stride from 1 to edge */ + for (k = 0; k < nslabs; k++) { + nstarts = 1; + for (j = 0; j < var_rank[i]; j++) { + if ((k >> j) & 1) { + start[j] = 0; + edge[j] = mid[j]; + }else{ + start[j] = mid[j]; + edge[j] = var_shape[i][j] - mid[j]; + } + sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; + nstarts *= stride[j]; + } + for (m = 0; m < nstarts; m++) { + err = toMixedBase(m, var_rank[i], sstride, index); + IF (err) + error("error in toMixedBase"); + nels = 1; + for (j = 0; j < var_rank[i]; j++) { + count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; + nels *= count[j]; + index[j] += start[j]; + } + /* Random choice of forward or backward */ +/* TODO + if ( roll(2) ) { + for (j = 0; j < var_rank[i]; j++) { + index[j] += (count[j] - 1) * stride[j]; + stride[j] = -stride[j]; + } + } + */ + if (var_rank[i] > 0) { + j = var_rank[i] - 1; + imap[j] = 1; + for (; j > 0; j--) + imap[j-1] = imap[j] * count[j]; + } + allInExtRange = allInIntRange = 1; + for (j = 0; j < nels; j++) { + err = toMixedBase(j, var_rank[i], count, index2); + IF (err) + error("error in toMixedBase 1"); + for (d = 0; d < var_rank[i]; d++) + index2[d] = index[d] + index2[d] * stride[d]; + expect[j] = hash4(var_type[i], var_rank[i], index2, + NCT_ITYPE($1)); + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) { + allInIntRange = allInIntRange && expect[j] >= $1_min + && expect[j] <= $1_max; + } else { + allInExtRange = 0; + } + } + if (var_rank[i] == 0 && i%2 ) + err = ncmpi_get_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value); + else + err = ncmpi_get_varm_$1_all(ncid,i,index,count,stride,imap,value); + if (canConvert) { + if (allInExtRange) { + if (allInIntRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (j = 0; j < nels; j++) { + if (inRange3(expect[j],var_type[i],NCT_ITYPE($1)) + && expect[j] >= $1_min + && expect[j] <= $1_max) { + IF (!equal(value[j],expect[j],var_type[i], + NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("var_name: %s, ", var_name[i]); + error("element number: %d ", j); + error("expect: %g, ", expect[j]); + error("got: %g", (double) value[j]); + } + } else { + nok++; + } + } + } + } else { + IF (nels > 0 && err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + } + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_VARM(text) +TEST_NC_GET_VARM(uchar) +TEST_NC_GET_VARM(schar) +TEST_NC_GET_VARM(short) +TEST_NC_GET_VARM(int) +TEST_NC_GET_VARM(long) +TEST_NC_GET_VARM(float) +TEST_NC_GET_VARM(double) + + +dnl TEST_NC_GET_ATT(TYPE) +dnl +define(`TEST_NC_GET_ATT',dnl +`dnl +void +test_ncmpi_get_att_$1(void) +{ + int ncid; + int i; + int j; + MPI_Offset k; + int err; + int allInExtRange; + int allInIntRange; + int canConvert; /* Both text or both numeric */ + $1 value[MAX_NELS]; + double expect[MAX_NELS]; + int nok = 0; /* count of valid comparisons */ + + err = ncmpi_open(comm, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_open: %s", ncmpi_strerror(err)); + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_ITYPE($1) == NCT_TEXT); + err = ncmpi_get_att_$1(BAD_ID, i, ATT_NAME(i,j), value); + IF (err != NC_EBADID) + error("bad ncid: status = %d", err); + err = ncmpi_get_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), value); + IF (err != NC_ENOTVAR) + error("bad var id: status = %d", err); + err = ncmpi_get_att_$1(ncid, i, "noSuch", value); + IF (err != NC_ENOTATT) + error("Bad attribute name: status = %d", err); + allInExtRange = allInIntRange = 1; + for (k = 0; k < ATT_LEN(i,j); k++) { + expect[k] = hash4(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1)); + if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) { + allInIntRange = allInIntRange && expect[k] >= $1_min + && expect[k] <= $1_max; + } else { + allInExtRange = 0; + } + } + err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value); + if (canConvert || ATT_LEN(i,j) == 0) { + if (allInExtRange) { + if (allInIntRange) { + IF (err) + error("%s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("Range error: status = %d", err); + } + } else { + IF (err != 0 && err != NC_ERANGE) + error("OK or Range error: status = %d", err); + } + for (k = 0; k < ATT_LEN(i,j); k++) { + if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1)) + && expect[k] >= $1_min && expect[k] <= $1_max) { + IF (!equal(value[k],expect[k],ATT_TYPE(i,j), + NCT_ITYPE($1))){ + error("value read not that expected"); + if (verbose) { + error("\n"); + error("varid: %d, ", i); + error("att_name: %s, ", ATT_NAME(i,j)); + error("element number: %d ", k); + error("expect: %g", expect[k]); + error("got: %g", (double) value[k]); + } + } else { + nok++; + } + } + } + } else { + IF (err != NC_ECHAR) + error("wrong type: status = %d", err); + } + } + } + + err = ncmpi_close(ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + print_nok(nok); +} +')dnl + +TEST_NC_GET_ATT(text) +TEST_NC_GET_ATT(uchar) +TEST_NC_GET_ATT(schar) +TEST_NC_GET_ATT(short) +TEST_NC_GET_ATT(int) +TEST_NC_GET_ATT(long) +TEST_NC_GET_ATT(float) +TEST_NC_GET_ATT(double) + Index: /tags/v1-0-3/test/nc_test/util.c =================================================================== --- /tags/v1-0-3/test/nc_test/util.c (revision 560) +++ /tags/v1-0-3/test/nc_test/util.c (revision 560) @@ -0,0 +1,893 @@ +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include +#include "tests.h" + +/* Prototypes */ +static int inRange_float(const double value, const ncmpi_type datatype); + +void +print_nok(int nok) +{ + if (verbose || nfails > 0) + print("\n"); + print(" %d good comparisons. ", nok); +} + + +/* Is value within external type range? */ +int +inRange(const double value, const ncmpi_type datatype) +{ + double min, max; + + switch (datatype) { + case NC_CHAR: min = X_CHAR_MIN; max = X_CHAR_MAX; break; + case NC_BYTE: min = X_BYTE_MIN; max = X_BYTE_MAX; break; + case NC_SHORT: min = X_SHORT_MIN; max = X_SHORT_MAX; break; + case NC_INT: min = X_INT_MIN; max = X_INT_MAX; break; + case NC_FLOAT: min = X_FLOAT_MIN; max = X_FLOAT_MAX; break; + case NC_DOUBLE: min = X_DOUBLE_MIN; max = X_DOUBLE_MAX; break; + default: + min = 0.0; + max = 0.0; + assert(0); + } + return value >= min && value <= max; +} + +static int +inRange_uchar(const double value, const ncmpi_type datatype) +{ + if (datatype == NC_BYTE) { + return(value >= 0 && value <= 255); + } + /* else */ + return inRange(value, datatype); +} + +static int +inRange_float(const double value, const ncmpi_type datatype) +{ + double min, max; + + switch (datatype) { + case NC_CHAR: min = X_CHAR_MIN; max = X_CHAR_MAX; break; + case NC_BYTE: min = X_BYTE_MIN; max = X_BYTE_MAX; break; + case NC_SHORT: min = X_SHORT_MIN; max = X_SHORT_MAX; break; + case NC_INT: min = X_INT_MIN; max = X_INT_MAX; break; + case NC_FLOAT: + if(FLT_MAX < X_FLOAT_MAX) { + min = (-FLT_MAX); + max = FLT_MAX; + } else { + min = X_FLOAT_MIN; + max = X_FLOAT_MAX; + } + break; + case NC_DOUBLE: + if(FLT_MAX < X_DOUBLE_MAX) { + min = (-FLT_MAX); + max = FLT_MAX; + } else { + min = X_DOUBLE_MIN; + max = X_DOUBLE_MAX; + } + break; + default: + min = 0.0; + max = 0.0; + assert(0); + } + if(!( value >= min && value <= max)) { +#if 0 /* DEBUG */ + if(datatype == NC_FLOAT) { + fprintf(stderr, "\n"); + fprintf(stderr, "min % .17e\n", min); + fprintf(stderr, "value % .17e\n", value); + fprintf(stderr, "max % .17e\n", max); + } +#endif + return 0; + } +#if FLT_MANT_DIG != DBL_MANT_DIG + /* else */ + { + const float fvalue = value; + return fvalue >= min && fvalue <= max; + } +#else + return 1; +#endif +} + +/* wrapper for inRange to handle special NC_BYTE/uchar adjustment */ +int +inRange3( + const double value, + const ncmpi_type datatype, + const nct_itype itype) +{ + switch (itype) { + case NCT_UCHAR: + return inRange_uchar(value, datatype); + case NCT_FLOAT: + return inRange_float(value, datatype); + default: + break; + } + return inRange(value, datatype); +} + + +/* + * Does x == y, where one is internal and other external (netCDF)? + * Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON. + */ +int +equal( + const double x, + const double y, + ncmpi_type extType, /* external data type */ + nct_itype itype) +{ + const double flt_epsilon = 1.19209290E-07; + const double dbl_epsilon = 2.2204460492503131E-16; + double epsilon; + + epsilon = extType == NC_FLOAT || itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon; + return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y)); +} + +/* Test whether two int vectors are equal. If so return 1, else 0 */ +int +int_vec_eq(const int *v1, const int *v2, const int n) +{ + int i; + for (i= 0; i < n && v1[i] == v2[i]; i++) + ; + return i == n; +} + + +/* + * Generate random integer from 0 to n-1 + * Like throwing an n-sided dice marked 0, 1, 2, ..., n-1 + */ +int roll( int n ) +{ + int r; + + do + /* + * Compute a pseudo-random value between 0.0 and 1.0, multiply + * it by n-1, and then find the nearest integer. + * + * We don't use RAND_MAX here because not all compilation + * environments define it (e.g. gcc(1) under SunOS 4.1.4). + */ + r = ((rand() % 32768) / 32767.0) * (n - 1) + 0.5; + while (r >= n); + + return r; +} + + +/* + * Convert number to mixed base + * + * E.g. to convert 41 inches to yards, feet and inches: + * MPI_Offset base[] = {1, 3, 12}; + * MPI_Offset result[3]; + * status = toMixedBase(41, 3, base, result); + * + * Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado + */ +int +toMixedBase( + size_t number, /* number to be converted to mixed base */ + size_t length, + const MPI_Offset base[], /* dimensioned [length], base[0] ignored */ + MPI_Offset result[]) /* dimensioned [length] */ +{ + size_t i; + + if (length > 0) { + for (i = length - 1; i > 0; i--) { + if (base[i] == 0) + return 1; + result[i] = number % base[i]; + number = number / base[i]; + } + result[0] = number; + } + return 0; +} + +/* + * Convert number from mixed base + * + * E.g. to convert 1 yard, 0 feet, 5 inches to inches: + * MPI_Offset number[] = {1, 0, 5}; + * MPI_Offset base[] = {1, 3, 12}; + * inches = fromMixedBase(3, number, base); + * + * Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado + */ +size_t +fromMixedBase( + size_t length, + MPI_Offset number[], /* dimensioned [length] */ + MPI_Offset base[]) /* dimensioned [length], base[0] ignored */ +{ + size_t i; + size_t result = 0; + + for (i = 1; i < length; i++) { + result += number[i-1]; + result *= base[i]; + } + if (length > 0) + result += number[i-1]; + return result; +} + + +/* Convert any ncmpi_type to double */ +int nc2dbl ( const ncmpi_type datatype, const void *p, double *result) +{ + if ( ! p ) return 2; + if ( ! result ) return 3; + switch (datatype) { + case NC_BYTE: *result = *((signed char *) p); break; + case NC_CHAR: *result = *((char *) p); break; + case NC_SHORT: *result = *((short *) p); break; + case NC_INT: +#if INT_MAX >= X_INT_MAX + *result = *((int *) p); +#else + *result = *((long *) p); +#endif + break; + case NC_FLOAT: *result = *((float *) p); break; + case NC_DOUBLE: *result = *((double *) p); break; + default: return 1; + } + return 0; +} + + +/* Convert double to any ncmpi_type */ +int dbl2nc ( const double d, const ncmpi_type datatype, void *p) +{ + double r; /* rounded value */ + + if (p) { + switch (datatype) { + case NC_BYTE: + r = floor(0.5+d); + if ( r < schar_min || r > schar_max ) return 2; + *((signed char *) p) = r; + break; + case NC_CHAR: + r = floor(0.5+d); + if ( r < text_min || r > text_max ) return 2; + *((char *) p) = r; + break; + case NC_SHORT: + r = floor(0.5+d); + if ( r < short_min || r > short_max ) return 2; + *((short *) p) = r; + break; + case NC_INT: + r = floor(0.5+d); + if ( r < long_min || r > long_max ) return 2; +#if INT_MAX >= X_INT_MAX + *((int *) p) = r; +#else + *((long *) p) = r; +#endif + break; + case NC_FLOAT: + if ( fabs(d) > float_max ) return 2; + *((float *) p) = d; + break; + case NC_DOUBLE: + *((double *) p) = d; + break; + default: + return 1; + } + return 0; + } else { + return 1; + } +} + +#define FUZZ (1.19209290E-07) + +/* Generate data values as function of type, rank (-1 for attribute), index */ +double +hash( const ncmpi_type type, const int rank, const MPI_Offset *index ) +{ + double base; + double result = 0.0; + int d; /* index of dimension */ + + /* If vector then elements 0 & 1 are min & max. Elements 2 & 3 are */ + /* just < min & > max (except for NC_CHAR & NC_DOUBLE) */ + if (abs(rank) == 1 && index[0] <= 3) { + switch (index[0]) { + case 0: + switch (type) { + case NC_CHAR: return X_CHAR_MIN; + case NC_BYTE: return X_BYTE_MIN; + case NC_SHORT: return X_SHORT_MIN; + case NC_INT: return X_INT_MIN; + case NC_FLOAT: return X_FLOAT_MIN; + case NC_DOUBLE: return X_DOUBLE_MIN; + default: assert(0); + } + case 1: + switch (type) { + case NC_CHAR: return X_CHAR_MAX; + case NC_BYTE: return X_BYTE_MAX; + case NC_SHORT: return X_SHORT_MAX; + case NC_INT: return X_INT_MAX; + case NC_FLOAT: return X_FLOAT_MAX; + case NC_DOUBLE: return X_DOUBLE_MAX; + default: assert(0); + } + case 2: + switch (type) { + case NC_CHAR: return 'A'; + case NC_BYTE: return X_BYTE_MIN-1.0; + case NC_SHORT: return X_SHORT_MIN-1.0; + case NC_INT: return X_INT_MIN-1.0; + case NC_FLOAT: return X_FLOAT_MIN * (1.0 + FUZZ); + case NC_DOUBLE: return -1.0; + default: assert(0); + } + case 3: + switch (type) { + case NC_CHAR: return 'Z'; + case NC_BYTE: return X_BYTE_MAX+1.0; + case NC_SHORT: return X_SHORT_MAX+1.0; + case NC_INT: return X_INT_MAX+1.0; + case NC_FLOAT: return X_FLOAT_MAX * (1.0 + FUZZ); + case NC_DOUBLE: return 1.0; + default: assert(0); + } + } + } else { + switch (type) { + case NC_CHAR: base = 2; break; + case NC_BYTE: base = -2; break; + case NC_SHORT: base = -5; break; + case NC_INT: base = -20; break; + case NC_FLOAT: base = -9; break; + case NC_DOUBLE: base = -10; break; + default: + base = 0; + assert(0); + } + result = rank < 0 ? base * 7 : base * (rank + 1); + for (d = 0; d < abs(rank); d++) + result = base * (result + index[d]); + } + return result; +} + +/* wrapper for hash to handle special NC_BYTE/uchar adjustment */ +double +hash4( + const ncmpi_type type, + const int rank, + const MPI_Offset *index, + const nct_itype itype) +{ + double result; + + result = hash( type, rank, index ); + if (itype == NCT_UCHAR && type == NC_BYTE && result >= -128 && result < 0) + result += 256; + return result; +} + +static ncmpi_type +char2type(char letter) { + switch (letter) { + case 'c': return NC_CHAR; + case 'b': return NC_BYTE; + case 's': return NC_SHORT; + case 'i': return NC_INT; + case 'f': return NC_FLOAT; + case 'd': return NC_DOUBLE; + default: assert(0); + } + return NC_CHAR; /* Just to keep compiler happy */ +} + + +static void +init_dims(const char *digit) +{ + int dimid; /* index of dimension */ + for (dimid = 0; dimid < NDIMS; dimid++) + { + dim_len[dimid] = dimid == 0 ? NRECS : dimid; + dim_name[dimid][0] = 'D'; + dim_name[dimid][1] = digit[dimid]; + dim_name[dimid][2] = '\0'; + } +} + +static void +init_gatts(const char *type_letter) +{ + int attid; + for (attid = 0; attid < NGATTS; attid++) + { + gatt_name[attid][0] = 'G'; + gatt_name[attid][1] = type_letter[attid]; + gatt_name[attid][2] = '\0'; + gatt_len[attid] = 1 + attid; + gatt_type[attid] = char2type (type_letter[attid]); + } +} + +static MPI_Offset +product(size_t nn, const MPI_Offset *sp) +{ + MPI_Offset result = 1; + while(nn-- > 0) + result *= *sp++; + return result; +} + +/* + define global variables: + dim_name, dim_len, + var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels + att_name, gatt_name, att_type, gatt_type, att_len, gatt_len + */ +void +init_gvars (void) +{ + const MPI_Offset max_dim_len[MAX_RANK] = { + MAX_DIM_LEN +1, + MAX_DIM_LEN, + MAX_DIM_LEN + }; + const char type_letter[] = "cbsifd"; + const char digit[] = "r123456789"; + + size_t rank; + int vn; /* var number */ + int xtype; /* index of type */ + int an; /* attribute number */ + + assert(sizeof(max_dim_len)/sizeof(max_dim_len[0]) >= MAX_RANK); + + init_dims(digit); + + for (rank = 0, vn = 0, xtype = 0, an = 0; rank <= MAX_RANK; rank++) + { + /* number variables of a type and rank */ + const size_t nvars = product(rank, max_dim_len); + int jj; + + for (jj = 0; jj < nvars; jj++) + { + /* number types of this shape */ + const int ntypes = rank < 2 ? NTYPES : 1; + + int tc; + for (tc = 0; tc < ntypes; + tc++, vn++, xtype = (xtype + 1) % NTYPES) + { + MPI_Offset tmp[MAX_RANK]; + + var_name[vn][0] = type_letter[xtype]; + var_type[vn] = char2type (type_letter[xtype]); + var_rank[vn] = rank; + var_natts[vn] = rank == 0 ? vn % (MAX_NATTS + 1) : 0; + { + int ac; + for (ac = 0; ac < var_natts[vn]; ac++, an++) + { + att_name[vn][ac][0] = type_letter[an % NTYPES]; + att_name[vn][ac][1] = '\0'; + att_len[vn][ac] = an; + att_type[vn][ac] = char2type (type_letter[an % NTYPES]); + } + } /* ac block */ +#ifndef NDEBUG + assert(toMixedBase (jj, rank, max_dim_len, tmp) == 0); +#else + (void) toMixedBase (jj, rank, max_dim_len, tmp); +#endif + { + int dn; /* dimension number */ + for (dn = 0; dn < rank; dn++) + var_dimid[vn][dn] = (int)tmp[dn]; + for (dn = 0, var_nels[vn] = 1; dn < rank; dn++) + { + var_dimid[vn][dn] += dn > 0; + assert (var_dimid[vn][dn] <= 9); + var_name[vn][dn + 1] = digit[var_dimid[vn][dn]]; + var_shape[vn][dn] = var_dimid[vn][dn] ? + var_dimid[vn][dn] : NRECS; + var_nels[vn] *= var_shape[vn][dn]; + } + } /* dn block */ + } + } + } + + init_gatts(type_letter); +} + + +/* define dims defined by global variables */ +void +def_dims(int ncid) +{ + int err; /* status */ + int i; + int dimid; /* dimension id */ + + for (i = 0; i < NDIMS; i++) { + err = ncmpi_def_dim(ncid, dim_name[i], i==0 ? NC_UNLIMITED : dim_len[i], + &dimid); + IF (err) error("ncmpi_def_dim: %s", ncmpi_strerror(err)); + } +} + + +/* define vars defined by global variables */ +void +def_vars(int ncid) +{ + int err; /* status */ + int i; + int var_id; + + for (i = 0; i < NVARS; i++) { + err = ncmpi_def_var(ncid, var_name[i], var_type[i], var_rank[i], + var_dimid[i], &var_id); + IF (err) error("ncmpi_def_var: %s", ncmpi_strerror(err)); + } +} + + +/* put attributes defined by global variables */ +void +put_atts(int ncid) +{ + int err; /* status */ + int i; + MPI_Offset k; + int j; /* index of attribute */ + int allInRange; + double att[MAX_NELS]; + char catt[MAX_NELS]; + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + if (ATT_TYPE(i,j) == NC_CHAR) { + for (k = 0; k < ATT_LEN(i,j); k++) { + catt[k] = hash(ATT_TYPE(i,j), -1, &k); + } + err = ncmpi_put_att_text(ncid, i, ATT_NAME(i,j), + ATT_LEN(i,j), catt); + IF (err) + error("ncmpi_put_att_text: %s", ncmpi_strerror(err)); + } else { + for (allInRange = 1, k = 0; k < ATT_LEN(i,j); k++) { + att[k] = hash(ATT_TYPE(i,j), -1, &k); + allInRange = allInRange && inRange(att[k], ATT_TYPE(i,j)); + } + err = ncmpi_put_att_double(ncid, i, ATT_NAME(i,j), + ATT_TYPE(i,j), ATT_LEN(i,j), att); + if (allInRange) { + IF (err) + error("ncmpi_put_att_double: %s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("type-conversion range error: status = %d", err); + } + } + } + } +} + +/* put variables defined by global variables */ +void +put_vars(int ncid) +{ + MPI_Offset start[MAX_RANK]; + MPI_Offset index[MAX_RANK]; + int err; /* status */ + int i; + size_t j; + double value[MAX_NELS]; + char text[MAX_NELS]; + int allInRange; + + for (j = 0; j < MAX_RANK; j++) + start[j] = 0; + for (i = 0; i < NVARS; i++) { + for (allInRange = 1, j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) error("toMixedBase"); + if (var_name[i][0] == 'c') { + text[j] = hash(var_type[i], var_rank[i], index); + } else { + value[j] = hash(var_type[i], var_rank[i], index); + allInRange = allInRange && inRange(value[j], var_type[i]); + } + } + if (var_name[i][0] == 'c') { + err = ncmpi_put_vara_text_all(ncid, i, start, var_shape[i], text); + IF (err) + error("ncmpi_put_vara_text_all: %s", ncmpi_strerror(err)); + } else { + err = ncmpi_put_vara_double_all(ncid, i, start, var_shape[i], value); + if (allInRange) { + IF (err) + error("ncmpi_put_vara_double_all: %s", ncmpi_strerror(err)); + } else { + IF (err != NC_ERANGE) + error("type-conversion range error: status = %d", err); + } + } + } +} + + +/* Create & write all of specified file using global variables */ +void +write_file(char *filename) +{ + int ncid; /* netCDF id */ + int err; /* status */ + + err = ncmpi_create(comm, filename, NC_CLOBBER|extra_flags, MPI_INFO_NULL, &ncid); + IF (err) + error("ncmpi_create: %s", ncmpi_strerror(err)); + + def_dims(ncid); + def_vars(ncid); + put_atts(ncid); + err = ncmpi_enddef(ncid); + IF (err) + error("ncmpi_enddef: %s", ncmpi_strerror(err)); + put_vars(ncid); + + err = ncmpi_close (ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); +} + + +/* + * check dimensions of specified file have expected name & length + */ +void +check_dims(int ncid) +{ + char name[NC_MAX_NAME]; + MPI_Offset length; + int i; + int err; /* status */ + + for (i = 0; i < NDIMS; i++) { + err = ncmpi_inq_dim(ncid, i, name, &length); + IF (err) + error("ncmpi_inq_dim: %s", ncmpi_strerror(err)); + IF (strcmp(name, dim_name[i]) != 0) + error("Unexpected name of dimension %d", i); + IF (length != dim_len[i]) + error("Unexpected length %d of dimension %d", length, i); + } +} + + +/* + * check variables of specified file have expected name, type, shape & values + */ +void +check_vars(int ncid) +{ + MPI_Offset index[MAX_RANK]; + int err; /* status */ + int i; + size_t j; + char text; + double value; + ncmpi_type datatype; + int ndims; + int dimids[MAX_RANK]; + int isChar; + double expect; + char name[NC_MAX_NAME]; + MPI_Offset length; + int nok = 0; /* count of valid comparisons */ + + for (i = 0; i < NVARS; i++) { + isChar = var_type[i] == NC_CHAR; + err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL); + IF (err) + error("ncmpi_inq_var: %s", ncmpi_strerror(err)); + IF (strcmp(name, var_name[i]) != 0) + error("Unexpected var_name"); + IF (datatype != var_type[i]) + error("Unexpected type"); + IF (ndims != var_rank[i]) + error("Unexpected rank"); + for (j = 0; j < ndims; j++) { + err = ncmpi_inq_dim(ncid, dimids[j], 0, &length); + IF (err) + error("ncmpi_inq_dim: %s", ncmpi_strerror(err)); + IF (length != var_shape[i][j]) + error("Unexpected shape"); + } + for (j = 0; j < var_nels[i]; j++) { + err = toMixedBase(j, var_rank[i], var_shape[i], index); + IF (err) + error("error in toMixedBase 2"); + expect = hash( var_type[i], var_rank[i], index ); + if (isChar) { + ncmpi_begin_indep_data(ncid); + err = ncmpi_get_var1_text(ncid, i, index, &text); + IF (err) + error("ncmpi_get_var1_text: %s", ncmpi_strerror(err)); + IF (text != expect) { + error("Var %s value read 0x%02x not that expected 0x%02x ", + var_name[i], text, (char)expect); + print_n_size_t(var_rank[i], index); + } else { +#if 0 + print("\nOk %s ", var_name[i]); + print_n_size_t(var_rank[i], index); +#endif + nok++; + } + ncmpi_end_indep_data(ncid); + } else { + ncmpi_begin_indep_data(ncid); + err = ncmpi_get_var1_double(ncid, i, index, &value); + if (inRange(expect,var_type[i])) { + IF (err) { + error("ncmpi_get_var1_double: %s", ncmpi_strerror(err)); + } else { + IF (!equal(value,expect,var_type[i], NCT_DOUBLE)) { + error("Var %s value read % 12.5e not that expected % 12.7e ", + var_name[i], value, expect); + print_n_size_t(var_rank[i], index); + } else { +#if 0 + print("\nOk %s ", var_name[i]); + print_n_size_t(var_rank[i], index); +#endif + nok++; + } + } + } + ncmpi_end_indep_data(ncid); + } + } + } + print_nok(nok); +} + + +/* + * check attributes of specified file have expected name, type, length & values + */ +void +check_atts(int ncid) +{ + int err; /* status */ + int i; + int j; + MPI_Offset k; + ncmpi_type datatype; + char name[NC_MAX_NAME]; + MPI_Offset length; + char text[MAX_NELS]; + double value[MAX_NELS]; + double expect; + int nok = 0; /* count of valid comparisons */ + + for (i = -1; i < NVARS; i++) { + for (j = 0; j < NATTS(i); j++) { + err = ncmpi_inq_attname(ncid, i, j, name); + IF (err) + error("ncmpi_inq_attname: %s", ncmpi_strerror(err)); + IF (strcmp(name, ATT_NAME(i,j)) != 0) + error("ncmpi_inq_attname: unexpected name"); + err = ncmpi_inq_att(ncid, i, name, &datatype, &length); + IF (err) + error("ncmpi_inq_att: %s", ncmpi_strerror(err)); + IF (datatype != ATT_TYPE(i,j)) + error("ncmpi_inq_att: unexpected type"); + IF (length != ATT_LEN(i,j)) + error("ncmpi_inq_att: unexpected length"); + if (datatype == NC_CHAR) { + err = ncmpi_get_att_text(ncid, i, name, text); + IF (err) + error("ncmpi_get_att_text: %s", ncmpi_strerror(err)); + for (k = 0; k < ATT_LEN(i,j); k++) { + IF (text[k] != hash(datatype, -1, &k)) { + error("ncmpi_get_att_text: unexpected value"); + } else { + nok++; + } + } + } else { + err = ncmpi_get_att_double(ncid, i, name, value); + for (k = 0; k < ATT_LEN(i,j); k++) { + expect = hash(datatype, -1, &k); + if (inRange(expect,ATT_TYPE(i,j))) { + IF (err) + error("ncmpi_get_att_double: %s", ncmpi_strerror(err)); + IF (!equal(value[k], expect, ATT_TYPE(i,j), NCT_DOUBLE)) { + error("Att value read not that expected"); + } else { + nok++; + } + } + } + } + } + } + print_nok(nok); +} + + +/* Check file (dims, vars, atts) corresponds to global variables */ +void +check_file(char *filename) +{ + int ncid; /* netCDF id */ + int err; /* status */ + + err = ncmpi_open(comm, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); + IF (err) { + error("ncmpi_open: %s", ncmpi_strerror(err)); + } else { + check_dims(ncid); + check_vars(ncid); + check_atts(ncid); + err = ncmpi_close (ncid); + IF (err) + error("ncmpi_close: %s", ncmpi_strerror(err)); + } +} + +/* TODO: Maybe this function belongs in the netcdf library. */ +const char * +s_ncmpi_type(ncmpi_type type) +{ + switch((int)type){ + case NC_BYTE: + return "NC_BYTE"; + case NC_CHAR: + return "NC_CHAR"; + case NC_SHORT: + return "NC_SHORT"; + case NC_INT: + return "NC_INT"; + case NC_FLOAT: + return "NC_FLOAT"; + case NC_DOUBLE: + return "NC_DOUBLE"; + } + return ""; +} Index: /tags/v1-0-3/test/Makefile.in =================================================================== --- /tags/v1-0-3/test/Makefile.in (revision 422) +++ /tags/v1-0-3/test/Makefile.in (revision 422) @@ -0,0 +1,15 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ +SUBDIRS = common test_double test_double_int test_float test_int test_dtype nc_test fandc nf_test + +all: + set -e; for i in $(SUBDIRS); do ( cd $$i && $(MAKE) ; ) ; done + +clean: + set -e; for i in $(SUBDIRS); do ( cd $$i && $(MAKE) clean ; ) ; done + +# Eventually, this target will run all of the relevant tests +testing: + cd nc_test && make testing + if [ @has_fortran@ = yes ] ; then cd nf_test && make testing ; fi + Index: /tags/v1-0-3/test/nf_test/depend =================================================================== --- /tags/v1-0-3/test/nf_test/depend (revision 332) +++ /tags/v1-0-3/test/nf_test/depend (revision 332) @@ -0,0 +1,25 @@ +fortlib.o: fortlib.c +lib.o: ../../src/libf/pnetcdf.inc +lib.o: lib.F +lib.o: tests.inc +nf_error.o: ../../src/libf/pnetcdf.inc +nf_error.o: nf_error.F +nf_error.o: tests.inc +nf_test.o: ../../src/libf/pnetcdf.inc +nf_test.o: nf_test.F +nf_test.o: tests.inc +test_get.o: ../../src/libf/pnetcdf.inc +test_get.o: test_get.F +test_get.o: tests.inc +test_put.o: ../../src/libf/pnetcdf.inc +test_put.o: test_put.F +test_put.o: tests.inc +test_read.o: ../../src/libf/pnetcdf.inc +test_read.o: test_read.F +test_read.o: tests.inc +test_write.o: ../../src/libf/pnetcdf.inc +test_write.o: test_write.F +test_write.o: tests.inc +util.o: ../../src/libf/pnetcdf.inc +util.o: tests.inc +util.o: util.F Index: /tags/v1-0-3/test/nf_test/nf_error.F =================================================================== --- /tags/v1-0-3/test/nf_test/nf_error.F (revision 193) +++ /tags/v1-0-3/test/nf_test/nf_error.F (revision 193) @@ -0,0 +1,75 @@ +#if 0 + Copyright 1996, UCAR/Unidata + See netcdf/COPYRIGHT file for copying and redistribution conditions. + $Id$ +#endif + + +C +C Use for logging error messages +C + subroutine error(msg) + implicit none + character*(*) msg +#include "tests.inc" + + nfails = nfails + 1 + if (nfails .le. max_nmpt) print *, msg + end + + +C +C Use for logging error conditions +C + subroutine errori(msg, i) + implicit none + character*(*) msg + integer i +#include "tests.inc" + + nfails = nfails + 1 + if (nfails .le. max_nmpt) print *, msg, i + end + + +C +C Use for logging error conditions +C + subroutine errord(msg, d) + implicit none + character*(*) msg + doubleprecision d +#include "tests.inc" + + nfails = nfails + 1 + if (nfails .le. max_nmpt) print *, msg, d + end + + +C +C Use for logging error conditions +C + subroutine errorc(msg, string) + implicit none + character*(*) msg + character*(*) string +#include "tests.inc" + + nfails = nfails + 1 + if (nfails .le. max_nmpt) print *, msg, + + string(1:len_trim(string)) + end + + +C +C Use for logging error conditions +C + subroutine errore(msg, err) + implicit none + character*(*) msg + integer err +#include "tests.inc" + + nfails = nfails + 1 + call errorc(msg, nfmpi_strerror(err)) + end Index: /tags/v1-0-3/test/nf_test/util.F =================================================================== --- /tags/v1-0-3/test/nf_test/util.F (revision 498) +++ /tags/v1-0-3/test/nf_test/util.F (revision 498) @@ -0,0 +1,1348 @@ +!********************************************************************* +! Copyright 1996, UCAR/Unidata +! See netcdf/COPYRIGHT file for copying and redistribution conditions. +! $Id$ +!********************************************************************/ + + SUBROUTINE PRINT_NOK(NOK) + IMPLICIT NONE + INTEGER NOK +#include "tests.inc" + + IF (VERBOSE .OR. NFAILS .GT. 0) PRINT *, ' ' + IF (VERBOSE) PRINT *, NOK, ' good comparisons.' + END + + +! Is value within external type range? */ + FUNCTION INRANGE(VALUE, DATATYPE) + IMPLICIT NONE + DOUBLEPRECISION VALUE + INTEGER DATATYPE +#include "tests.inc" + + DOUBLEPRECISION MIN + DOUBLEPRECISION MAX + + IF (DATATYPE .EQ. NF_CHAR) THEN + MIN = X_CHAR_MIN + MAX = X_CHAR_MAX + ELSE IF (DATATYPE .EQ. NF_BYTE) THEN + MIN = X_BYTE_MIN + MAX = X_BYTE_MAX + ELSE IF (DATATYPE .EQ. NF_SHORT) THEN + MIN = X_SHORT_MIN + MAX = X_SHORT_MAX + ELSE IF (DATATYPE .EQ. NF_INT) THEN + MIN = X_INT_MIN + MAX = X_INT_MAX + ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN + MIN = X_FLOAT_MIN + MAX = X_FLOAT_MAX + ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN + MIN = X_DOUBLE_MIN + MAX = X_DOUBLE_MAX + ELSE + CALL UD_ABORT + END IF + + INRANGE = (VALUE .GE. MIN) .AND. (VALUE .LE. MAX) + END + + + FUNCTION INRANGE_UCHAR(VALUE, DATATYPE) + IMPLICIT NONE + DOUBLEPRECISION VALUE + INTEGER DATATYPE +#include "tests.inc" + + IF (DATATYPE .EQ. NF_BYTE) THEN + INRANGE_UCHAR = (VALUE .GE. 0) .AND. (VALUE .LE. 255) + ELSE + INRANGE_UCHAR = INRANGE(VALUE, DATATYPE) + END IF + END + + + FUNCTION INRANGE_FLOAT(VALUE, DATATYPE) + IMPLICIT NONE + DOUBLEPRECISION VALUE + INTEGER DATATYPE +#include "tests.inc" + + DOUBLEPRECISION MIN + DOUBLEPRECISION MAX + REAL FVALUE + + IF (DATATYPE .EQ. NF_CHAR) THEN + MIN = X_CHAR_MIN + MAX = X_CHAR_MAX + ELSE IF (DATATYPE .EQ. NF_BYTE) THEN + MIN = X_BYTE_MIN + MAX = X_BYTE_MAX + ELSE IF (DATATYPE .EQ. NF_SHORT) THEN + MIN = X_SHORT_MIN + MAX = X_SHORT_MAX + ELSE IF (DATATYPE .EQ. NF_INT) THEN + MIN = X_INT_MIN + MAX = X_INT_MAX + ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN + IF (internal_max(NFT_REAL) .LT. X_FLOAT_MAX) THEN + MIN = -internal_max(NFT_REAL) + MAX = internal_max(NFT_REAL) + ELSE + MIN = X_FLOAT_MIN + MAX = X_FLOAT_MAX + END IF + ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN + IF (internal_max(NFT_REAL) .LT. X_DOUBLE_MAX) THEN + MIN = -internal_max(NFT_REAL) + MAX = internal_max(NFT_REAL) + ELSE + MIN = X_DOUBLE_MIN + MAX = X_DOUBLE_MAX + END IF + ELSE + CALL UD_ABORT + END IF + + IF (.NOT.((VALUE .GE. MIN) .AND. (VALUE .LE. MAX))) THEN + INRANGE_FLOAT = .FALSE. + ELSE + FVALUE = VALUE + INRANGE_FLOAT = (FVALUE .GE. MIN) .AND. (FVALUE .LE. MAX) + END IF + END + + +! wrapper for inrange to handle special NF_BYTE/uchar adjustment */ + function inrange3(value, datatype, itype) + implicit none + doubleprecision value + integer datatype + integer itype +#include "tests.inc" + + if (itype .eq. NFT_REAL) then + inrange3 = inrange_float(value, datatype) + else + inrange3 = inrange(value, datatype) + end if + end + + +! +! Does x == y, where one is internal and other external (netCDF)? +! Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON. +! + function equal(x, y, extType, itype) + implicit none + doubleprecision x + doubleprecision y + integer extType !!/* external data type */ + integer itype +#include "tests.inc" + + doubleprecision epsilon + + if ((extType .eq. NF_REAL) .or. (itype .eq. NFT_REAL)) then + epsilon = 1.19209290E-07 + else + epsilon = 2.2204460492503131E-16 + end if + equal = abs(x-y) .le. epsilon * max( abs(x), abs(y)) + end + + +! Test whether two int vectors are equal. If so return 1, else 0 */ + function int_vec_eq(v1, v2, n) + implicit none + integer n + integer v1(n) + integer v2(n) +#include "tests.inc" + + integer i + + int_vec_eq = .true. + + if (n .le. 0) + + return + + do 1, i=1, n + if (v1(i) .ne. v2(i)) then + int_vec_eq = .false. + return + end if +1 continue + end + + +! +! Generate random integer from 0 through n-1 +! Like throwing an n-sided dice marked 0, 1, 2, ..., n-1 +! + function roll(n) + implicit none +#include "tests.inc" + NFMPI_OFFSET n + + doubleprecision ud_rand + external ud_rand + +1 roll = (ud_rand(0) * (n-1)) + 0.5 + if (roll .ge. n) goto 1 + end + + +! +! Convert an origin-1 cumulative index to a netCDF index vector. +! Grosset dimension first; finest dimension last. +! +! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado +! Steve Emmerson, (same place) +! + function index2ncindexes(index, rank, base, indexes) + implicit none + integer index !!/* index to be converted */ + integer rank !/* number of dimensions */ +#include "tests.inc" + NFMPI_OFFSET base(rank) !/* base(rank) ignored */ + NFMPI_OFFSET indexes(rank) !/* returned FORTRAN indexes */ + + integer i + integer offset + integer intbase + + if (rank .gt. 0) then + offset = index - 1 + do 1, i = rank, 1, -1 + if (base(i) .eq. 0) then + index2ncindexes = 1 + return + end if + intbase = base(i) + indexes(i) = 1 + mod(offset, intbase) + offset = offset / base(i) +1 continue + end if + index2ncindexes = 0 + end + + +! +! Convert an origin-1 cumulative index to a FORTRAN index vector. +! Finest dimension first; grossest dimension last. +! +! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado +! Steve Emmerson, (same place) +! + function index2indexes(index, rank, base, indexes) + implicit none + integer index !/* index to be converted */ + integer rank !/* number of dimensions */ +#include "tests.inc" + NFMPI_OFFSET base(rank) !/* base(rank) ignored */ + NFMPI_OFFSET indexes(rank) !/* returned FORTRAN indexes */ + + integer i + integer offset + integer intbase + + if (rank .gt. 0) then + offset = index - 1 + do 1, i = 1, rank + if (base(i) .eq. 0) then + index2indexes = 1 + return + end if + intbase = base(i) + indexes(i) = 1 + mod(offset, intbase) + offset = offset / base(i) +1 continue + end if + index2indexes = 0 + end + + +! +! Convert a FORTRAN index vector to an origin-1 cumulative index. +! Finest dimension first; grossest dimension last. +! +! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado +! Steve Emmerson, (same place) +! + function indexes2index(rank, indexes, base) + implicit none + integer rank !/* number of dimensions */ + integer indexes(rank) !/* FORTRAN indexes */ + integer base(rank) !/* base(rank) ignored */ +#include "tests.inc" + + integer i + + indexes2index = 0 + if (rank .gt. 0) then + do 1, i = rank, 1, -1 + indexes2index = (indexes2index-1) * base(i) + indexes(i) +1 continue + end if + end + + +! Generate data values as function of type, rank (-1 for attribute), index */ + function hash(type, rank, index) + implicit none + integer type + integer rank +#include "tests.inc" + NFMPI_OFFSET index(*) + + doubleprecision base + doubleprecision result + integer d !/* index of dimension */ + + !/* If vector then elements 1 & 2 are min & max. Elements 3 & 4 are */ + !/* just < min & > max (except for NF_CHAR & NF_DOUBLE) */ + if (abs(rank) .eq. 1 .and. index(1) .le. 4) then + if (index(1) .eq. 1) then + if (type .eq. NF_CHAR) then + hash = X_CHAR_MIN + else if (type .eq. NF_BYTE) then + hash = X_BYTE_MIN + else if (type .eq. NF_SHORT) then + hash = X_SHORT_MIN + else if (type .eq. NF_INT) then + hash = X_INT_MIN + else if (type .eq. NF_FLOAT) then + hash = X_FLOAT_MIN + else if (type .eq. NF_DOUBLE) then + hash = X_DOUBLE_MIN + else + call ud_abort + end if + else if (index(1) .eq. 2) then + if (type .eq. NF_CHAR) then + hash = X_CHAR_MAX + else if (type .eq. NF_BYTE) then + hash = X_BYTE_MAX + else if (type .eq. NF_SHORT) then + hash = X_SHORT_MAX + else if (type .eq. NF_INT) then + hash = X_INT_MAX + else if (type .eq. NF_FLOAT) then + hash = X_FLOAT_MAX + else if (type .eq. NF_DOUBLE) then + hash = X_DOUBLE_MAX + else + call ud_abort + end if + else if (index(1) .eq. 3) then + if (type .eq. NF_CHAR) then + hash = ichar('A') + else if (type .eq. NF_BYTE) then + hash = X_BYTE_MIN-1.0 + else if (type .eq. NF_SHORT) then + hash = X_SHORT_MIN-1.0 + else if (type .eq. NF_INT) then + hash = X_INT_MIN + else if (type .eq. NF_FLOAT) then + hash = X_FLOAT_MIN + else if (type .eq. NF_DOUBLE) then + hash = -1.0 + else + call ud_abort + end if + else if (index(1) .eq. 4) then + if (type .eq. NF_CHAR) then + hash = ichar('Z') + else if (type .eq. NF_BYTE) then + hash = X_BYTE_MAX+1.0 + else if (type .eq. NF_SHORT) then + hash = X_SHORT_MAX+1.0 + else if (type .eq. NF_INT) then + hash = X_INT_MAX+1.0 + else if (type .eq. NF_FLOAT) then + hash = X_FLOAT_MAX + else if (type .eq. NF_DOUBLE) then + hash = 1.0 + else + call ud_abort + end if + end if + else + if (type .eq. NF_CHAR) then + base = 2 + else if (type .eq. NF_BYTE) then + base = -2 + else if (type .eq. NF_SHORT) then + base = -5 + else if (type .eq. NF_INT) then + base = -20 + else if (type .eq. NF_FLOAT) then + base = -9 + else if (type .eq. NF_DOUBLE) then + base = -10 + else + stop 'in hash()' + end if + + if (rank .lt. 0) then + result = base * 7 + else + result = base * (rank + 1) + end if + +! /* +! * NB: Finest netCDF dimension assumed first. +! */ + do 1, d = abs(rank), 1, -1 + result = base * (result + index(d) - 1) +1 continue + hash = result + end if + end + + +! wrapper for hash to handle special NC_BYTE/uchar adjustment */ + function hash4(type, rank, index, itype) + implicit none + integer type + integer rank +#include "tests.inc" + NFMPI_OFFSET index(*) + integer itype + + hash4 = hash( type, rank, index ) + if ((itype .eq. NFT_CHAR) .and. (type .eq. NF_BYTE) .and. + + (hash4 .ge. -128) .and. (hash4 .lt. 0)) hash4 = hash4 + 256 + end + + + integer function char2type(letter) + implicit none + character*1 letter +#include "tests.inc" + + if (letter .eq. 'c') then + char2type = NF_CHAR + else if (letter .eq. 'b') then + char2type = NF_BYTE + else if (letter .eq. 's') then + char2type = NF_SHORT + else if (letter .eq. 'i') then + char2type = NF_INT + else if (letter .eq. 'f') then + char2type = NF_FLOAT + else if (letter .eq. 'd') then + char2type = NF_DOUBLE + else + stop 'char2type(): invalid type-letter' + end if + end + + + subroutine init_dims(digit) + implicit none + character*1 digit(NDIMS) +#include "tests.inc" + + integer dimid !/* index of dimension */ + do 1, dimid = 1, NDIMS + if (dimid .eq. RECDIM) then + dim_len(dimid) = NRECS + else + dim_len(dimid) = dimid - 1 + endif + dim_name(dimid) = 'D' // digit(dimid) +1 continue + end + + + subroutine init_gatts(type_letter) + implicit none + character*1 type_letter(NTYPES) +#include "tests.inc" + + integer attid + integer char2type + + do 1, attid = 1, NTYPES + gatt_name(attid) = 'G' // type_letter(attid) + gatt_len(attid) = attid + gatt_type(attid) = char2type(type_letter(attid)) +1 continue + end + + + integer function prod(nn, sp) + implicit none + integer nn +#include "tests.inc" + NFMPI_OFFSET sp(MAX_RANK) + + integer i + + prod = 1 + do 1, i = 1, nn + prod = prod * sp(i) +1 continue + end + + +! +! define global variables: +! dim_name, dim_len, +! var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels +! att_name, gatt_name, att_type, gatt_type, att_len, gatt_len +! + + subroutine init_gvars + implicit none +#include "tests.inc" + + NFMPI_OFFSET max_dim_len(MAX_RANK) + character*1 type_letter(NTYPES) + character*1 digit(10) + + integer rank + integer vn !/* var number */ + integer xtype !/* index of type */ + integer an !/* origin-0 cumulative attribute index */ + integer nvars + integer jj + integer ntypes + integer tc + NFMPI_OFFSET tmp(MAX_RANK) + integer ac !/* attribute index */ + integer dn !/* dimension number */ + integer prod !/* function */ + integer char2type !/* function */ + integer err + + data max_dim_len /0, MAX_DIM_LEN, MAX_DIM_LEN/ + data type_letter /'c', 'b', 's', 'i', 'f', 'd'/ + data digit /'r', '1', '2', '3', '4', '5', + + '6', '7', '8', '9'/ + + max_dim_len(1) = MAX_DIM_LEN + 1 + + call init_dims(digit) + + vn = 1 + xtype = 1 + an = 0 + +! /* Loop over variable ranks */ + do 1, rank = 0, MAX_RANK + nvars = prod(rank, max_dim_len) + + !/* Loop over variable shape vectors */ + do 2, jj = 1, nvars !/* 1, 5, 20, 80 */ + !/* number types of this shape */ + if (rank .lt. 2) then + ntypes = NTYPES !/* 6 */ + else + ntypes = 1 + end if + + !/* Loop over external data types */ + do 3, tc = 1, ntypes !/* 6, 1 */ + var_name(vn) = type_letter(xtype) + var_type(vn) = char2type(type_letter(xtype)) + var_rank(vn) = rank + if (rank .eq. 0) then + var_natts(vn) = mod(vn - 1, MAX_NATTS + 1) + else + var_natts(vn) = 0 + end if + + do 4, ac = 1, var_natts(vn) + attname(ac,vn) = + + type_letter(1+mod(an, NTYPES)) + attlen(ac,vn) = an + atttype(ac,vn) = + + char2type(type_letter(1+mod(an, NTYPES))) + an = an + 1 +4 continue + + !/* Construct initial shape vector */ + err = index2ncindexes(jj, rank, max_dim_len, tmp) + do 5, dn = 1, rank + var_dimid(dn,vn) = tmp(1+rank-dn) +5 continue + + var_nels(vn) = 1 + do 6, dn = 1, rank + if (dn .lt. rank) then + var_dimid(dn,vn) = var_dimid(dn,vn) + 1 + end if + if (var_dimid(dn,vn) .gt. 9) then + stop 'Invalid var_dimid vector' + end if + var_name(vn)(rank+2-dn:rank+2-dn) = + + digit(var_dimid(dn,vn)) + if (var_dimid(dn,vn) .ne. RECDIM) then + var_shape(dn,vn) = var_dimid(dn,vn) - 1 + else + var_shape(dn,vn) = NRECS + end if + var_nels(vn) = var_nels(vn) * var_shape(dn,vn) +6 continue + + vn = vn + 1 + xtype = 1 + mod(xtype, NTYPES) +3 continue +2 continue +1 continue + + call init_gatts(type_letter) + end + + +! define dims defined by global variables */ + subroutine def_dims(ncid) + implicit none + integer ncid +#include "tests.inc" + + integer err !/* status */ + integer i + integer dimid !/* dimension id */ + NFMPI_OFFSET length + + do 1, i = 1, NDIMS + if (i .eq. RECDIM) then + length = NFMPI_UNLIMITED + err = nfmpi_def_dim(ncid, dim_name(i), length, + + dimid) + else + err = nfmpi_def_dim(ncid, dim_name(i), dim_len(i), + + dimid) + end if + if (err .ne. 0) then + call errore('nfmpi_def_dim: ', err) + end if +1 continue + end + + +! define vars defined by global variables */ + subroutine def_vars(ncid) + implicit none + integer ncid +#include "tests.inc" + + integer err !/* status */ + integer i + integer var_id + + do 1, i = 1, NVARS + err = nfmpi_def_var(ncid, var_name(i), var_type(i), + + var_rank(i), var_dimid(1,i), var_id) + if (err .ne. 0) then + call errore('nfmpi_def_var: ', err) + end if +1 continue + end + + +! put attributes defined by global variables */ + subroutine put_atts(ncid) + implicit none + integer ncid +#include "tests.inc" + + integer err !/* netCDF status */ + integer i !/* variable index (0 => global + ! * attribute */ + integer k !/* attribute index */ + integer j !/* index of attribute */ + NFMPI_OFFSET ndx(1) + logical allInRange + doubleprecision att(MAX_NELS) + character*(MAX_NELS+2) catt + + do 1, i = 0, NVARS !/* var 0 => NF_GLOBAL attributes */ + do 2, j = 1, NATTS(i) + if (NF_CHAR .eq. ATT_TYPE(j,i)) then + catt = ' ' + do 3, k = 1, ATT_LEN(j,i) + ndx(1) = k + catt(k:k) = char(int(hash(ATT_TYPE(j,i), -1, + + ndx))) +3 continue +! /* +! * The following ensures that the text buffer doesn't +! * start with 4 zeros (which is a CFORTRAN NULL pointer +! * indicator) yet contains a zero (which causes the +! * CFORTRAN interface to pass the address of the +! * actual text buffer). +! */ + catt(ATT_LEN(j,i)+1:ATT_LEN(j,i)+1) = char(1) + catt(ATT_LEN(j,i)+2:ATT_LEN(j,i)+2) = char(0) + + err = nfmpi_put_att_text(ncid, varid(i), + + ATT_NAME(j,i), + + ATT_LEN(j,i), catt) + if (err .ne. 0) then + call errore('nfmpi_put_att_text: ', err) + end if + else + allInRange = .true. + do 4, k = 1, ATT_LEN(j,i) + ndx(1) = k + att(k) = hash(ATT_TYPE(j,i), -1, ndx) + allInRange = allInRange .and. + + inRange(att(k), ATT_TYPE(j,i)) +4 continue + err = nfmpi_put_att_double(ncid, varid(i), + + ATT_NAME(j,i), + + ATT_TYPE(j,i), + + ATT_LEN(j,i), att) + if (allInRange) then + if (err .ne. 0) then + call errore('nfmpi_put_att_double: ', err) + end if + else + if (err .ne. NF_ERANGE) then + call errore( + + 'type-conversion range error: status = ', + + err) + end if + end if + end if +2 continue +1 continue + end + + +! put variables defined by global variables */ + subroutine put_vars(ncid) + implicit none + integer ncid +#include "tests.inc" + + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + integer err !/* netCDF status */ + integer i + integer j + doubleprecision value(MAX_NELS) + character*(MAX_NELS+2) text + logical allInRange + + do 1, j = 1, MAX_RANK + start(j) = 1 +1 continue + + err = nfmpi_begin_indep_data(ncid) + do 2, i = 1, NVARS + allInRange = .true. + do 3, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) then + call errori( + + 'Error calling index2indexes() for var ', j) + end if + if (var_name(i)(1:1) .eq. 'c') then + text(j:j) = + + char(int(hash(var_type(i), var_rank(i), index))) + else + value(j) = hash(var_type(i), var_rank(i), index) + allInRange = allInRange .and. + + inRange(value(j), var_type(i)) + end if +3 continue + if (var_name(i)(1:1) .eq. 'c') then +! /* +! * The following statement ensures that the first 4 +! * characters in 'text' are not all zeros (which is +! * a cfortran.h NULL indicator) and that the string +! * contains a zero (which will cause the address of the +! * actual string buffer to be passed). +! */ + text(var_nels(i)+1:var_nels(i)+1) = char(1) + text(var_nels(i)+2:var_nels(i)+2) = char(0) + err = nfmpi_put_vara_text(ncid, i, start, + + var_shape(1,i), text) + if (err .ne. 0) then + call errore('nfmpi_put_vara_text: ', err) + end if + else + err = nfmpi_put_vara_double(ncid, i, start, + + var_shape(1,i), value) + if (allInRange) then + if (err .ne. 0) then + call errore('nfmpi_put_vara_double: ', err) + end if + else + if (err .ne. NF_ERANGE) then + call errore( + + 'type-conversion range error: status = ', + + err) + end if + end if + end if +2 continue + err = nfmpi_end_indep_data(ncid) + end + + +! Create & write all of specified file using global variables */ + subroutine write_file(filename) + implicit none + character*(*) filename +#include "tests.inc" + + integer ncid !/* netCDF id */ + integer err !/* netCDF status */ + + err = nfmpi_create(comm, filename, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + end if + + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) then + call errore('nfmpi_enddef: ', err) + end if + call put_vars(ncid) + + err = nfmpi_close(ncid) + if (err .ne. 0) then + call errore('nfmpi_close: ', err) + end if + end + + +! +! check dimensions of specified file have expected name & length +! + subroutine check_dims(ncid) + implicit none + integer ncid +#include "tests.inc" + + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + integer i + integer err !/* netCDF status */ + + do 1, i = 1, NDIMS + err = nfmpi_inq_dim(ncid, i, name, length) + if (err .ne. 0) then + call errore('nfmpi_inq_dim: ', err) + end if + if (name .ne. dim_name(i)) then + call errori('Unexpected name of dimension ', i) + end if + if (length .ne. dim_len(i)) then + call errori('Unexpected length of dimension ', i) + end if +1 continue + end + + +! +! check variables of specified file have expected name, type, shape & values +! + subroutine check_vars(ncid) + implicit none + integer ncid +#include "tests.inc" + + NFMPI_OFFSET index(MAX_RANK) + integer err !/* netCDF status */ + integer i + integer j + character*1 text + doubleprecision value + integer datatype + integer ndims + integer natt + integer dimids(MAX_RANK) + logical isChar + doubleprecision expect + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + integer nok !/* count of valid comparisons */ + + nok = 0 + err = nfmpi_begin_indep_data(ncid) + + do 1, i = 1, NVARS + isChar = var_type(i) .eq. NF_CHAR + err = nfmpi_inq_var(ncid, i, name, datatype, ndims, dimids, + + natt) + if (err .ne. 0) then + call errore('nfmpi_inq_var: ', err) + end if + if (name .ne. var_name(i)) then + call errori('Unexpected var_name for variable ', i) + end if + if (datatype .ne. var_type(i)) then + call errori('Unexpected type for variable ', i) + end if + if (ndims .ne. var_rank(i)) then + call errori('Unexpected rank for variable ', i) + end if + do 2, j = 1, ndims + err = nfmpi_inq_dim(ncid, dimids(j), name, length) + if (err .ne. 0) then + call errore('nfmpi_inq_dim: ', err) + end if + if (length .ne. var_shape(j,i)) then + call errori('Unexpected shape for variable ', i) + end if +2 continue + do 3, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) then + call errori('error in index2indexes() 2, variable ', + + i) + end if + expect = hash(var_type(i), var_rank(i), index ) + if (isChar) then + err = nfmpi_get_var1_text(ncid, i, index, text) + if (err .ne. 0) then + call errore('nfmpi_get_var1_text: ', err) + end if + if (ichar(text) .ne. expect) then + call errori( + + 'Var value read not that expected for variable ', i) + else + nok = nok + 1 + end if + else + err = nfmpi_get_var1_double(ncid, i, index, + + value) + if (inRange(expect,var_type(i))) then + if (err .ne. 0) then + call errore('nfmpi_get_var1_double: ', err) + else + if (.not. equal(value,expect,var_type(i), + + NFT_DOUBLE)) then + call errori( + + 'Var value read not that expected for variable ', i) + else + nok = nok + 1 + end if + end if + end if + end if +3 continue +1 continue + err = nfmpi_end_indep_data(ncid) + call print_nok(nok) + end + + +! +! check attributes of specified file have expected name, type, length & values +! + subroutine check_atts(ncid) + implicit none + integer ncid +#include "tests.inc" + + integer err !/* netCDF status */ + integer i + integer j + integer k + integer vid !/* "variable" ID */ + integer datatype + NFMPI_OFFSET ndx(1) + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + character*(MAX_NELS) text + doubleprecision value(MAX_NELS) + doubleprecision expect + integer nok !/* count of valid comparisons */ + + nok = 0 + + do 1, vid = 0, NVARS + i = varid(vid) + + do 2, j = 1, NATTS(i) + err = nfmpi_inq_attname(ncid, i, j, name) + if (err .ne. 0) then + call errore('nfmpi_inq_attname: ', err) + end if + if (name .ne. ATT_NAME(j,i)) then + call errori( + + 'nfmpi_inq_attname: unexpected name for var ', i) + end if + err = nfmpi_inq_att(ncid, i, name, datatype, length) + if (err .ne. 0) then + call errore('nfmpi_inq_att: ', err) + end if + if (datatype .ne. ATT_TYPE(j,i)) then + call errori( + + 'nfmpi_inq_att: unexpected type for var ', i) + end if + if (length .ne. ATT_LEN(j,i)) then + call errori( + + 'nfmpi_inq_att: unexpected length for var ', i) + end if + if (datatype .eq. NF_CHAR) then + err = nfmpi_get_att_text(ncid, i, name, text) + if (err .ne. 0) then + call errore('nfmpi_get_att_text: ', err) + end if + do 3, k = 1, ATT_LEN(j,i) + ndx(1) = k + if (ichar(text(k:k)) .ne. hash(datatype, -1, + + ndx)) + + then + call errori( + + 'nfmpi_get_att_text: unexpected value for var ', i) + else + nok = nok + 1 + end if +3 continue + else + err = nfmpi_get_att_double(ncid, i, name, value) + do 4, k = 1, ATT_LEN(j,i) + ndx(1) = k + expect = hash(datatype, -1, ndx) + if (inRange(expect,ATT_TYPE(j,i))) then + if (err .ne. 0) then + call errore( + + 'nfmpi_get_att_double: ', err) + end if + if (.not. equal(value(k), expect, + + ATT_TYPE(j,i), NFT_DOUBLE)) then + call errori( + + 'Att value read not that expected for var ', i) + else + nok = nok + 1 + end if + end if +4 continue + end if +2 continue +1 continue + call print_nok(nok) + end + + +! Check file (dims, vars, atts) corresponds to global variables */ + subroutine check_file(filename) + implicit none + character*(*) filename +#include "tests.inc" + + integer ncid !/* netCDF id */ + integer err !/* netCDF status */ + + err = nfmpi_open(comm, filename, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_open: ', err) + else + call check_dims(ncid) + call check_vars(ncid) + call check_atts(ncid) + err = nfmpi_close (ncid) + if (err .ne. 0) then + call errore('nfmpi_close: ', err) + end if + end if + end + + +! +! Functions for accessing attribute test data. +! +! NB: 'varid' is 0 for global attributes; thus, global attributes can +! be handled in the same loop as variable attributes. +! + + FUNCTION VARID(VID) + IMPLICIT NONE + INTEGER VID +#include "tests.inc" + IF (VID .LT. 1) THEN + VARID = NF_GLOBAL + ELSE + VARID = VID + ENDIF + end + + + FUNCTION NATTS(VID) + IMPLICIT NONE + INTEGER VID +#include "tests.inc" + IF (VID .LT. 1) THEN + NATTS = NGATTS + ELSE + NATTS = VAR_NATTS(VID) + ENDIF + END + + + FUNCTION ATT_NAME(J,VID) + IMPLICIT NONE + INTEGER J + INTEGER VID +#include "tests.inc" + IF (VID .LT. 1) THEN + ATT_NAME = GATT_NAME(J) + ELSE + ATT_NAME = ATTNAME(J,VID) + ENDIF + END + + + FUNCTION ATT_TYPE(J,VID) + IMPLICIT NONE + INTEGER J + INTEGER VID +#include "tests.inc" + IF (VID .LT. 1) THEN + ATT_TYPE = GATT_TYPE(J) + ELSE + ATT_TYPE = ATTTYPE(J,VID) + ENDIF + END + + + FUNCTION ATT_LEN(J,VID) + IMPLICIT NONE + INTEGER J + INTEGER VID +#include "tests.inc" + IF (VID .LT. 1) THEN + ATT_LEN = GATT_LEN(J) + ELSE + ATT_LEN = ATTLEN(J,VID) + ENDIF + END + + +! +! Return the minimum value of an internal type. +! + function internal_min(type) + implicit none + integer type + doubleprecision min_schar + doubleprecision min_short + doubleprecision min_int + doubleprecision min_long + doubleprecision max_float + doubleprecision max_double +#include "tests.inc" + + if (type .eq. NFT_CHAR) then + internal_min = 0 + else if (type .eq. NFT_INT1) then +#if defined NF_INT1_IS_C_SIGNED_CHAR + internal_min = min_schar() +#elif defined NF_INT1_IS_C_SHORT + internal_min = min_short() +#elif defined NF_INT1_IS_C_INT + internal_min = min_int() +#elif defined NF_INT1_IS_C_LONG + internal_min = min_long() +#else +#include "No C equivalent to Fortran INTEGER*1" +#endif + else if (type .eq. NFT_INT2) then +#if defined NF_INT2_IS_C_SHORT + internal_min = min_short() +#elif defined NF_INT2_IS_C_INT + internal_min = min_int() +#elif defined NF_INT2_IS_C_LONG + internal_min = min_long() +#else +#include "No C equivalent to Fortran INTEGER*2" +#endif + else if (type .eq. NFT_INT) then +#if defined NF_INT_IS_C_INT + internal_min = min_int() +#elif defined NF_INT_IS_C_LONG + internal_min = min_long() +#else +#include "No C equivalent to Fortran INTEGER" +#endif + else if (type .eq. NFT_REAL) then +#if defined NF_REAL_IS_C_FLOAT + internal_min = -max_float() +#elif defined NF_REAL_IS_C_DOUBLE + internal_min = -max_double() +#else +#include "No C equivalent to Fortran REAL" +#endif + else if (type .eq. NFT_DOUBLE) then +#if defined NF_DOUBLEPRECISION_IS_C_DOUBLE + internal_min = -max_double() +#elif defined NF_DOUBLEPRECISION_IS_C_FLOAT + internal_min = -max_float() +#else +#include "No C equivalent to Fortran DOUBLE" +#endif + else + stop 'internal_min(): invalid type' + end if + end + + +! +! Return the maximum value of an internal type. +! + function internal_max(type) + implicit none + integer type + doubleprecision max_schar + doubleprecision max_short + doubleprecision max_int + doubleprecision max_long + doubleprecision max_float + doubleprecision max_double +#include "tests.inc" + + if (type .eq. NFT_CHAR) then + internal_max = 255 + else if (type .eq. NFT_INT1) then +#if defined NF_INT1_IS_C_SIGNED_CHAR + internal_max = max_schar() +#elif defined NF_INT1_IS_C_SHORT + internal_max = max_short() +#elif defined NF_INT1_IS_C_INT + internal_max = max_int() +#elif defined NF_INT1_IS_C_LONG + internal_max = max_long() +#else +#include "No C equivalent to Fortran INTEGER*1" +#endif + else if (type .eq. NFT_INT2) then +#if defined NF_INT2_IS_C_SHORT + internal_max = max_short() +#elif defined NF_INT2_IS_C_INT + internal_max = max_int() +#elif defined NF_INT2_IS_C_LONG + internal_max = max_long() +#else +#include "No C equivalent to Fortran INTEGER*2" +#endif + else if (type .eq. NFT_INT) then +#if defined NF_INT_IS_C_INT + internal_max = max_int() +#elif defined NF_INT_IS_C_LONG + internal_max = max_long() +#else +#include "No C equivalent to Fortran INTEGER" +#endif + else if (type .eq. NFT_REAL) then +#if defined NF_REAL_IS_C_FLOAT + internal_max = max_float() +#elif defined NF_REAL_IS_C_DOUBLE + internal_max = max_double() +#else +#include "No C equivalent to Fortran REAL" +#endif + else if (type .eq. NFT_DOUBLE) then +#if defined NF_DOUBLEPRECISION_IS_C_DOUBLE + internal_max = max_double() +#elif defined NF_DOUBLEPRECISION_IS_C_FLOAT + internal_max = max_float() +#else +#include "No C equivalent to Fortran DOUBLE" +#endif + else + stop 'internal_max(): invalid type' + end if + end + + +! +! Return the minimum value of an external type. +! + function external_min(type) + implicit none + integer type +#include "tests.inc" + + if (type .eq. NF_BYTE) then + external_min = X_BYTE_MIN + else if (type .eq. NF_CHAR) then + external_min = X_CHAR_MIN + else if (type .eq. NF_SHORT) then + external_min = X_SHORT_MIN + else if (type .eq. NF_INT) then + external_min = X_INT_MIN + else if (type .eq. NF_FLOAT) then + external_min = X_FLOAT_MIN + else if (type .eq. NF_DOUBLE) then + external_min = X_DOUBLE_MIN + else + stop 'external_min(): invalid type' + end if + end + + +! +! Return the maximum value of an internal type. +! + function external_max(type) + implicit none + integer type +#include "tests.inc" + + if (type .eq. NF_BYTE) then + external_max = X_BYTE_MAX + else if (type .eq. NF_CHAR) then + external_max = X_CHAR_MAX + else if (type .eq. NF_SHORT) then + external_max = X_SHORT_MAX + else if (type .eq. NF_INT) then + external_max = X_INT_MAX + else if (type .eq. NF_FLOAT) then + external_max = X_FLOAT_MAX + else if (type .eq. NF_DOUBLE) then + external_max = X_DOUBLE_MAX + else + stop 'external_max(): invalid type' + end if + end + + +! +! Indicate whether or not a value lies in the range of an internal type. +! + function in_internal_range(itype, value) + implicit none + integer itype + doubleprecision value +#include "tests.inc" + + in_internal_range = value .ge. internal_min(itype) .and. + + value .le. internal_max(itype) + end + + +! +! Return the length of a character variable minus any trailing blanks. +! + function len_trim(string) + implicit none + character*(*) string +#include "tests.inc" + + do 1, len_trim = len(string), 1, -1 + if (string(len_trim:len_trim) .ne. ' ') + + goto 2 +1 continue + +2 return + end Index: /tags/v1-0-3/test/nf_test/Makefile.in =================================================================== --- /tags/v1-0-3/test/nf_test/Makefile.in (revision 444) +++ /tags/v1-0-3/test/nf_test/Makefile.in (revision 444) @@ -0,0 +1,105 @@ +# Makefile for netCDF (semi)exhaustive FORTRAN test. +# +# $Id$ + +srcdir = @srcdir@ +VPATH = @srcdir@ + +include ../../macros.make + +# M4FLAGS = -s -B7168 +# CC = cc -fullwarn -woff 1209,1506 + + +INCLUDES = -I$(srcdir) -I$(srcdir)/../../src/libf -I../../src/libf -I$(srcdir)/../../src/lib -I../../src/lib + +FFLAGS = $(INCLUDES) @FFLAGS@ +lib_netcdf = ../../src/lib/libpnetcdf.a +# Don't use "-L../libsrc -lnetcdf" in the following because that doesn't +# work on a CRAY T90 (sigh). +ld_netcdf = $(lib_netcdf) + +M4SRCS = \ + test_get.m4 \ + test_put.m4 +# + +FSRCS = \ + $(M4SRCS:.m4=.F) \ + nf_error.F \ + nf_test.F \ + test_read.F \ + test_write.F \ + util.F +# + +CSRCS = fortlib.c + +OBJS = \ + test_get.o \ + test_put.o \ + nf_error.o \ + nf_test.o \ + test_read.o \ + test_write.o \ + util.o \ + fortlib.o + +time_log = times + +GARBAGE = \ + $(time_log) \ + lint.out \ + nf_test \ + scratch.nc \ + *.f77 +# + +PACKING_LIST = \ + $(CSRCS) \ + $(FSRCS) \ + $(M4SRCS) \ + depend \ + Makefile \ + tests.inc +# + +all: nf_test + +test: nf_test test.nc + ./nf_test + @echo '*** Success ***' + +readonly: nf_test test.nc + ./nf_test -r + +test.nc: nf_test + ./nf_test -c + +install: + +uninstall: + + +nf_test: $(OBJS) $(lib_netcdf) + $(LINK.F) $(OBJS) $(ld_netcdf) $(FLIBS) $(MATHLIB) $(LIBS) + + +tags: $(FSRCS) $(CSRCS) FORCE + ctags -t $(FSRCS) $(CSRCS) ../fortran/*.c ../libsrc/*.c + + +test_get.F: test_get.m4 +test_put.F: test_put.m4 + +# This simple testing target ensures that the test files are present +testing: test.nc nf_test + rm -f scratch.nc + ./nf_test + +#test.nc: +# (cd ../nc_test && make nc_test && ./nc_test -c) +# cp ../nc_test/test.nc . + +include $(srcdir)/../../rules.make +include $(srcdir)/depend Index: /tags/v1-0-3/test/nf_test/fortlib.c =================================================================== --- /tags/v1-0-3/test/nf_test/fortlib.c (revision 558) +++ /tags/v1-0-3/test/nf_test/fortlib.c (revision 558) @@ -0,0 +1,247 @@ +/* + * $Id$ + * + * This file contains support functions for FORTRAN code. For example, + * under HP-UX A.09.05, the U77 library doesn't contain the exit() + * routine -- so we create one here. + * + * This file is heavily modified from nf_test/fortlib.c in the serial netcdf + * source. + */ + + +#include +#include +#include +#include +#include + + +#ifdef F77_NAME_UPPER +#define ud_exit_ UD_EXIT +#elif defined(F77_NAME_LOWER_2USCORE) +#define ud_exit_ ud_exit__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define ud_exit_ ud_exit +/* Else leave name alone */ +#endif + +FORTRAN_API void FORT_CALL ud_exit_(int *v1) { + if (*v1 == 0) { + MPI_Finalize(); + exit(0); + } + MPI_Abort(MPI_COMM_WORLD, *v1); + return; +} + +#ifdef F77_NAME_UPPER +#define ud_abort_ UD_ABORT +#elif defined(F77_NAME_LOWER_2USCORE) +#define ud_abort_ ud_abort__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define ud_abort_ ud_abort +/* Else leave name alone */ +#endif + +FORTRAN_API void FORT_CALL ud_abort_(int *v1) { + MPI_Abort(MPI_COMM_WORLD, *v1); + return; +} + +#ifdef F77_NAME_UPPER +#define ud_rand_ UD_RAND +#elif defined(F77_NAME_LOWER_2USCORE) +#define ud_rand_ ud_rand__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define ud_rand_ ud_rand +/* Else leave name alone */ +#endif + +/* +* Return a pseudo-random value between 0.0 and 1.0. +* +* We don't use RAND_MAX here because not all compilation +* environments define it (e.g. gcc(1) under SunOS 4.1.3). +*/ +FORTRAN_API double FORT_CALL ud_rand_(int *seed) { + if (*seed != 0) + srand(*seed); + return (rand() % 32768 )/ 32767.0; +} + +#ifdef F77_NAME_UPPER +#define ud_shift_ UD_SHIFT +#elif defined(F77_NAME_LOWER_2USCORE) +#define ud_shift_ ud_shift__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define ud_shift_ ud_shift +/* Else leave name alone */ +#endif + +FORTRAN_API int FORT_CALL ud_shift_(int * value, int *amount) { + if(*amount < 0) + *value >>= -*amount; + else if (*amount > 0) + *value <<= *amount; + return *value; +} + +#ifdef F77_NAME_UPPER +#define nc_ignorefpe_ NC_IGNOREFPE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nc_ignorefpe_ nc_ignorefpe__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nc_ignorefpe_ nc_ignorefpe +/* Else leave name alone */ +#endif +#include +FORTRAN_API void FORT_CALL nc_ignorefpe_(int *doit) +{ + if(doit) + (void) signal(SIGFPE, SIG_IGN); +} + +#ifdef F77_NAME_UPPER +#define min_int_ MIN_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define min_int_ min_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define min_int_ min_int +/* Else leave name alone */ +#endif +FORTRAN_API double min_int_() { + return INT_MIN; +} + +#ifdef F77_NAME_UPPER +#define min_schar_ MIN_SCHAR +#elif defined(F77_NAME_LOWER_2USCORE) +#define min_schar_ min_schar__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define min_schar_ min_schar +/* Else leave name alone */ +#endif +FORTRAN_API double min_schar_() { + return SCHAR_MIN; +} + +#ifdef F77_NAME_UPPER +#define min_short_ MIN_SHORT +#elif defined(F77_NAME_LOWER_2USCORE) +#define min_short_ min_short__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define min_short_ min_short +/* Else leave name alone */ +#endif +FORTRAN_API double min_short_() { + return SHRT_MIN; +} + +#ifdef F77_NAME_UPPER +#define max_int_ MAX_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define max_int_ max_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define max_int_ max_int +/* Else leave name alone */ +#endif +FORTRAN_API double max_int_() { + return INT_MAX; +} + +#ifdef F77_NAME_UPPER +#define max_schar_ MAX_SCHAR +#elif defined(F77_NAME_LOWER_2USCORE) +#define max_schar_ max_schar__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define max_schar_ max_schar +/* Else leave name alone */ +#endif +FORTRAN_API double max_schar_() { + return SCHAR_MAX; +} + +#ifdef F77_NAME_UPPER +#define max_short_ MAX_SHORT +#elif defined(F77_NAME_LOWER_2USCORE) +#define max_short_ max_short__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define max_short_ max_short +/* Else leave name alone */ +#endif +FORTRAN_API double max_short_() { + return SHRT_MAX; +} + +#ifdef F77_NAME_UPPER +#define max_float_ MAX_FLOAT +#elif defined(F77_NAME_LOWER_2USCORE) +#define max_float_ max_float__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define max_float_ max_float +/* Else leave name alone */ +#endif +FORTRAN_API double max_float_() { + return FLT_MAX; +} + +#ifdef F77_NAME_UPPER +#define max_double_ MAX_DOUBLE +#elif defined(F77_NAME_LOWER_2USCORE) +#define max_double_ max_double__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define max_double_ max_double +/* Else leave name alone */ +#endif +FORTRAN_API double max_double_() { + return DBL_MAX; +} + +#if 0 /* this is implemented in library src now */ + +#ifdef F77_NAME_UPPER +#define nfmpi_issyserr_ NFMPI_ISSYSERR +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_issyserr_ nfmpi_issyserr__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_issyserr_ nfmpi_issyserr +/* Else leave name alone */ +#endif + +FORTRAN_API int nfmpi_issyserr_(int * A1) { + if (*A1 > 0) + return 1; + else + return 0; +} + + +#ifdef F77_NAME_UPPER +#define nfmpi_delete_ NFMPI_DELETE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_delete_ nfmpi_delete__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_delete_ nfmpi_delete +/* Else leave name alone */ +#endif +FORTRAN_API void nfmpi_delete_(char * name, int *err, int d1) { + char *p1; + + {char *p = name + d1 - 1; + int li; + while (*p == ' ' && p > name) p--; + p++; + p1 = (char *)malloc( p-name + 1 ); + for (li=0; li<(p-name); li++) { p1[li] = name[li]; } + p1[li] = 0; + } + + if ( unlink(p1) != 0 ) + *err = errno; + else + *err = 0; + free(p1); +} + +#endif Index: /tags/v1-0-3/test/nf_test/nf_test.F =================================================================== --- /tags/v1-0-3/test/nf_test/nf_test.F (revision 559) +++ /tags/v1-0-3/test/nf_test/nf_test.F (revision 559) @@ -0,0 +1,526 @@ +#if 0 +/********************************************************************* + * Copyright 1996, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +/* + * Test driver for netCDF-3 interface. This program performs tests against + * the netCDF-3 specification for all user-level functions in an + * implementation of the netCDF library. + * + * Unless invoked with "-r" (readonly) option, must be invoked from a + * directory in which the invoker has write permission. + * + * Files: + * The read-only tests read files: + * test.nc (see below) + * test_get.F (used merely as an example of a non-netCDF file) + * + * The write tests + * read test.nc (see below) + * write scratch.nc (deleted after each test) + * + * The file test.nc is created by running nc_test with the -c (create) option. + */ +#endif + + subroutine usage() + implicit none +#include "tests.inc" + + call error('usage: nf_test [-hrv] [-n ]') + call error(' nf_test [-c]') + call error(' [-h] Print help' ) + call error(' [-c] Create file test.nc (Do not do tests)' ) + call error(' [-r] Just do read-only tests' ) + call error(' [-v] Verbose mode' ) + call error( + + ' [-n ] max. number of messages per test (Default: 8)') + end + + + subroutine test(name, func) + implicit none + character*(*) name + external func +#include "tests.inc" + + write(*, 1) name +1 format('*** Testing ', a, ' ... ') + nfails = 0 + call func() + nfailsTotal = nfailsTotal + nfails + if (verbose) + + print *, ' ' + if ( nfails .ne. 0) then + print *, ' ' + print *, ' ### ', nfails, ' FAILURES TESTING ', name, + + '! ###' + end if + end + + +#if _CRAYIEEE +! which machines need this? + subroutine getarg(iarg, carg) + implicit none + integer iarg + character*(*) carg + integer ilen + integer ierror + call PXFGETARG(iarg, carg, ilen, ierror) + end +#endif + + program nf_test +#if defined(VISUAL_CPLUSPLUS) +! DIGITAL Visual Fortran needs DFLIB for getarg + USE DFLIB +! DIGITAL Visual Fortran needs DFPORT for iargc + USE DFPORT + implicit none +#elif defined(NAGf90Fortran) + USE F90_UNIX_ENV, only : iargc, getarg + implicit none +#else + implicit none + integer iargc +#endif +#if defined(__crayx1) + integer ipxfargc +#endif +#include "tests.inc" + + integer argc + character*80 arg + integer iarg + integer iopt + character*1 opt + integer lastopt + logical skiparg + integer status + integer err + + external test_nfmpi_strerror + external test_nfmpi_open + external test_nfmpi_close + external test_nfmpi_inq + external test_nfmpi_inq_dimid + external test_nfmpi_inq_dim + external test_nfmpi_inq_dimlen + external test_nfmpi_inq_dimname + external test_nfmpi_inq_varid + external test_nfmpi_inq_var + external test_nfmpi_inq_natts + external test_nfmpi_inq_ndims + external test_nfmpi_inq_nvars + external test_nfmpi_inq_unlimdim + external test_nfmpi_inq_vardimid + external test_nfmpi_inq_varname + external test_nfmpi_inq_varnatts + external test_nfmpi_inq_varndims + external test_nfmpi_inq_vartype + external test_nfmpi_get_var1_text +#if defined(NF_INT1_T) + external test_nfmpi_get_var1_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_var1_int2 +#endif + external test_nfmpi_get_var1_int + external test_nfmpi_get_var1_real + external test_nfmpi_get_var1_double + external test_nfmpi_get_var_text +#if defined(NF_INT1_T) + external test_nfmpi_get_var_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_var_int2 +#endif + external test_nfmpi_get_var_int + external test_nfmpi_get_var_real + external test_nfmpi_get_var_double + external test_nfmpi_get_vara_text +#if defined(NF_INT1_T) + external test_nfmpi_get_vara_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_vara_int2 +#endif + external test_nfmpi_get_vara_int + external test_nfmpi_get_vara_real + external test_nfmpi_get_vara_double + external test_nfmpi_get_vars_text +#if defined(NF_INT1_T) + external test_nfmpi_get_vars_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_vars_int2 +#endif + external test_nfmpi_get_vars_int + external test_nfmpi_get_vars_real + external test_nfmpi_get_vars_double + + external test_nfmpi_get_varm_text +#if defined(NF_INT1_T) + external test_nfmpi_get_varm_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_varm_int2 +#endif + external test_nfmpi_get_varm_int + external test_nfmpi_get_varm_real + external test_nfmpi_get_varm_double + + external test_nfmpi_get_att_text +#if defined(NF_INT1_T) + external test_nfmpi_get_att_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_get_att_int2 +#endif + external test_nfmpi_get_att_int + external test_nfmpi_get_att_real + external test_nfmpi_get_att_double + external test_nfmpi_inq_att + external test_nfmpi_inq_attname + external test_nfmpi_inq_attid + external test_nfmpi_inq_attlen + external test_nfmpi_inq_atttype + external test_nfmpi_create + external test_nfmpi_redef + external test_nfmpi_enddef + external test_nfmpi_sync + external test_nfmpi_abort + external test_nfmpi_def_dim + external test_nfmpi_rename_dim + external test_nfmpi_def_var + external test_nfmpi_put_var1_text +#if defined(NF_INT1_T) + external test_nfmpi_put_var1_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_var1_int2 +#endif + external test_nfmpi_put_var1_int + external test_nfmpi_put_var1_real + external test_nfmpi_put_var1_double + external test_nfmpi_put_var_text +#if defined(NF_INT1_T) + external test_nfmpi_put_var_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_var_int2 +#endif + external test_nfmpi_put_var_int + external test_nfmpi_put_var_real + external test_nfmpi_put_var_double + external test_nfmpi_put_vara_text +#if defined(NF_INT1_T) + external test_nfmpi_put_vara_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_vara_int2 +#endif + external test_nfmpi_put_vara_int + external test_nfmpi_put_vara_real + external test_nfmpi_put_vara_double + external test_nfmpi_put_vars_text +#if defined(NF_INT1_T) + external test_nfmpi_put_vars_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_vars_int2 +#endif + external test_nfmpi_put_vars_int + external test_nfmpi_put_vars_real + external test_nfmpi_put_vars_double + + external test_nfmpi_put_varm_text +#if defined(NF_INT1_T) + external test_nfmpi_put_varm_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_varm_int2 +#endif + external test_nfmpi_put_varm_int + external test_nfmpi_put_varm_real + external test_nfmpi_put_varm_double + + external test_nfmpi_rename_var + external test_nfmpi_put_att_text +#if defined(NF_INT1_T) + external test_nfmpi_put_att_int1 +#endif +#if defined(NF_INT2_T) + external test_nfmpi_put_att_int2 +#endif + external test_nfmpi_put_att_int + external test_nfmpi_put_att_real + external test_nfmpi_put_att_double + external test_nfmpi_copy_att + external test_nfmpi_rename_att + external test_nfmpi_del_att + external test_nfmpi_set_fill +#if 0 + external test_nfmpi_set_default_format +#endif + external nc_ignorefpe + + call MPI_INIT(err) + comm = MPI_COMM_WORLD + + call nc_ignorefpe(1) + + testfile = 'test.nc' + scratch = 'scratch.nc' + + nfailsTotal = 0 + call getarg(0, progname) + create_file = .false. !/* file test.nc will normally already exist */ + readonly = .false. !/* assume may write in test dir as default */ + verbose = .false. + max_nmpt = 8 + skiparg = .false. + +#if defined(__crayx1) + argc = ipxfargc() +#else + argc = iargc() +#endif + do 1, iarg = 1, argc + if (skiparg) then + skiparg = .false. + else + call getarg(iarg, arg) + if (arg(1:1) .eq. '-') then + lastopt = index(arg, ' ') - 1 + do 2, iopt = 2, lastopt + opt = arg(iopt:iopt) + if (opt .eq. 'c') then + create_file = .true. + else if (opt .eq. 'r') then + readonly = .true. + else if (opt .eq. 'v') then + verbose = .true. + else if (opt .eq. 'n') then + call getarg(iarg+1, arg) + ! NOTE: The UNICOS 8 fort77(1) compiler does + ! not support list-directed I/O from an internal + ! file -- so we use a format specification. + read (arg, '(i6)') max_nmpt + skiparg = .true. + go to 1 + else + call usage + call ud_exit(1) + end if + 2 continue + else + call usage + call ud_exit(1) + end if + end if +1 continue + +C /* Initialize global variables defining test file */ + call init_gvars + + if ( create_file ) then + call write_file(testfile) + if (nfailsTotal .eq. 0) + + call ud_exit(0) + call ud_exit(1) + end if + +C /* delete any existing scratch netCDF file */ + if ( .not. readonly ) + + err = nfmpi_delete(scratch, MPI_COMM_WORLD) + +C /* Test read-only functions, using pregenerated test-file */ + call test('nfmpi_strerror', test_nfmpi_strerror) + call test('nfmpi_open', test_nfmpi_open) + call test('nfmpi_close', test_nfmpi_close) + call test('nfmpi_inq', test_nfmpi_inq) + call test('nfmpi_inq_dimid', test_nfmpi_inq_dimid) + call test('nfmpi_inq_dim', test_nfmpi_inq_dim) + call test('nfmpi_inq_dimlen', test_nfmpi_inq_dimlen) + call test('nfmpi_inq_dimname', test_nfmpi_inq_dimname) + call test('nfmpi_inq_varid', test_nfmpi_inq_varid) + call test('nfmpi_inq_var', test_nfmpi_inq_var) + call test('nfmpi_inq_natts', test_nfmpi_inq_natts) + call test('nfmpi_inq_ndims', test_nfmpi_inq_ndims) + call test('nfmpi_inq_nvars', test_nfmpi_inq_nvars) + call test('nfmpi_inq_unlimdim', test_nfmpi_inq_unlimdim) + call test('nfmpi_inq_vardimid', test_nfmpi_inq_vardimid) + call test('nfmpi_inq_varname', test_nfmpi_inq_varname) + call test('nfmpi_inq_varnatts', test_nfmpi_inq_varnatts) + call test('nfmpi_inq_varndims', test_nfmpi_inq_varndims) + call test('nfmpi_inq_vartype', test_nfmpi_inq_vartype) + call test('nfmpi_get_var1_text', test_nfmpi_get_var1_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_var1_int1', test_nfmpi_get_var1_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_var1_int2', test_nfmpi_get_var1_int2) +#endif + call test('nfmpi_get_var1_int', test_nfmpi_get_var1_int) + call test('nfmpi_get_var1_real', test_nfmpi_get_var1_real) + call test('nfmpi_get_var1_double', test_nfmpi_get_var1_double) + call test('nfmpi_get_var_text', test_nfmpi_get_var_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_var_int1', test_nfmpi_get_var_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_var_int2', test_nfmpi_get_var_int2) +#endif + call test('nfmpi_get_var_int', test_nfmpi_get_var_int) + call test('nfmpi_get_var_real', test_nfmpi_get_var_real) + call test('nfmpi_get_var_double', test_nfmpi_get_var_double) + call test('nfmpi_get_vara_text', test_nfmpi_get_vara_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_vara_int1', test_nfmpi_get_vara_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_vara_int2', test_nfmpi_get_vara_int2) +#endif + call test('nfmpi_get_vara_int', test_nfmpi_get_vara_int) + call test('nfmpi_get_vara_real', test_nfmpi_get_vara_real) + call test('nfmpi_get_vara_double', test_nfmpi_get_vara_double) + call test('nfmpi_get_vars_text', test_nfmpi_get_vars_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_vars_int1', test_nfmpi_get_vars_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_vars_int2', test_nfmpi_get_vars_int2) +#endif + call test('nfmpi_get_vars_int', test_nfmpi_get_vars_int) + call test('nfmpi_get_vars_real', test_nfmpi_get_vars_real) + call test('nfmpi_get_vars_double', test_nfmpi_get_vars_double) + + call test('nfmpi_get_varm_text', test_nfmpi_get_varm_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_varm_int1', test_nfmpi_get_varm_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_varm_int2', test_nfmpi_get_varm_int2) +#endif + call test('nfmpi_get_varm_int', test_nfmpi_get_varm_int) + call test('nfmpi_get_varm_real', test_nfmpi_get_varm_real) + call test('nfmpi_get_varm_double', test_nfmpi_get_varm_double) + + call test('nfmpi_get_att_text', test_nfmpi_get_att_text) +#if defined(NF_INT1_T) + call test('nfmpi_get_att_int1', test_nfmpi_get_att_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_get_att_int2', test_nfmpi_get_att_int2) +#endif + call test('nfmpi_get_att_int', test_nfmpi_get_att_int) + call test('nfmpi_get_att_real', test_nfmpi_get_att_real) + call test('nfmpi_get_att_double', test_nfmpi_get_att_double) + call test('nfmpi_inq_att', test_nfmpi_inq_att) + call test('nfmpi_inq_attname', test_nfmpi_inq_attname) + call test('nfmpi_inq_attid', test_nfmpi_inq_attid) + call test('nfmpi_inq_attlen', test_nfmpi_inq_attlen) + call test('nfmpi_inq_atttype', test_nfmpi_inq_atttype) + +C /* Test write functions */ + if (.not. readonly) then + call test('nfmpi_create', test_nfmpi_create) + call test('nfmpi_redef', test_nfmpi_redef) + call test('nfmpi_enddef', test_nfmpi_enddef) + call test('nfmpi_sync', test_nfmpi_sync) + call test('nfmpi_abort', test_nfmpi_abort) + call test('nfmpi_def_dim', test_nfmpi_def_dim) + call test('nfmpi_rename_dim', test_nfmpi_rename_dim) + call test('nfmpi_def_var', test_nfmpi_def_var) + call test('nfmpi_put_var1_text', test_nfmpi_put_var1_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_var1_int1', test_nfmpi_put_var1_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_var1_int2', test_nfmpi_put_var1_int2) +#endif + call test('nfmpi_put_var1_int', test_nfmpi_put_var1_int) + call test('nfmpi_put_var1_real', test_nfmpi_put_var1_real) + call test('nfmpi_put_var1_double', + + test_nfmpi_put_var1_double) + call test('nfmpi_put_var_text', test_nfmpi_put_var_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_var_int1', test_nfmpi_put_var_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_var_int2', test_nfmpi_put_var_int2) +#endif + call test('nfmpi_put_var_int', test_nfmpi_put_var_int) + call test('nfmpi_put_var_real', test_nfmpi_put_var_real) + call test('nfmpi_put_var_double', + + test_nfmpi_put_var_double) + call test('nfmpi_put_vara_text', test_nfmpi_put_vara_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_vara_int1', test_nfmpi_put_vara_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_vara_int2', test_nfmpi_put_vara_int2) +#endif + call test('nfmpi_put_vara_int', test_nfmpi_put_vara_int) + call test('nfmpi_put_vara_real', test_nfmpi_put_vara_real) + call test('nfmpi_put_vara_double', + + test_nfmpi_put_vara_double) + call test('nfmpi_put_vars_text', test_nfmpi_put_vars_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_vars_int1', test_nfmpi_put_vars_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_vars_int2', test_nfmpi_put_vars_int2) +#endif + call test('nfmpi_put_vars_int', test_nfmpi_put_vars_int) + call test('nfmpi_put_vars_real', test_nfmpi_put_vars_real) + call test('nfmpi_put_vars_double', + + test_nfmpi_put_vars_double) + + call test('nfmpi_put_varm_text', test_nfmpi_put_varm_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_varm_int1', test_nfmpi_put_varm_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_varm_int2', test_nfmpi_put_varm_int2) +#endif + call test('nfmpi_put_varm_int', test_nfmpi_put_varm_int) + call test('nfmpi_put_varm_real', test_nfmpi_put_varm_real) + call test('nfmpi_put_varm_double', + + test_nfmpi_put_varm_double) + + call test('nfmpi_rename_var', test_nfmpi_rename_var) + call test('nfmpi_put_att_text', test_nfmpi_put_att_text) +#if defined(NF_INT1_T) + call test('nfmpi_put_att_int1', test_nfmpi_put_att_int1) +#endif +#if defined(NF_INT2_T) + call test('nfmpi_put_att_int2', test_nfmpi_put_att_int2) +#endif + call test('nfmpi_put_att_int', test_nfmpi_put_att_int) + call test('nfmpi_put_att_real', test_nfmpi_put_att_real) + call test('nfmpi_put_att_double', + + test_nfmpi_put_att_double) + call test('nfmpi_copy_att', test_nfmpi_copy_att) + call test('nfmpi_rename_att', test_nfmpi_rename_att) + call test('nfmpi_del_att', test_nfmpi_del_att) + call test('nfmpi_set_fill', test_nfmpi_set_fill) +#if 0 + call test('nfmpi_set_default_format', + + test_nfmpi_set_default_format); +#endif + end if + + print *, 'NOTE: Parallel-netcdf expects to see 3 failures' + print *,'Total number of failures: ', nfailsTotal + if (nfailsTotal .eq. 3) + + call ud_exit(0) + if (nfailsTotal .eq. 0) + + call ud_exit(0) + call ud_exit(1) + end Index: /tags/v1-0-3/test/nf_test/test_put.m4 =================================================================== --- /tags/v1-0-3/test/nf_test/test_put.m4 (revision 559) +++ /tags/v1-0-3/test/nf_test/test_put.m4 (revision 559) @@ -0,0 +1,1395 @@ +divert(-1) + +dnl This is m4 source. +dnl Process using m4 to produce FORTRAN language file. + +changequote([,]) dnl + +undefine([index])dnl + +dnl Macros + +dnl Upcase(str) +dnl +define([Upcase],[dnl +translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)]) + +dnl NFT_ITYPE(type) +dnl +define([NFT_ITYPE], [NFT_[]Upcase($1)]) + +dnl ARITH(itype, value) +dnl +define([ARITH], [ifelse($1, text, ichar($2), $2)]) + +dnl DATATYPE(funf_suffix) +dnl +define([DATATYPE], [dnl +ifelse($1, text, character, +ifelse($1, int1, NF_INT1_T, +ifelse($1, int2, NF_INT2_T, +ifelse($1, int, integer, +ifelse($1, real, real, +ifelse($1, double, doubleprecision)[]dnl +)[]dnl +)[]dnl +)[]dnl +)[]dnl +)[]dnl +]) + +dnl MAKE_ARITH(funf_suffix, var) +dnl +define([MAKE_ARITH], [dnl +ifelse($1, text, ichar($2), $2)[]dnl +]) + +dnl MAKE_DOUBLE(funf_suffix, var) +dnl +define([MAKE_DOUBLE], [dnl +ifelse($1, text, dble(ichar($2)), dble($2))[]dnl +]) + +dnl MAKE_TYPE(funf_suffix, var) +dnl +define([MAKE_TYPE], [dnl +ifelse($1, text, char(int($2)), $2)[]dnl +]) + +dnl HASH(TYPE) +dnl +define([HASH], +[dnl +C +C ensure hash value within range for internal TYPE +C + function hash_$1(type, rank, index, itype) + implicit none +#include "tests.inc" + integer type + integer rank + NFMPI_OFFSET index(1) + integer itype + doubleprecision minimum + doubleprecision maximum + + minimum = internal_min(itype) + maximum = internal_max(itype) + + hash_$1 = max(minimum, min(maximum, hash4( type, rank, + + index, itype))) + end +])dnl + + +dnl CHECK_VARS(TYPE) +dnl +define([CHECK_VARS],dnl +[dnl +C +C check all vars in file which are (text/numeric) compatible with TYPE +C + subroutine check_vars_$1(filename) + implicit none +#include "tests.inc" + character*(*) filename + integer ncid !/* netCDF id */ + NFMPI_OFFSET index(MAX_RANK) + integer err !/* status */ + integer d + integer i + integer j + DATATYPE($1) value + integer datatype + integer ndims + integer dimids(MAX_RANK) + integer ngatts + doubleprecision expect + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + logical canConvert !/* Both text or both numeric */ + integer nok !/* count of valid comparisons */ + doubleprecision val + integer intindex + + nok = 0 + + err = nfmpi_open(comm, filename, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_begin_indep_data(ncid) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (canConvert) then + err = nfmpi_inq_var(ncid, i, name, datatype, ndims, + + dimids, ngatts) + if (err .ne. 0) + + call errore('nfmpi_inq_var: ', err) + if (name .ne. var_name(i)) + + call error('Unexpected var_name') + if (datatype .ne. var_type(i)) + + call error('Unexpected type') + if (ndims .ne. var_rank(i)) + + call error('Unexpected rank') + do 2, j = 1, ndims + err = nfmpi_inq_dim(ncid, dimids(j), name, + + length) + if (err .ne. 0) + + call errore('nfmpi_inq_dim: ', err) + if (length .ne. var_shape(j,i)) + + call error('Unexpected shape') +2 continue + do 3, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes()') + expect = hash4( var_type(i), var_rank(i), index, + + NFT_ITYPE($1)) + err = nfmpi_get_var1_$1(ncid, i, index, + + value) + if (inRange3(expect,datatype,NFT_ITYPE($1))) then + if (in_internal_range(NFT_ITYPE($1), + + expect)) then + if (err .ne. 0) then + call errore + + ('nfmpi_get_var1_$1: ', + + err) + else + val = MAKE_ARITH($1,value) + if (.not.equal( + + val, + + expect,var_type(i), + + NFT_ITYPE($1))) then + call error( + + 'Var value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: %d', i) + call errorc('var_name: ', + + var_name(i)) + call error('index:') + do 4, d = 1, var_rank(i) + intindex = index(d) + call errori(' ', intindex) +4 continue + call errord('expect: ', expect) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if + end if + end if +3 continue + end if +1 continue + err = nfmpi_end_indep_data(ncid) + err = nfmpi_close (ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +])dnl + + +dnl CHECK_ATTS(TYPE) numeric only +dnl +define([CHECK_ATTS],dnl +[dnl +C/* +C * check all attributes in file which are (text/numeric) compatible with TYPE +C * ignore any attributes containing values outside range of TYPE +C */ + subroutine check_atts_$1(ncid) + implicit none +#include "tests.inc" + integer ncid + integer err !/* status */ + integer i + integer j + integer k + NFMPI_OFFSET ndx(1) + DATATYPE($1) value(MAX_NELS) + integer datatype + doubleprecision expect(MAX_NELS) + NFMPI_OFFSET length + integer nInExtRange !/* number values within external range */ + integer nInIntRange !/* number values within internal range */ + logical canConvert !/* Both text or both numeric */ + integer nok !/* count of valid comparisons */ + doubleprecision val + + nok = 0 + + do 1, i = 0, NVARS + do 2, j = 1, NATTS(i) + canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (canConvert) then + err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i), + + datatype, length) + if (err .ne. 0) + + call errore('nfmpi_inq_att: ', err) + if (datatype .ne. ATT_TYPE(j,i)) + + call error('nfmpi_inq_att: unexpected type') + if (length .ne. ATT_LEN(j,i)) + + call error('nfmpi_inq_att: unexpected length') + if (.not.(length .le. MAX_NELS)) + + stop 'assert(length .le. MAX_NELS)' + nInIntRange = 0 + nInExtRange = 0 + do 4, k = 1, length + ndx(1) = k + expect(k) = hash4( datatype, -1, ndx, + + NFT_ITYPE($1)) + if (inRange3(expect(k), datatype, + + NFT_ITYPE($1))) then + nInExtRange = nInExtRange + 1 + if (in_internal_range(NFT_ITYPE($1), + + expect(k))) + + nInIntRange = nInIntRange + 1 + end if +4 continue + err = nfmpi_get_att_$1(ncid, i, + + ATT_NAME(j,i), value) + if (nInExtRange .eq. length .and. + + nInIntRange .eq. length) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', err) + end if + do 3, k = 1, length + if (inRange3(expect(k),datatype,NFT_ITYPE($1)) + + .and. + + in_internal_range(NFT_ITYPE($1), + + expect(k))) then + val = MAKE_ARITH($1,value(k)) + if (.not.equal( + + val, + + expect(k),datatype, + + NFT_ITYPE($1))) then + call error( + + 'att. value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: ', i) + call errorc('att_name: ', + + ATT_NAME(j,i)) + call errori('element number: ', k) + call errord('expect: ', expect(k)) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if +3 continue + end if +2 continue +1 continue + + call print_nok(nok) + end +])dnl + + +dnl TEST_NFMPI_PUT_VAR1(TYPE) +dnl +define([TEST_NFMPI_PUT_VAR1],dnl +[dnl + subroutine test_nfmpi_put_var1_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + NFMPI_OFFSET index(MAX_RANK) + logical canConvert !/* Both text or both numeric */ + DATATYPE($1) value + doubleprecision val + + value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */ + + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + err = nfmpi_begin_indep_data(ncid) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + do 2, j = 1, var_rank(i) + index(j) = 1 +2 continue + err = nfmpi_put_var1_$1(BAD_ID, i, index, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_var1_$1(ncid, BAD_VARID, + + index, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + if (var_dimid(j,i) .gt. 1) then !/* skip record dim */ + index(j) = var_shape(j,i) + 1 + err = nfmpi_put_var1_$1(ncid, i, + + index, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad index: ', err) + endif + index(j) = 0 + end if +3 continue + do 4, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes 1') + value = MAKE_TYPE($1, hash_$1(var_type(i),var_rank(i), + + index, NFT_ITYPE($1))) + err = nfmpi_put_var1_$1(ncid, i, index, value) + if (canConvert) then + val = ARITH($1, value) + if (inRange3(val, var_type(i), NFT_ITYPE($1))) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +4 continue +1 continue + err = nfmpi_end_indep_data(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + call check_vars_$1(scratch) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', + + scratch) + end +])dnl + + +dnl TEST_NFMPI_PUT_VAR(TYPE) +dnl +define([TEST_NFMPI_PUT_VAR],dnl +[dnl + subroutine test_nfmpi_put_var_$1() + implicit none +#include "tests.inc" + integer ncid + integer vid + integer i + integer j + integer err + integer nels + NFMPI_OFFSET index(MAX_RANK) + logical canConvert !/* Both text or both numeric */ + logical allInExtRange !/* All values within external range?*/ + DATATYPE($1) value(MAX_NELS) + doubleprecision val + + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + err = nfmpi_begin_indep_data(ncid) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + err = nfmpi_put_var_$1(BAD_ID, i, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_var_$1(ncid, BAD_VARID, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + nels = 1 + do 3, j = 1, var_rank(i) + nels = nels * var_shape(j,i) +3 continue + allInExtRange = .true. + do 4, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes 1') + value(j) = MAKE_TYPE($1, hash_$1(var_type(i), + + var_rank(i), + + index, NFT_ITYPE($1))) + val = ARITH($1, value(j)) + allInExtRange = allInExtRange .and. + + inRange3(val, var_type(i), NFT_ITYPE($1)) +4 continue + err = nfmpi_put_var_$1(ncid, i, value) + if (canConvert) then + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE .and. + + var_dimid(var_rank(i),i) .ne. RECDIM) + + call errore('Range error: ', err) + endif + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + endif +1 continue + err = nfmpi_end_indep_data(ncid) + +C The preceeding has written nothing for record variables, now try +C again with more than 0 records. + +C Write record number NRECS to force writing of preceding records. +C Assumes variable cr is char vector with UNLIMITED dimension. + + err = nfmpi_inq_varid(ncid, "cr", vid) + if (err .ne. 0) + + call errore('nfmpi_inq_varid: ', err) + index(1) = NRECS + err = nfmpi_begin_indep_data(ncid) + err = nfmpi_put_var1_text(ncid, vid, index, 'x') + if (err .ne. 0) + + call errore('nfmpi_put_var1_text: ', err) + + do 5 i = 1, NVARS +C Only test record variables here + if (var_rank(i) .ge. 1 .and. + + var_dimid(var_rank(i),i) .eq. RECDIM) then + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (var_rank(i) .gt. MAX_RANK) + + stop 'var_rank(i) .gt. MAX_RANK' + if (var_nels(i) .gt. MAX_NELS) + + stop 'var_nels(i) .gt. MAX_NELS' + err = nfmpi_put_var_$1(BAD_ID, i, value) + + nels = 1 + do 6 j = 1, var_rank(i) + nels = nels * var_shape(j,i) +6 continue + allInExtRange = .true. + do 7, j = 1, nels + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes()') + value(j) = MAKE_TYPE($1, hash_$1(var_type(i), + + var_rank(i), + + index, NFT_ITYPE($1))) + val = ARITH($1, value(j)) + allInExtRange = allInExtRange .and. + + inRange3(val, var_type(i), NFT_ITYPE($1)) +7 continue + err = nfmpi_put_var_$1(ncid, i, value) + if (canConvert) then + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('range error: ', err) + endif + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + endif + endif +5 continue + err = nfmpi_end_indep_data(ncid); + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + call check_vars_$1(scratch) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', + + scratch) + end +])dnl + + +dnl TEST_NFMPI_PUT_VARA(TYPE) +dnl +define([TEST_NFMPI_PUT_VARA],dnl +[dnl + subroutine test_nfmpi_put_vara_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer k + integer d + integer err + integer nslabs + integer nels + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + logical canConvert !/* Both text or both numeric */ + logical allInExtRange !/* all values within external range? */ + DATATYPE($1) value(MAX_NELS) + doubleprecision val + integer ud_shift + + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) + + stop 'assert(var_rank(i) .le. MAX_RANK)' + if (.not.(var_nels(i) .le. MAX_NELS)) + + stop 'assert(var_nels(i) .le. MAX_NELS)' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 +2 continue + err = nfmpi_put_vara_$1_all(BAD_ID, i, start, + + edge, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_vara_$1_all(ncid, BAD_VARID, + + start, edge, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + if (var_dimid(j,i) .ne. RECDIM) then !/* skip record dim */ + start(j) = var_shape(j,i) + 1 + err = nfmpi_put_vara_$1_all(ncid, i, start, + + edge, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad start: ', err) + endif + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_put_vara_$1_all(ncid, i, start, + + edge, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + endif + edge(j) = 1 + end if +3 continue + +C /* Check correct error returned even when nothing to put */ + do 20, j = 1, var_rank(i) + edge(j) = 0 +20 continue + err = nfmpi_put_vara_$1_all(BAD_ID, i, start, + + edge, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_vara_$1_all(ncid, BAD_VARID, + + start, edge, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 21, j = 1, var_rank(i) + if (var_dimid(j,i) .gt. 1) then ! skip record dim + start(j) = var_shape(j,i) + 1 + edge(j) = 1 !/* By Jianwei, fix NF_EINVALCOORDS bug */ + err = nfmpi_put_vara_$1_all(ncid, i, start, + + edge, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad start: ', err) + endif + start(j) = 1 + edge(j) = 0 !/* By Jianwei, restore original value */ + endif +21 continue + err = nfmpi_put_vara_$1_all(ncid, i, start, edge, value) + if (canConvert) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + endif + do 22, j = 1, var_rank(i) + edge(j) = 1 +22 continue + + + !/* Choose a random point dividing each dim into 2 parts */ + !/* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue + !/* bits of k determine whether to put lower or upper part of dim */ + do 5, k = 1, nslabs + nels = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + nels = nels * edge(j) +6 continue + allInExtRange = .true. + do 7, j = 1, nels + err = index2indexes(j, var_rank(i), edge, index) + if (err .ne. 0) + + call error('error in index2indexes 1') + do 8, d = 1, var_rank(i) + index(d) = index(d) + start(d) - 1 +8 continue + value(j)= MAKE_TYPE($1, hash_$1(var_type(i), + + var_rank(i), index, + + NFT_ITYPE($1))) + val = ARITH($1, value(j)) + allInExtRange = allInExtRange .and. + + inRange3(val, var_type(i), NFT_ITYPE($1)) +7 continue + err = nfmpi_put_vara_$1_all(ncid, i, start, + + edge, value) + if (canConvert) then + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('range error: ', err) + end if + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +5 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + call check_vars_$1(scratch) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', + + scratch) + end +])dnl + + +dnl TEST_NFMPI_PUT_VARS(TYPE) +dnl +define([TEST_NFMPI_PUT_VARS],dnl +[dnl + subroutine test_nfmpi_put_vars_$1() + implicit none +#include "tests.inc" + integer ncid + integer d + integer i + integer j + integer k + integer m + integer err + integer nels + integer nslabs + integer nstarts !/* number of different starts */ + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET index2(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + NFMPI_OFFSET count(MAX_RANK) + NFMPI_OFFSET sstride(MAX_RANK) + NFMPI_OFFSET stride(MAX_RANK) + logical canConvert !/* Both text or both numeric */ + logical allInExtRange !/* all values within external range? */ + DATATYPE($1) value(MAX_NELS) + doubleprecision val + integer ud_shift + + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) + + stop 'assert(var_rank(i) .le. MAX_RANK)' + if (.not.(var_nels(i) .le. MAX_NELS)) + + stop 'assert(var_nels(i) .le. MAX_NELS)' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 + stride(j) = 1 +2 continue + err = nfmpi_put_vars_$1_all(BAD_ID, i, start, + + edge, stride, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_vars_$1_all(ncid, BAD_VARID, start, + + edge, stride, + + value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + if (var_dimid(j,i) .ne. RECDIM) then ! skip record dim + start(j) = var_shape(j,i) + 1 + err = nfmpi_put_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad start: ', err) + endif + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_put_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + endif + edge(j) = 1 + stride(j) = 0 + err = nfmpi_put_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_ESTRIDE) + + call errore('bad stride: ', err) + endif + stride(j) = 1 + end if +3 continue + !/* Choose a random point dividing each dim into 2 parts */ + !/* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue + !/* bits of k determine whether to put lower or upper part of dim */ + !/* choose random stride from 1 to edge */ + do 5, k = 1, nslabs + nstarts = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + if (edge(j) .gt. 0) then + stride(j) = 1+roll(edge(j)) + else + stride(j) = 1 + end if + sstride(j) = stride(j) + nstarts = nstarts * stride(j) +6 continue + do 7, m = 1, nstarts + err = index2indexes(m, var_rank(i), sstride, index) + if (err .ne. 0) + + call error('error in index2indexes') + nels = 1 + do 8, j = 1, var_rank(i) + count(j) = 1 + (edge(j) - index(j)) / stride(j) + nels = nels * count(j) + index(j) = index(j) + start(j) - 1 +8 continue + !/* Random choice of forward or backward */ +C/* TODO +C if ( roll(2) ) { +C for (j = 1 j .lt. var_rank(i) j++) { +C index(j) += (count(j) - 1) * stride(j) +C stride(j) = -stride(j) +C } +C } +C*/ + allInExtRange = .true. + do 9, j = 1, nels + err = index2indexes(j, var_rank(i), count, + + index2) + if (err .ne. 0) + + call error('error in index2indexes') + do 10, d = 1, var_rank(i) + index2(d) = index(d) + + + (index2(d)-1) * stride(d) +10 continue + value(j) = MAKE_TYPE($1, hash_$1(var_type(i), + + var_rank(i), + + index2, NFT_ITYPE($1))) + val = ARITH($1, value(j)) + allInExtRange = allInExtRange .and. + + inRange3(val, var_type(i), + + NFT_ITYPE($1)) +9 continue + err = nfmpi_put_vars_$1_all(ncid, i, index, + + count, stride, + + value) + if (canConvert) then + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('range error: ', err) + end if + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +7 continue +5 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + call check_vars_$1(scratch) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed:', + + scratch) + end +])dnl + + +dnl since parallel-netcdf doesn't have varm type, we haven't completed the +dnl parallel-netcdf-ification of these routines +dnl TEST_NFMPI_PUT_VARM(TYPE) +dnl +define([TEST_NFMPI_PUT_VARM],dnl +[dnl + subroutine test_nfmpi_put_varm_$1() + implicit none +#include "tests.inc" + integer ncid + integer d + integer i + integer j + integer k + integer m + integer err + integer nels + integer nslabs + integer nstarts !/* number of different starts */ + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET index2(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + NFMPI_OFFSET count(MAX_RANK) + NFMPI_OFFSET sstride(MAX_RANK) + NFMPI_OFFSET stride(MAX_RANK) + NFMPI_OFFSET imap(MAX_RANK) + logical canConvert !/* Both text or both numeric */ + logical allInExtRange !/* all values within external range? */ + DATATYPE($1) value(MAX_NELS) + doubleprecision val + integer ud_shift + + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) + + stop 'assert(var_rank(i) .le. MAX_RANK)' + if (.not.(var_nels(i) .le. MAX_NELS)) + + stop 'assert(var_nels(i) .le. MAX_NELS)' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 + stride(j) = 1 + imap(j) = 1 +2 continue + err = nfmpi_put_varm_$1_all(BAD_ID, i, start, + + edge, stride, imap, + + value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_varm_$1_all(ncid, BAD_VARID, start, + + edge, stride, + + imap, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + if (var_dimid(j,i) .ne. RECDIM) then !/* skip record dim */ + start(j) = var_shape(j,i) + 1 + err = nfmpi_put_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad start: ', err) + endif + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_put_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + endif + edge(j) = 1 + stride(j) = 0 + err = nfmpi_put_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_ESTRIDE) + + call errore('bad stride: ', err) + endif + stride(j) = 1 + end if +3 continue + !/* Choose a random point dividing each dim into 2 parts */ + !/* Put 2^rank (nslabs) slabs so defined */ + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue + !/* bits of k determine whether to put lower or upper part of dim */ + !/* choose random stride from 1 to edge */ + do 5, k = 1, nslabs + nstarts = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + if (edge(j) .gt. 0) then + stride(j) = 1+roll(edge(j)) + else + stride(j) = 1 + end if + sstride(j) = stride(j) + nstarts = nstarts * stride(j) +6 continue + do 7, m = 1, nstarts + err = index2indexes(m, var_rank(i), sstride, index) + if (err .ne. 0) + + call error('error in index2indexes') + nels = 1 + do 8, j = 1, var_rank(i) + count(j) = 1 + (edge(j) - index(j)) / stride(j) + nels = nels * count(j) + index(j) = index(j) + start(j) - 1 +8 continue + !/* Random choice of forward or backward */ +C/* TODO +C if ( roll(2) ) then +C do 9, j = 1, var_rank(i) +C index(j) = index(j) + +C + (count(j) - 1) * stride(j) +C stride(j) = -stride(j) +C9 continue +C end if +C*/ + if (var_rank(i) .gt. 0) then + imap(1) = 1 + do 10, j = 2, var_rank(i) + imap(j) = imap(j-1) * count(j-1) +10 continue + end if + allInExtRange = .true. + do 11 j = 1, nels + err = index2indexes(j, var_rank(i), count, + + index2) + if (err .ne. 0) + + call error('error in index2indexes') + do 12, d = 1, var_rank(i) + index2(d) = index(d) + + + (index2(d)-1) * stride(d) +12 continue + value(j) = MAKE_TYPE($1, hash_$1(var_type(i), + + var_rank(i), + + index2, NFT_ITYPE($1))) + val = ARITH($1, value(j)) + allInExtRange = allInExtRange .and. + + inRange3(val, var_type(i), + + NFT_ITYPE($1)) +11 continue + err = nfmpi_put_varm_$1_all(ncid,i,index,count, + + stride,imap, + + value) + if (canConvert) then + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('range error: ', err) + end if + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +7 continue +5 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + call check_vars_$1(scratch) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed:', + + scratch) + end +])dnl + + +dnl TEST_NFMPI_PUT_ATT(TYPE) numeric only +dnl +define([TEST_NFMPI_PUT_ATT],dnl +[dnl + subroutine test_nfmpi_put_att_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer k + NFMPI_OFFSET ndx(1) + integer err + DATATYPE($1) value(MAX_NELS) + logical allInExtRange !/* all values within external range? */ + doubleprecision val + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + + do 1, i = 0, NVARS + do 2, j = 1, NATTS(i) + if (.not.(ATT_TYPE(j,i) .eq. NF_CHAR)) then + if (.not.((ATT_LEN(j,i) .le. MAX_NELS))) + + stop 'assert(ATT_LEN(j,i) .le. MAX_NELS)' + err = nfmpi_put_att_$1(BAD_ID, i, + + ATT_NAME(j,i), + + ATT_TYPE(j,i), + + ATT_LEN(j,i), value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_att_$1(ncid, BAD_VARID, + + ATT_NAME(j,i), + + ATT_TYPE(j,i), ATT_LEN(j,i), value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_put_att_$1(ncid, i, + + ATT_NAME(j,i), BAD_TYPE, + + ATT_LEN(j,i), value) + if (err .ne. NF_EBADTYPE) + + call errore('bad type: ', err) + allInExtRange = .true. + do 3, k = 1, ATT_LEN(j,i) + ndx(1) = k + value(k) = hash_$1(ATT_TYPE(j,i), -1, ndx, + + NFT_ITYPE($1)) + val = ARITH($1, value(k)) + allInExtRange = allInExtRange .and. + + inRange3(val, ATT_TYPE(j,i), + + NFT_ITYPE($1)) +3 continue + err = nfmpi_put_att_$1(ncid, i, ATT_NAME(j,i), + + ATT_TYPE(j,i), ATT_LEN(j,i), + + value) + if (allInExtRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('range error: ', err) + end if + end if +2 continue +1 continue + + call check_atts_$1(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed:', + + scratch) + end +])dnl + +divert(0)dnl +dnl If you see this line, you can ignore the next one. +C Do not edit this file. It is produced from the corresponding .m4 source */ + +C******************************************************************** +C Copyright 1996, UCAR/Unidata +C See netcdf/COPYRIGHT file for copying and redistribution conditions. +C $Id$ +C******************************************************************** + +HASH(text) +#ifdef NF_INT1_T +HASH(int1) +#endif +#ifdef NF_INT2_T +HASH(int2) +#endif +HASH(int) +HASH(real) +HASH(double) + +CHECK_VARS(text) +#ifdef NF_INT1_T +CHECK_VARS(int1) +#endif +#ifdef NF_INT2_T +CHECK_VARS(int2) +#endif +CHECK_VARS(int) +CHECK_VARS(real) +CHECK_VARS(double) + +CHECK_ATTS(text) +#ifdef NF_INT1_T +CHECK_ATTS(int1) +#endif +#ifdef NF_INT2_T +CHECK_ATTS(int2) +#endif +CHECK_ATTS(int) +CHECK_ATTS(real) +CHECK_ATTS(double) + +TEST_NFMPI_PUT_VAR1(text) +#ifdef NF_INT1_T +TEST_NFMPI_PUT_VAR1(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_VAR1(int2) +#endif +TEST_NFMPI_PUT_VAR1(int) +TEST_NFMPI_PUT_VAR1(real) +TEST_NFMPI_PUT_VAR1(double) + +TEST_NFMPI_PUT_VAR(text) +#ifdef NF_INT1_T +TEST_NFMPI_PUT_VAR(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_VAR(int2) +#endif +TEST_NFMPI_PUT_VAR(int) +TEST_NFMPI_PUT_VAR(real) +TEST_NFMPI_PUT_VAR(double) + +TEST_NFMPI_PUT_VARA(text) +#ifdef NF_INT1_T +TEST_NFMPI_PUT_VARA(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_VARA(int2) +#endif +TEST_NFMPI_PUT_VARA(int) +TEST_NFMPI_PUT_VARA(real) +TEST_NFMPI_PUT_VARA(double) + +TEST_NFMPI_PUT_VARS(text) +#ifdef NF_INT1_T +TEST_NFMPI_PUT_VARS(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_VARS(int2) +#endif +TEST_NFMPI_PUT_VARS(int) +TEST_NFMPI_PUT_VARS(real) +TEST_NFMPI_PUT_VARS(double) + +TEST_NFMPI_PUT_VARM(text) +#ifdef NF_INT1_T +TEST_NFMPI_PUT_VARM(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_VARM(int2) +#endif +TEST_NFMPI_PUT_VARM(int) +TEST_NFMPI_PUT_VARM(real) +TEST_NFMPI_PUT_VARM(double) + + subroutine test_nfmpi_put_att_text() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + NFMPI_OFFSET k + integer err + character value(MAX_NELS) + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + + do 1, i = 0, NVARS + do 2, j = 1, NATTS(i) + if (ATT_TYPE(j,i) .eq. NF_CHAR) then + if (.not.(ATT_LEN(j,i) .le. MAX_NELS)) + + stop 'assert(ATT_LEN(j,i) .le. MAX_NELS)' + err = nfmpi_put_att_text(BAD_ID, i, + + ATT_NAME(j,i), ATT_LEN(j,i), value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_put_att_text(ncid, BAD_VARID, + + ATT_NAME(j,i), + + ATT_LEN(j,i), value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, k = 1, ATT_LEN(j,i) + value(k) = char(int(hash(ATT_TYPE(j,i), -1, k))) +3 continue + err = nfmpi_put_att_text(ncid, i, ATT_NAME(j,i), + + ATT_LEN(j,i), value) + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + end if +2 continue +1 continue + + call check_atts_text(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed:', + + scratch) + end + +#ifdef NF_INT1_T +TEST_NFMPI_PUT_ATT(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_PUT_ATT(int2) +#endif +TEST_NFMPI_PUT_ATT(int) +TEST_NFMPI_PUT_ATT(real) +TEST_NFMPI_PUT_ATT(double) Index: /tags/v1-0-3/test/nf_test/tests.inc =================================================================== --- /tags/v1-0-3/test/nf_test/tests.inc (revision 424) +++ /tags/v1-0-3/test/nf_test/tests.inc (revision 424) @@ -0,0 +1,236 @@ +!/********************************************************************* +! * Copyright 1996, UCAR/Unidata +! * See netcdf/COPYRIGHT file for copying and redistribution conditions. +! * $Id$ +! *********************************************************************/ +!!!! +! Do not tabify this unless you like hitting the 72 char limit !!! +!!! +#ifndef UD_TESTS_INC +#define UD_TESTS_INC + + +!/* The following prevents non-FORTRAN code from appearing in the output. */ +#if defined(__osf__) +# undef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif + +#define NO_NETCDF_2 1 + +#include "../../src/libf/nfconfig.inc" + +!/* Parameters of test data */ + +#ifdef NF_INT1_T +# define NF_B 1 +#else +# define NF_B 0 +#endif +#ifdef NF_INT2_T +# define NF_S 1 +#else +# define NF_S 0 +#endif +! Total number of FORTRAN types: +#define NUM_FORTRAN_TYPES (3 + NF_S + NF_B) +#undef NF_B +#undef NF_S + +#define NTYPES 6 +#define NDIMS 5 +#define NVARS 136 +#define NRECS 2 +#define NGATTS NTYPES +#define RECDIM 1 +#define MAX_RANK 3 +#define MAX_NELS 64 +#define MAX_DIM_LEN 4 +#define MAX_NATTS 3 + + +!/* +! * Limits of external types (based on those in ncx.h): +! */ +#define X_CHAR_MIN 0 +#define X_CHAR_MAX 127 +#define X_INT1_MIN (-128) +#define X_INT1_MAX 127 +#define X_INT2_MIN (-32768) +#define X_INT2_MAX 32767 +#define X_INT_MIN (-2147483647-1) +#define X_INT_MAX 2147483647 +#if 0 +#define X_REAL_MAX 3.4028234663852886e+38 +#else +#define X_REAL_MAX 3.4028234663852886e+37 +#endif +#define X_REAL_MIN (-X_FLOAT_MAX) +#if 0 +#define X_DOUBLE_MAX 1.7976931348623157E+308 +#else +#define X_DOUBLE_MAX 1.7976931348623157D+200 +#endif +#define X_DOUBLE_MIN (-X_DOUBLE_MAX) + +#define X_BYTE_MIN X_INT1_MIN +#define X_BYTE_MAX X_INT1_MAX +#define X_SHORT_MIN X_INT2_MIN +#define X_SHORT_MAX X_INT2_MAX +#define X_FLOAT_MIN X_REAL_MIN +#define X_FLOAT_MAX X_REAL_MAX + + +!/* +! * Examples of invalid argument values: +! */ +#define BAD_ID -1 +#define BAD_DIMID -1 +#define BAD_VARID -2 +#define BAD_ATTNUM -1 +#define BAD_TYPE 0 +#define BAD_FILLMODE -1 +#define BAD_NAME 'a/b' + + +!/* +! * Internal data types: +! */ +#define NFT_UNSPECIFIED 0 +#define NFT_TEXT 16 +#define NFT_CHAR NFT_TEXT +#define NFT_INT1 17 +#define NFT_INT2 18 +#define NFT_INT 20 +#define NFT_REAL 36 +#define NFT_DOUBLE 40 + + +!/* +! * Define a macro for trimming trailing blanks from character variables. +! */ +#define TRIM(string) string(1:len_trim(string)) + + +! +! FORTRAN GETARG() subroutine: +! +#ifdef __hpux +# define getarg getarg_ +#endif + + +#endif /* UD_TESTS_INC */ + +#include "mpif.h" +#include "pnetcdf.inc" + + +! /* Global variables - filenames */ + + CHARACTER*80 testfile !/* netCDF read-only test data */ + CHARACTER*80 scratch !/* netCDF test file for writing */ + +! /* Global variables - command-line arguments */ + + LOGICAL CREATE_FILE + LOGICAL READONLY + LOGICAL VERBOSE + INTEGER NFAILS + INTEGER MAX_NMPT !/* max num messages per test */ + +! /* Global variables - test data */ + + CHARACTER*2 DIM_NAME(NDIMS) + NFMPI_OFFSET DIM_LEN(NDIMS) + CHARACTER*(2+MAX_RANK) VAR_NAME(NVARS) + INTEGER VAR_TYPE(NVARS) + INTEGER VAR_RANK(NVARS) + INTEGER VAR_DIMID(MAX_RANK,NVARS) + NFMPI_OFFSET VAR_SHAPE(MAX_RANK,NVARS) + INTEGER VAR_NELS(NVARS) + INTEGER VAR_NATTS(NVARS) + CHARACTER*2 ATTNAME(MAX_NATTS,NVARS) + CHARACTER*2 GATT_NAME(NGATTS) + INTEGER ATTTYPE(NGATTS,NVARS) + INTEGER GATT_TYPE(NGATTS) + INTEGER ATTLEN(MAX_NATTS,NVARS) + NFMPI_OFFSET GATT_LEN(NGATTS) + +! /* Miscellaneous global variables: */ + CHARACTER*80 PROGNAME !/* name of the program */ + INTEGER COMM !/* MPI communicator */ + + INTEGER NFAILSTOTAL + +! /* Common blocks for global variables: */ + +!/* MPI_OFFSET */ + COMMON /OFFSETCOM/ DIM_LEN, VAR_SHAPE, GATT_LEN + + COMMON /MPICOM/ COMM + COMMON /LOGCOM/ CREATE_FILE, + * READONLY, !/* don't change files */ + * VERBOSE !/* print details of tests */ + + COMMON /TXTCOM/ TESTFILE, + * SCRATCH, + * DIM_NAME, + * VAR_NAME, + * ATTNAME, + * GATT_NAME, + * PROGNAME + + COMMON /INTCOM/ NFAILS, !/* number of failures in + * ! * specific test */ + * VAR_TYPE, + * VAR_RANK, + * VAR_DIMID, + * VAR_NELS, + * VAR_NATTS, + * ATTTYPE, + * GATT_TYPE, + * ATTLEN, + * MAX_NMPT, + * NFAILSTOTAL + + +! /* Functions for accessing attribute test data */ +! /* varid is -1 for NC_GLOBAL so can do global atts in same loop */ + +!/* EXTERNAL ATT_NAME */ + + INTEGER VARID + INTEGER NATTS + CHARACTER*2 ATT_NAME + INTEGER ATT_TYPE + NFMPI_OFFSET ATT_LEN + + + LOGICAL INRANGE + LOGICAL INRANGE_UCHAR + LOGICAL INRANGE_FLOAT + + LOGICAL INRANGE3 + LOGICAL IN_INTERNAL_RANGE + LOGICAL EQUAL + LOGICAL INT_VEC_EQ + INTEGER ROLL + INTEGER INDEX2INDEXES + INTEGER INDEX2NCINDEXES + INTEGER INDEXES2INDEX + INTEGER NC2DBL + INTEGER DBL2NC + INTEGER LEN_TRIM + DOUBLEPRECISION HASH + DOUBLEPRECISION HASH4 + DOUBLEPRECISION HASH_TEXT + DOUBLEPRECISION HASH_INT1 + DOUBLEPRECISION HASH_INT2 + DOUBLEPRECISION HASH_INT + DOUBLEPRECISION HASH_REAL + DOUBLEPRECISION HASH_DOUBLE + DOUBLEPRECISION INTERNAL_MIN + DOUBLEPRECISION INTERNAL_MAX + DOUBLEPRECISION EXTERNAL_MIN + DOUBLEPRECISION EXTERNAL_MAX Index: /tags/v1-0-3/test/nf_test/README =================================================================== --- /tags/v1-0-3/test/nf_test/README (revision 475) +++ /tags/v1-0-3/test/nf_test/README (revision 475) @@ -0,0 +1,9 @@ +This test is ported from Unidata netCDF-3.5 to test the functionality +of the PnetCDF API Fortran interface particularly on a single processor. + +The typical way to run the test includes two steps: + + (1) create test.nc by " ./nf_test -c" + (2) run the test by " ./nf_test -v" + + Index: /tags/v1-0-3/test/nf_test/test_get.m4 =================================================================== --- /tags/v1-0-3/test/nf_test/test_get.m4 (revision 424) +++ /tags/v1-0-3/test/nf_test/test_get.m4 (revision 424) @@ -0,0 +1,1091 @@ +divert(-1) + +dnl This is m4 source. +dnl Process using m4 to produce FORTRAN language file. + +changequote([,]) + +undefine([index])dnl + +dnl Macros + +dnl Upcase(str) +dnl +define([Upcase],[dnl +translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)]) + +dnl NFT_ITYPE(type) +dnl +define([NFT_ITYPE], [NFT_[]Upcase($1)]) + +dnl ARITH(itype, value) +dnl +define([ARITH], [ifelse($1, text, ichar($2), $2)]) + +dnl DATATYPE(funf_suffix) +dnl +define([DATATYPE], [dnl +ifelse($1, text, character, +ifelse($1, int1, NF_INT1_T, +ifelse($1, int2, NF_INT2_T, +ifelse($1, int, integer, +ifelse($1, real, real, +ifelse($1, double, doubleprecision)[]dnl +)[]dnl +)[]dnl +)[]dnl +)[]dnl +)[]dnl +]) + +dnl TEST_NFMPI_GET_VAR1(TYPE) +dnl +define([TEST_NFMPI_GET_VAR1],[dnl + subroutine test_nfmpi_get_var1_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + integer nok + NFMPI_OFFSET index(MAX_RANK) + doubleprecision expect + logical canConvert + DATATYPE($1) value + doubleprecision val + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_begin_indep_data(ncid) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + do 2, j = 1, var_rank(i) + index(j) = 1 +2 continue + err = nfmpi_get_var1_$1(BAD_ID, i, index, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_var1_$1(ncid, BAD_VARID, + + index, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + index(j) = var_shape(j,i) + 1 + err = nfmpi_get_var1_$1(ncid, i, index, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad index: ', err) + endif + index(j) = 1 +3 continue + do 4, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes 1') + expect = hash4( var_type(i), var_rank(i), index, + + NFT_ITYPE($1) ) + err = nfmpi_get_var1_$1(ncid, i, index, + + value) + if (canConvert) then + if (inRange3(expect,var_type(i), + + NFT_ITYPE($1))) then + if (in_internal_range(NFT_ITYPE($1), + + expect)) then + if (err .ne. 0) then + call errore('nfmpi_get_var: ', err) + else + val = ARITH($1, value) + if (.not. equal(val, expect, + + var_type(i), + + NFT_ITYPE($1))) then + call errord('unexpected: ', val) + else + nok = nok + 1 + end if + end if + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', err) + end if + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +4 continue +1 continue + err = nfmpi_end_indep_data(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +]) + +dnl TEST_NFMPI_GET_VAR(TYPE) +dnl +define([TEST_NFMPI_GET_VAR],[dnl + subroutine test_nfmpi_get_var_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + logical allInExtRange + logical allInIntRange + integer nels + integer nok + NFMPI_OFFSET index(MAX_RANK) + doubleprecision expect(MAX_NELS) + logical canConvert + DATATYPE($1) value(MAX_NELS) + doubleprecision val + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + err = nfmpi_get_var_$1_all(BAD_ID, i, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_var_$1_all(ncid, BAD_VARID, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + nels = 1 + do 3, j = 1, var_rank(i) + nels = nels * var_shape(j,i) +3 continue + allInExtRange = .true. + allInIntRange = .true. + do 4, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes 1') + expect(j) = hash4( var_type(i), var_rank(i), index, + + NFT_ITYPE($1) ) + if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then + allInIntRange = allInIntRange .and. + + in_internal_range(NFT_ITYPE($1), expect(j)) + else + allInExtRange = .false. + end if +4 continue + err = nfmpi_get_var_$1_all(ncid, i, value) + if (canConvert) then + if (allInExtRange) then + if (allInIntRange) then + if (err .ne. 0) + + call errore('nfmpi_get_var: ', err) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + endif + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('Range error: ', err) + endif + do 5, j = 1, var_nels(i) + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1)) .and. + + in_internal_range(NFT_ITYPE($1), + + expect(j))) then + val = ARITH($1, value(j)) + if (.not. equal(val, expect(j), + + var_type(i), + + NFT_ITYPE($1))) then + call errord('unexpected: ', val) + else + nok = nok + 1 + end if + endif +5 continue + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +]) + + +dnl TEST_NFMPI_GET_VARA(TYPE) +dnl +define([TEST_NFMPI_GET_VARA],[dnl + subroutine test_nfmpi_get_vara_$1() + implicit none +#include "tests.inc" + integer ncid + integer d + integer i + integer j + integer k + integer err + logical allInExtRange + logical allInIntRange + integer nels + integer nslabs + integer nok + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + logical canConvert + DATATYPE($1) value(MAX_NELS) + doubleprecision expect(MAX_NELS) + doubleprecision val + integer ud_shift + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert' + if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 +2 continue + err = nfmpi_get_vara_$1_all(BAD_ID, i, start, + + edge, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_vara_$1_all(ncid, BAD_VARID, start, + + edge, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + start(j) = var_shape(j,i) + 1 + err = nfmpi_get_vara_$1_all(ncid, i, start, + + edge, value) + if (canConvert .and. err .ne. NF_EINVALCOORDS) + + call errore('bad index: ', err) + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_get_vara_$1_all(ncid, i, start, + + edge, value) + if (canConvert .and. err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + edge(j) = 1 +3 continue + +C /* Check non-scalars for correct error returned even when */ +C /* there is nothing to get (edge(j).eq.0) */ + if (var_rank(i) .gt. 0) then + do 10, j = 1, var_rank(i) + edge(j) = 0 +10 continue + err = nfmpi_get_vara_$1_all(BAD_ID, i, start, + + edge, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_vara_$1_all(ncid, BAD_VARID, + + start, edge, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 11, j = 1, var_rank(i) + if (var_dimid(j,i) .gt. 1) then !/* skip record dim */ + start(j) = var_shape(j,i) + 1 + edge(j) = 1 !/* By Jianwei, fix NF_EINVALCOORDS bug */ + err = nfmpi_get_vara_$1_all(ncid, i, + + start, edge, value) + if (canConvert .and. err .ne. NF_EINVALCOORDS) + + call errore('bad start: ', err) + start(j) = 1 + edge(j) = 0 !/* By Jianwei, restore original value */ + endif +11 continue + err = nfmpi_get_vara_$1_all(ncid, i, start, + + edge, value) + if (canConvert) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + endif + do 12, j = 1, var_rank(i) + edge(j) = 1 +12 continue + endif + +C Choose a random point dividing each dim into 2 parts +C get 2^rank (nslabs) slabs so defined + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue +C bits of k determine whether to get lower or upper part of dim + do 5, k = 1, nslabs + nels = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + nels = nels * edge(j) +6 continue + allInIntRange = .true. + allInExtRange = .true. + do 7, j = 1, nels + err = index2indexes(j, var_rank(i), edge, index) + if (err .ne. 0) + + call error('error in index2indexes 1') + do 8, d = 1, var_rank(i) + index(d) = index(d) + start(d) - 1 +8 continue + expect(j) = hash4(var_type(i), var_rank(i), index, + + NFT_ITYPE($1)) + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1))) then + allInIntRange = + + allInIntRange .and. + + in_internal_range(NFT_ITYPE($1), expect(j)) + else + allInExtRange = .false. + end if +7 continue + err = nfmpi_get_vara_$1_all(ncid, i, start, + + edge, value) + if (canConvert) then + if (allInExtRange) then + if (allInIntRange) then + if (err .ne. 0) + + call errore('nfmpi_get_vara_$1:', + + err) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', err) + end if + do 9, j = 1, nels + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1)) .and. + + in_internal_range(NFT_ITYPE($1), expect(j))) + + then + val = ARITH($1, value(j)) + if (.not.equal(val,expect(j), + + var_type(i),NFT_ITYPE($1))) + + then + call error( + + 'value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: ', i) + call errorc('var_name: ', + + var_name(i)) + call errori('element number: %d ', + + j) + call errord('expect: ', expect(j)) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if +9 continue + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +5 continue +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errorc('nfmpi_close: ', nfmpi_strerror(err)) + call print_nok(nok) + end +])dnl + + +dnl TEST_NFMPI_GET_VARS(TYPE) +dnl +define([TEST_NFMPI_GET_VARS],dnl +[dnl + subroutine test_nfmpi_get_vars_$1() + implicit none +#include "tests.inc" + integer ncid + integer d + integer i + integer j + integer k + integer m + integer err + logical allInExtRange + logical allInIntRange + integer nels + integer nslabs + integer nstarts + integer nok + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET index2(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + NFMPI_OFFSET count(MAX_RANK) + NFMPI_OFFSET sstride(MAX_RANK) + NFMPI_OFFSET stride(MAX_RANK) + logical canConvert + DATATYPE($1) value(MAX_NELS) + doubleprecision expect(MAX_NELS) + doubleprecision val + integer ud_shift + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert' + if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 + stride(j) = 1 +2 continue + err = nfmpi_get_vars_$1_all(BAD_ID, i, start, + + edge, stride, value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_vars_$1_all(ncid, BAD_VARID, + + start, edge, stride, + + value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + start(j) = var_shape(j,i) + 1 + err = nfmpi_get_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad index: ', err) + endif + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_get_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + endif + edge(j) = 1 + stride(j) = 0 + err = nfmpi_get_vars_$1_all(ncid, i, start, + + edge, stride, + + value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_ESTRIDE) + + call errore('bad stride: ', err) + endif + stride(j) = 1 +3 continue +C Choose a random point dividing each dim into 2 parts +C get 2^rank (nslabs) slabs so defined + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue +C bits of k determine whether to get lower or upper part of dim +C choose random stride from 1 to edge + do 5, k = 1, nslabs + nstarts = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + if (edge(j) .gt. 0) then + sstride(j) = 1 + roll(edge(j)) + else + sstride(j) = 1 + end if + nstarts = nstarts * stride(j) +6 continue + do 7, m = 1, nstarts + err = index2indexes(m, var_rank(i), sstride, + + index) + if (err .ne. 0) + + call error('error in index2indexes') + nels = 1 + do 8, j = 1, var_rank(i) + count(j) = 1 + (edge(j) - index(j)) / + + stride(j) + nels = nels * count(j) + index(j) = index(j) + start(j) - 1 +8 continue +C Random choice of forward or backward +C /* TODO +C if ( roll(2) ) then +C for (j = 0 j < var_rank(i) j++) { +C index(j) += (count(j) - 1) * stride(j) +C stride(j) = -stride(j) +C } +C end if +C */ + allInIntRange = .true. + allInExtRange = .true. + do 9, j = 1, nels + err = index2indexes(j, var_rank(i), count, + + index2) + if (err .ne. 0) + + call error('error in index2indexes() 1') + do 10, d = 1, var_rank(i) + index2(d) = index(d) + (index2(d)-1) * + + stride(d) +10 continue + expect(j) = hash4(var_type(i), var_rank(i), + + index2, NFT_ITYPE($1)) + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1))) then + allInIntRange = + + allInIntRange .and. + + in_internal_range(NFT_ITYPE($1), + + expect(j)) + else + allInExtRange = .false. + end if +9 continue + err = nfmpi_get_vars_$1_all(ncid, i, index, + + count, stride, + + value) + if (canConvert) then + if (allInExtRange) then + if (allInIntRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', err) + end if + do 11, j = 1, nels + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1)) .and. + + in_internal_range(NFT_ITYPE($1), + + expect(j))) then + val = ARITH($1, value(j)) + if (.not.equal(val, expect(j), + + var_type(i), NFT_ITYPE($1))) then + call error( + + 'value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: ', i) + call errorc('var_name: ', + + var_name(i)) + call errori('element number: ', + + j) + call errord('expect: ', + + expect(j)) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if +11 continue + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +7 continue +5 continue + +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +])dnl + + +dnl parallel-netcdf doesn't implement varm yet, so we haven't +dnl parallel-netcdfified this all the way yet. +dnl TEST_NFMPI_GET_VARM(TYPE) +dnl +define([TEST_NFMPI_GET_VARM],dnl +[dnl + subroutine test_nfmpi_get_varm_$1() + implicit none +#include "tests.inc" + integer ncid + integer d + integer i + integer j + integer k + integer m + integer err + logical allInExtRange + logical allInIntRange + integer nels + integer nslabs + integer nstarts + integer nok + NFMPI_OFFSET start(MAX_RANK) + NFMPI_OFFSET edge(MAX_RANK) + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET index2(MAX_RANK) + NFMPI_OFFSET mid(MAX_RANK) + NFMPI_OFFSET count(MAX_RANK) + NFMPI_OFFSET sstride(MAX_RANK) + NFMPI_OFFSET stride(MAX_RANK) + NFMPI_OFFSET imap(MAX_RANK) + logical canConvert + DATATYPE($1) value(MAX_NELS) + doubleprecision expect(MAX_NELS) + doubleprecision val + integer ud_shift + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + canConvert = (var_type(i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion' + if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion' + do 2, j = 1, var_rank(i) + start(j) = 1 + edge(j) = 1 + stride(j) = 1 + imap(j) = 1 +2 continue + err = nfmpi_get_varm_$1_all(BAD_ID, i, start, edge, + + stride, imap, + + value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_varm_$1_all(ncid, BAD_VARID, start, + + edge, stride, + + imap, value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + do 3, j = 1, var_rank(i) + start(j) = var_shape(j,i) + 1 + err = nfmpi_get_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EINVALCOORDS) + + call errore('bad index: ', err) + endif + start(j) = 1 + edge(j) = var_shape(j,i) + 1 + err = nfmpi_get_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_EEDGE) + + call errore('bad edge: ', err) + endif + edge(j) = 1 + stride(j) = 0 + err = nfmpi_get_varm_$1_all(ncid, i, start, + + edge, stride, + + imap, value) + if (.not. canConvert) then + if (err .ne. NF_ECHAR) + + call errore('conversion: ', err) + else + if (err .ne. NF_ESTRIDE) + + call errore('bad stride: ', err) + endif + stride(j) = 1 +3 continue +C Choose a random point dividing each dim into 2 parts +C get 2^rank (nslabs) slabs so defined + nslabs = 1 + do 4, j = 1, var_rank(i) + mid(j) = roll( var_shape(j,i) ) + nslabs = nslabs * 2 +4 continue +C /* bits of k determine whether to get lower or upper part +C * of dim +C * choose random stride from 1 to edge */ + do 5, k = 1, nslabs + nstarts = 1 + do 6, j = 1, var_rank(i) + if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then + start(j) = 1 + edge(j) = mid(j) + else + start(j) = 1 + mid(j) + edge(j) = var_shape(j,i) - mid(j) + end if + if (edge(j) .gt. 0) then + stride(j) = 1+roll(edge(j)) + else + stride(j) = 1 + end if + sstride(j) = stride(j) + nstarts = nstarts * stride(j) +6 continue + do 7, m = 1, nstarts + err = index2indexes(m, var_rank(i), sstride, index) + if (err .ne. 0) + + call error('error in index2indexes') + nels = 1 + do 8, j = 1, var_rank(i) + count(j) = 1 + (edge(j) - index(j)) / + + stride(j) + nels = nels * count(j) + index(j) = index(j) + start(j) - 1 +8 continue +C Random choice of forward or backward +C /* TODO +C if ( roll(2) ) then +C for (j = 0 j < var_rank(i) j++) { +C index(j) += (count(j) - 1) * stride(j) +C stride(j) = -stride(j) +C } +C end if +C */ + if (var_rank(i) .gt. 0) then + imap(1) = 1 + do 9, j = 2, var_rank(i) + imap(j) = imap(j-1) * count(j-1) +9 continue + end if + allInIntRange = .true. + allInExtRange = .true. + do 10, j = 1, nels + err = index2indexes(j, var_rank(i), count, + + index2) + if (err .ne. 0) + + call error('error in index2indexes 1') + do 11, d = 1, var_rank(i) + index2(d) = index(d) + (index2(d)-1) * + + stride(d) +11 continue + expect(j) = hash4(var_type(i), var_rank(i), + + index2, NFT_ITYPE($1)) + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1))) then + allInIntRange = + + allInIntRange .and. + + in_internal_range(NFT_ITYPE($1), + + expect(j)) + else + allInExtRange = .false. + end if +10 continue + err = nfmpi_get_varm_$1_all(ncid,i,index,count, + + stride,imap, + + value) + if (canConvert) then + if (allInExtRange) then + if (allInIntRange) then + if (err .ne. 0) + + call error(nfmpi_strerror(err)) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', err) + end if + do 12, j = 1, nels + if (inRange3(expect(j),var_type(i), + + NFT_ITYPE($1)) .and. + + in_internal_range(NFT_ITYPE($1), + + expect(j))) then + val = ARITH($1, value(j)) + if (.not.equal(val, expect(j), + + var_type(i), + + NFT_ITYPE($1))) then + call error( + + 'value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: ', i) + call errorc('var_name: ', + + var_name(i)) + call errori('element number: ', + + j) + call errord('expect: ', + + expect(j)) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if +12 continue + else + if (nels .gt. 0 .and. err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +7 continue +5 continue +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +])dnl + + +dnl TEST_NFMPI_GET_ATT(TYPE) +dnl +define([TEST_NFMPI_GET_ATT],dnl +[dnl + subroutine test_nfmpi_get_att_$1() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer k + integer err + NFMPI_OFFSET ndx(1) + logical allInExtRange + logical allInIntRange + logical canConvert + DATATYPE($1) value(MAX_NELS) + doubleprecision expect(MAX_NELS) + integer nok + doubleprecision val + + nok = 0 + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + do 2, j = 1, NATTS(i) + canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv. + + (NFT_ITYPE($1) .eq. NFT_TEXT) + err = nfmpi_get_att_$1(BAD_ID, i, + + ATT_NAME(j,i), + + value) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_get_att_$1(ncid, BAD_VARID, + + ATT_NAME(j,i), + + value) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_get_att_$1(ncid, i, + + 'noSuch', + + value) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute name: ', err) + allInIntRange = .true. + allInExtRange = .true. + do 3, k = 1, ATT_LEN(j,i) + ndx(1) = k + expect(k) = hash4(ATT_TYPE(j,i), -1, ndx, + + NFT_ITYPE($1)) + if (inRange3(expect(k),ATT_TYPE(j,i), + + NFT_ITYPE($1))) then + allInIntRange = + + allInIntRange .and. + + in_internal_range(NFT_ITYPE($1), expect(k)) + else + allInExtRange = .false. + end if +3 continue + err = nfmpi_get_att_$1(ncid, i, + + ATT_NAME(j,i), + + value) + if (canConvert .or. ATT_LEN(j,i) .eq. 0) then + if (allInExtRange) then + if (allInIntRange) then + if (err .ne. 0) + + call errore('nfmpi_get_att_$1: ', + + err) + else + if (err .ne. NF_ERANGE) + + call errore('Range error: ', err) + end if + else + if (err .ne. 0 .and. err .ne. NF_ERANGE) + + call errore('OK or Range error: ', + + err) + end if + do 4, k = 1, ATT_LEN(j,i) + if (inRange3(expect(k),ATT_TYPE(j,i), + + NFT_ITYPE($1)) .and. + + in_internal_range(NFT_ITYPE($1), + + expect(k))) then + val = ARITH($1, value(k)) + if (.not.equal(val, expect(k), + + ATT_TYPE(j,i), + + NFT_ITYPE($1)))then + call error( + + 'value read not that expected') + if (verbose) then + call error(' ') + call errori('varid: ', i) + call errorc('att_name: ', + + ATT_NAME(j,i)) + call errori('element number: ', k) + call errord('expect: ', expect(k)) + call errord('got: ', val) + end if + else + nok = nok + 1 + end if + end if +4 continue + else + if (err .ne. NF_ECHAR) + + call errore('wrong type: ', err) + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + call print_nok(nok) + end +])dnl + +divert(0)dnl +dnl If you see this line, you can ignore the next one. +C Do not edit this file. It is produced from the corresponding .m4 source */ + +C********************************************************************* +C Copyright 1996, UCAR/Unidata +C See netcdf/COPYRIGHT file for copying and redistribution conditions. +C $Id$ +C********************************************************************* + +TEST_NFMPI_GET_VAR1(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_VAR1(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_VAR1(int2) +#endif +TEST_NFMPI_GET_VAR1(int) +TEST_NFMPI_GET_VAR1(real) +TEST_NFMPI_GET_VAR1(double) + +TEST_NFMPI_GET_VAR(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_VAR(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_VAR(int2) +#endif +TEST_NFMPI_GET_VAR(int) +TEST_NFMPI_GET_VAR(real) +TEST_NFMPI_GET_VAR(double) + +TEST_NFMPI_GET_VARA(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_VARA(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_VARA(int2) +#endif +TEST_NFMPI_GET_VARA(int) +TEST_NFMPI_GET_VARA(real) +TEST_NFMPI_GET_VARA(double) + +TEST_NFMPI_GET_VARS(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_VARS(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_VARS(int2) +#endif +TEST_NFMPI_GET_VARS(int) +TEST_NFMPI_GET_VARS(real) +TEST_NFMPI_GET_VARS(double) + +TEST_NFMPI_GET_VARM(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_VARM(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_VARM(int2) +#endif +TEST_NFMPI_GET_VARM(int) +TEST_NFMPI_GET_VARM(real) +TEST_NFMPI_GET_VARM(double) + +TEST_NFMPI_GET_ATT(text) +#ifdef NF_INT1_T +TEST_NFMPI_GET_ATT(int1) +#endif +#ifdef NF_INT2_T +TEST_NFMPI_GET_ATT(int2) +#endif +TEST_NFMPI_GET_ATT(int) +TEST_NFMPI_GET_ATT(real) +TEST_NFMPI_GET_ATT(double) Index: /tags/v1-0-3/test/nf_test/test_write.F =================================================================== --- /tags/v1-0-3/test/nf_test/test_write.F (revision 559) +++ /tags/v1-0-3/test/nf_test/test_write.F (revision 559) @@ -0,0 +1,1509 @@ +C******************************************************************** +C Copyright 1996, UCAR/Unidata +C See netcdf/COPYRIGHT file for copying and redistribution conditions. +C $Id$ +C******************************************************************** + + +C Test nfmpi_create +C For mode in NF_NOCLOBBER, NF_CLOBBER do: +C create netcdf file 'scratch.nc' with no data, close it +C test that it can be opened, do nfmpi_inq to check nvars = 0, etc. +C Try again in NF_NOCLOBBER mode, check error return +C On exit, delete this file + subroutine test_nfmpi_create() + implicit none +#include "tests.inc" + + integer clobber !/* 0 for NF_NOCLOBBER, 1 for NF_CLOBBER */ + integer err + integer ncid + integer ndims !/* number of dimensions */ + integer nvars !/* number of variables */ + integer ngatts !/* number of global attributes */ + integer recdim !/* id of unlimited dimension */ + integer flags + + flags = NF_NOCLOBBER + do 1, clobber = 0, 1 + err = nfmpi_create(comm, scratch, flags, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + end if + err = nfmpi_close(ncid) + if (err .ne. 0) then + call errore('nfmpi_close: ', err) + end if + err = nfmpi_open(comm, scratch, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_open: ', err) + end if + err = nfmpi_inq(ncid, ndims, nvars, ngatts, recdim) + if (err .ne. 0) then + call errore('nfmpi_inq: ', err) + else if (ndims .ne. 0) then + call errori( + + 'nfmpi_inq: wrong number of dimensions returned, ', + + ndims) + else if (nvars .ne. 0) then + call errori( + + 'nfmpi_inq: wrong number of variables returned, ', + + nvars) + else if (ngatts .ne. 0) then + call errori( + + 'nfmpi_inq: wrong number of global atts returned, ', + + ngatts) + else if (recdim .ge. 1) then + call errori( + + 'nfmpi_inq: wrong record dimension ID returned, ', + + recdim) + end if + err = nfmpi_close(ncid) + if (err .ne. 0) then + call errore('nfmpi_close: ', err) + end if + + flags = NF_CLOBBER +1 continue + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. NF_EEXIST) then + call errore('attempt to overwrite file: ', err) + end if + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) then + call errori('delete of scratch file failed: ', err) + end if + end + + +C Test nfmpi_redef +C (In fact also tests nfmpi_enddef - called from test_nfmpi_enddef) +C BAD_ID +C attempt redef (error) & enddef on read-only file +C create file, define dims & vars. +C attempt put var (error) +C attempt redef (error) & enddef. +C put vars +C attempt def new dims (error) +C redef +C def new dims, vars. +C put atts +C enddef +C put vars +C close +C check file: vars & atts + subroutine test_nfmpi_redef() + implicit none +#include "tests.inc" + integer title_len + parameter (title_len = 9) + + integer ncid !/* netcdf id */ + integer dimid !/* dimension id */ + integer vid !/* variable id */ + integer err + character*(title_len) title + doubleprecision var + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + integer intlen + + title = 'Not funny' + +C /* BAD_ID tests */ + err = nfmpi_redef(BAD_ID) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_enddef(BAD_ID) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + +C /* read-only tests */ + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_redef(ncid) + if (err .ne. NF_EPERM) + + call errore('nfmpi_redef in NF_NOWRITE mode: ', err) + err = nfmpi_enddef(ncid) + if (err .ne. NF_ENOTINDEFINE) + + call errore('nfmpi_redef in NF_NOWRITE mode: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* tests using scratch file */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + err = nfmpi_inq_varid(ncid, 'd', vid) + if (err .ne. 0) + + call errore('nfmpi_inq_varid: ', err) + var = 1.0 + err = nfmpi_begin_indep_data(ncid) + err = nfmpi_put_var1_double(ncid, vid, 0, var) + if (err .ne. NF_EINDEFINE) + + call errore('nfmpi_put_var... in define mode: ', err) + err = nfmpi_end_indep_data(ncid) + err = nfmpi_redef(ncid) + if (err .ne. NF_EINDEFINE) + + call errore('nfmpi_redef in define mode: ', err) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + call put_vars(ncid) + length = 8 + err = nfmpi_def_dim(ncid, 'abc', length, dimid) + if (err .ne. NF_ENOTINDEFINE) + + call errore('nfmpi_def_dim in define mode: ', err) + err = nfmpi_redef(ncid) + if (err .ne. 0) + + call errore('nfmpi_redef: ', err) + length = 8 + err = nfmpi_def_dim(ncid, 'abc', length, dimid) + if (err .ne. 0) + + call errore('nfmpi_def_dim: ', err) + err = nfmpi_def_var(ncid, 'abc', NF_INT, 0, 0, vid) + if (err .ne. 0) + + call errore('nfmpi_def_var: ', err) + length = len(title) + err = nfmpi_put_att_text(ncid, NF_GLOBAL, 'title', length, + + title) + if (err .ne .0) + + call errore('nfmpi_put_att_text: ', err) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + var = 1.0 + err = nfmpi_begin_indep_data(ncid) + err = nfmpi_put_var1_double(ncid, vid, 0, var) + if (err .ne. 0) + + call errore('nfmpi_put_var1_double: ', err) + err = nfmpi_end_indep_data(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* check scratch file written as expected */ + call check_file(scratch) + err = nfmpi_open(comm, scratch, NF_NOWRITE, + & MPI_INFO_NULL, ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_dim(ncid, dimid, name, length) + if (err .ne. 0) + + call errore('nfmpi_inq_dim: ', err) + if (name .ne. "abc") + + call errori('Unexpected dim name in netCDF ', ncid) + if (length .ne. 8) then + intlen = length + call errori('Unexpected dim length: ', intlen) + end if + err = nfmpi_begin_indep_data(ncid) + err = nfmpi_get_var1_double(ncid, vid, 0, var) + if (err .ne. 0) + + call errore('nfmpi_get_var1_double: ', err) + if (var .ne. 1.0) + + call errori( + + 'nfmpi_get_var1_double: unexpected value in netCDF ' + + , ncid) + err = nfmpi_end_indep_data(ncid) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete failed for netCDF: ', err) + end + +C Test nfmpi_enddef +C Simply calls test_nfmpi_redef which tests both nfmpi_redef & nfmpi_enddef + + subroutine test_nfmpi_enddef() + implicit none +#include "tests.inc" + + call test_nfmpi_redef + end + + +C Test nfmpi_sync +C try with bad handle, check error +C try in define mode, check error +C try writing with one handle, reading with another on same netCDF + subroutine test_nfmpi_sync() + implicit none +#include "tests.inc" + + integer ncidw !/* netcdf id for writing */ + integer ncidr !/* netcdf id for reading */ + integer err + +C /* BAD_ID test */ + err = nfmpi_sync(BAD_ID) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + +C /* create scratch file & try nfmpi_sync in define mode */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncidw) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_sync(ncidw) + if (err .ne. NF_EINDEFINE) + + call errore('nfmpi_sync called in define mode: ', err) + +C /* write using same handle */ + call def_dims(ncidw) + call def_vars(ncidw) + call put_atts(ncidw) + err = nfmpi_enddef(ncidw) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + call put_vars(ncidw) + err = nfmpi_sync(ncidw) + if (err .ne. 0) + + call errore('nfmpi_sync of ncidw failed: ', err) + +C /* open another handle, nfmpi_sync, read (check) */ + err = nfmpi_open(comm, scratch, NF_NOWRITE, MPI_INFO_NULL, + + ncidr) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_sync(ncidr) + if (err .ne. 0) + + call errore('nfmpi_sync of ncidr failed: ', err) + call check_dims(ncidr) + call check_atts(ncidr) + call check_vars(ncidr) + +C /* close both handles */ + err = nfmpi_close(ncidr) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_close(ncidw) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + + +C Test nfmpi_abort +C try with bad handle, check error +C try in define mode before anything written, check that file was deleted +C try after nfmpi_enddef, nfmpi_redef, define new dims, vars, atts +C try after writing variable + subroutine test_nfmpi_abort() + implicit none +#include "tests.inc" + + integer ncid !/* netcdf id */ + integer err + integer ndims + integer nvars + integer ngatts + integer recdim + +C /* BAD_ID test */ + err = nfmpi_abort(BAD_ID) + if (err .ne. NF_EBADID) + + call errore('bad ncid: status = ', err) + +C /* create scratch file & try nfmpi_abort in define mode */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + err = nfmpi_abort(ncid) + if (err .ne. 0) + + call errore('nfmpi_abort of ncid failed: ', err) + err = nfmpi_close(ncid) !/* should already be closed */ + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) !/* should already be deleted */ + if (err .eq. 0) + + call errori('scratch file should not exist: ', err) + +C create scratch file +C do nfmpi_enddef & nfmpi_redef +C define new dims, vars, atts +C try nfmpi_abort: should restore previous state (no dims, vars, atts) + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + err = nfmpi_redef(ncid) + if (err .ne. 0) + + call errore('nfmpi_redef: ', err) + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + err = nfmpi_abort(ncid) + if (err .ne. 0) + + call errore('nfmpi_abort of ncid failed: ', err) + err = nfmpi_close(ncid) !/* should already be closed */ + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_open(comm, scratch, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq (ncid, ndims, nvars, ngatts, recdim) + if (err .ne. 0) + + call errore('nfmpi_inq: ', err) + if (ndims .ne. 0) + + call errori('ndims should be ', 0) + if (nvars .ne. 0) + + call errori('nvars should be ', 0) + if (ngatts .ne. 0) + + call errori('ngatts should be ', 0) + err = nfmpi_close (ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* try nfmpi_abort in data mode - should just close */ + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + call put_vars(ncid) + err = nfmpi_abort(ncid) + if (err .ne. 0) + + call errore('nfmpi_abort of ncid failed: ', err) + err = nfmpi_close(ncid) !/* should already be closed */ + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + call check_file(scratch) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + + +C Test nfmpi_def_dim +C try with bad netCDF handle, check error +C try in data mode, check error +C check that returned id is one more than previous id +C try adding same dimension twice, check error +C try with illegal sizes, check error +C make sure unlimited size works, shows up in nfmpi_inq_unlimdim +C try to define a second unlimited dimension, check error + subroutine test_nfmpi_def_dim() + implicit none +#include "tests.inc" + + integer ncid + integer err !/* status */ + integer i + integer dimid !/* dimension id */ + NFMPI_OFFSET length + +C /* BAD_ID test */ + length = 8 + err = nfmpi_def_dim(BAD_ID, 'abc', length, dimid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + +C /* data mode test */ + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + length = 8 + err = nfmpi_def_dim(ncid, 'abc', length, dimid) + if (err .ne. NF_ENOTINDEFINE) + + call errore('bad ncid: ', err) + +C /* define-mode tests: unlimited dim */ + err = nfmpi_redef(ncid) + if (err .ne. 0) + + call errore('nfmpi_redef: ', err) + length = NFMPI_UNLIMITED + err = nfmpi_def_dim(ncid, dim_name(1), length, dimid) + if (err .ne. 0) + + call errore('nfmpi_def_dim: ', err) + if (dimid .ne. 1) + + call errori('Unexpected dimid: ', dimid) + err = nfmpi_inq_unlimdim(ncid, dimid) + if (err .ne. 0) + + call errore('nfmpi_inq_unlimdim: ', err) + if (dimid .ne. RECDIM) + + call error('Unexpected recdim: ') + err = nfmpi_inq_dimlen(ncid, dimid, length) + if (length .ne. 0) + + call errori('Unexpected length: ', 0) + length = NFMPI_UNLIMITED + err = nfmpi_def_dim(ncid, 'abc', length, dimid) + if (err .ne. NF_EUNLIMIT) + + call errore('2nd unlimited dimension: ', err) + +C /* define-mode tests: remaining dims */ + do 1, i = 2, NDIMS + err = nfmpi_def_dim(ncid, dim_name(i-1), dim_len(i), + + dimid) + if (err .ne. NF_ENAMEINUSE) + + call errore('duplicate name: ', err) + err = nfmpi_def_dim(ncid, BAD_NAME, dim_len(i), dimid) + if (err .ne. NF_EBADNAME) + + call errore('bad name: ', err) + length = NFMPI_UNLIMITED - 1 + err = nfmpi_def_dim(ncid, dim_name(i), length, + + dimid) + if (err .ne. NF_EDIMSIZE) + + call errore('bad size: ', err) + err = nfmpi_def_dim(ncid, dim_name(i), + & dim_len(i), dimid) + if (err .ne. 0) + + call errore('nfmpi_def_dim: ', err) + if (dimid .ne. i) + + call errori('Unexpected dimid: ', 0) +1 continue + +C /* Following just to expand unlimited dim */ + call def_vars(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + call put_vars(ncid) + +C /* Check all dims */ + call check_dims(ncid) + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + + +C Test nfmpi_rename_dim +C try with bad netCDF handle, check error +C check that proper rename worked with nfmpi_inq_dim +C try renaming to existing dimension name, check error +C try with bad dimension handle, check error + subroutine test_nfmpi_rename_dim() + implicit none +#include "tests.inc" + + integer ncid + integer err !/* status */ + character*(NF_MAX_NAME) name + +C /* BAD_ID test */ + err = nfmpi_rename_dim(BAD_ID, 1, 'abc') + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + +C /* main tests */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + err = nfmpi_rename_dim(ncid, BAD_DIMID, 'abc') + if (err .ne. NF_EBADDIM) + + call errore('bad dimid: ', err) + err = nfmpi_rename_dim(ncid, 3, 'abc') + if (err .ne. 0) + + call errore('nfmpi_rename_dim: ', err) + err = nfmpi_inq_dimname(ncid, 3, name) + if (name .ne. 'abc') + + call errorc('Unexpected name: ', name) + err = nfmpi_rename_dim(ncid, 1, 'abc') + if (err .ne. NF_ENAMEINUSE) + + call errore('duplicate name: ', err) + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + + +C Test nfmpi_def_var +C try with bad netCDF handle, check error +C try with bad name, check error +C scalar tests: +C check that proper define worked with nfmpi_inq_var +C try redefining an existing variable, check error +C try with bad datatype, check error +C try with bad number of dimensions, check error +C try in data mode, check error +C check that returned id is one more than previous id +C try with bad dimension ids, check error + subroutine test_nfmpi_def_var() + implicit none +#include "tests.inc" + + integer ncid + integer vid + integer err !/* status */ + integer i + integer ndims + integer na + character*(NF_MAX_NAME) name + integer dimids(MAX_RANK) + integer datatype + +C /* BAD_ID test */ + err = nfmpi_def_var(BAD_ID, 'abc', NF_SHORT, 0, dimids, vid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: status = ', err) + +C /* scalar tests */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 0, dimids, vid) + if (err .ne. 0) + + call errore('nfmpi_def_var: ', err) + err = nfmpi_inq_var(ncid, vid, name, datatype, ndims, dimids, + + na) + if (err .ne. 0) + + call errore('nfmpi_inq_var: ', err) + if (name .ne. 'abc') + + call errorc('Unexpected name: ', name) + if (datatype .ne. NF_SHORT) + + call error('Unexpected datatype') + if (ndims .ne. 0) + + call error('Unexpected rank') + err = nfmpi_def_var(ncid, BAD_NAME, NF_SHORT, + & 0, dimids, vid) + if (err .ne. NF_EBADNAME) + + call errore('bad name: ', err) + err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 0, dimids, vid) + if (err .ne. NF_ENAMEINUSE) + + call errore('duplicate name: ', err) + err = nfmpi_def_var(ncid, 'ABC', BAD_TYPE, -1, dimids, vid) + if (err .ne. NF_EBADTYPE) + + call errore('bad type: ', err) + err = nfmpi_def_var(ncid, 'ABC', NF_SHORT, -1, dimids, vid) + if (err .ne. NF_EINVAL) + + call errore('bad rank: ', err) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + err = nfmpi_def_var(ncid, 'ABC', NF_SHORT, 0, dimids, vid) + if (err .ne. NF_ENOTINDEFINE) + + call errore('nfmpi_def_var called in data mode: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', scratch) + +C /* general tests using global vars */ + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + do 1, i = 1, NVARS + err = nfmpi_def_var(ncid, var_name(i), var_type(i), + + var_rank(i), var_dimid(1,i), vid) + if (err .ne. 0) + + call errore('nfmpi_def_var: ', err) + if (vid .ne. i) + + call error('Unexpected varid') +1 continue + +C /* try bad dim ids */ + dimids(1) = BAD_DIMID + err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 1, dimids, vid) + if (err .ne. NF_EBADDIM) + + call errore('bad dim ids: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', scratch) + end + + +C Test nfmpi_rename_var +C try with bad netCDF handle, check error +C try with bad variable handle, check error +C try renaming to existing variable name, check error +C check that proper rename worked with nfmpi_inq_varid +C try in data mode, check error + subroutine test_nfmpi_rename_var() + implicit none +#include "tests.inc" + + integer ncid + integer vid + integer err + integer i + character*(NF_MAX_NAME) name + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_rename_var(ncid, BAD_VARID, 'newName') + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + call def_dims(ncid) + call def_vars(ncid) + +C /* Prefix "new_" to each name */ + do 1, i = 1, NVARS + err = nfmpi_rename_var(BAD_ID, i, 'newName') + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_rename_var(ncid, i, var_name(NVARS)) + if (err .ne. NF_ENAMEINUSE) + + call errore('duplicate name: ', err) + name = 'new_' // var_name(i) + err = nfmpi_rename_var(ncid, i, name) + if (err .ne. 0) + + call errore('nfmpi_rename_var: ', err) + err = nfmpi_inq_varid(ncid, name, vid) + if (err .ne. 0) + + call errore('nfmpi_inq_varid: ', err) + if (vid .ne. i) + + call error('Unexpected varid') +1 continue + +C /* Change to data mode */ +C /* Try making names even longer. Then restore original names */ + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + do 2, i = 1, NVARS + name = 'even_longer_' // var_name(i) + err = nfmpi_rename_var(ncid, i, name) + if (err .ne. NF_ENOTINDEFINE) + + call errore('longer name in data mode: ', err) + err = nfmpi_rename_var(ncid, i, var_name(i)) + if (err .ne. 0) + + call errore('nfmpi_rename_var: ', err) + err = nfmpi_inq_varid(ncid, var_name(i), vid) + if (err .ne. 0) + + call errore('nfmpi_inq_varid: ', err) + if (vid .ne. i) + + call error('Unexpected varid') +2 continue + + call put_vars(ncid) + call check_vars(ncid) + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', scratch) + end + + +C Test nfmpi_copy_att +C try with bad source or target netCDF handles, check error +C try with bad source or target variable handle, check error +C try with nonexisting attribute, check error +C check that NF_GLOBAL variable for source or target works +C check that new attribute put works with target in define mode +C check that old attribute put works with target in data mode +C check that changing type and length of an attribute work OK +C try with same ncid for source and target, different variables +C try with same ncid for source and target, same variable + subroutine test_nfmpi_copy_att() + implicit none +#include "tests.inc" + + integer ncid_in + integer ncid_out + integer vid + integer err + integer i + integer j + character*(NF_MAX_NAME) name !/* of att */ + integer datatype !/* of att */ + NFMPI_OFFSET length !/* of att */ + character*1 value + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid_in) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid_out) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid_out) + call def_vars(ncid_out) + + do 1, i = 0, NVARS + vid = VARID(i) + do 2, j = 1, NATTS(i) + name = ATT_NAME(j,i) + err = nfmpi_copy_att(ncid_in, BAD_VARID, name, + + ncid_out, vid) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_copy_att(ncid_in, vid, name, ncid_out, + + BAD_VARID) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_copy_att(BAD_ID, vid, name, + + ncid_out, vid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_copy_att(ncid_in, vid, name, + + BAD_ID, vid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_copy_att(ncid_in, vid, 'noSuch', + + ncid_out, vid) + if (err .ne. NF_ENOTATT) + + call errore('bad attname: ', err) + err = nfmpi_copy_att(ncid_in, vid, name, + + ncid_out, vid) + if (err .ne. 0) + + call errore('nfmpi_copy_att: ', err) + err = nfmpi_copy_att(ncid_out, vid, name, + + ncid_out, vid) + if (err .ne. 0) + + call errore('source = target: ', err) +2 continue +1 continue + + err = nfmpi_close(ncid_in) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* Close scratch. Reopen & check attributes */ + err = nfmpi_close(ncid_out) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_open(comm, scratch, NF_WRITE, MPI_INFO_NULL, + + ncid_out) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + call check_atts(ncid_out) + +C change to define mode +C define single char. global att. ':a' with value 'A' +C This will be used as source for following copies + err = nfmpi_redef(ncid_out) + if (err .ne. 0) + + call errore('nfmpi_redef: ', err) + length = 1 + err = nfmpi_put_att_text(ncid_out, NF_GLOBAL, 'a', length, 'A') + if (err .ne. 0) + + call errore('nfmpi_put_att_text: ', err) + +C change to data mode +C Use scratch as both source & dest. +C try copy to existing att. change type & decrease length +C rename 1st existing att of each var (if any) 'a' +C if this att. exists them copy ':a' to it + err = nfmpi_enddef(ncid_out) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + do 3, i = 1, NVARS + if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then + err = nfmpi_rename_att(ncid_out, i, + + att_name(1,i), 'a') + if (err .ne. 0) + + call errore('nfmpi_rename_att: ', err) + err = nfmpi_copy_att(ncid_out, NF_GLOBAL, 'a', + + ncid_out, i) + if (err .ne. 0) + + call errore('nfmpi_copy_att: ', err) + end if +3 continue + err = nfmpi_close(ncid_out) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* Reopen & check */ + err = nfmpi_open(comm, scratch, NF_WRITE, MPI_INFO_NULL, + + ncid_out) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 4, i = 1, NVARS + if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then + err = nfmpi_inq_att(ncid_out, i, 'a', + + datatype, length) + if (err .ne. 0) + + call errore('nfmpi_inq_att: ', err) + if (datatype .ne. NF_CHAR) + + call error('Unexpected type') + if (length .ne. 1) + + call error('Unexpected length') + err = nfmpi_get_att_text(ncid_out, i, 'a', value) + if (err .ne. 0) + + call errore('nfmpi_get_att_text: ', err) + if (value .ne. 'A') + + call error('Unexpected value') + end if +4 continue + + err = nfmpi_close(ncid_out) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed', scratch) + end + + +C Test nfmpi_rename_att +C try with bad netCDF handle, check error +C try with bad variable handle, check error +C try with nonexisting att name, check error +C try renaming to existing att name, check error +C check that proper rename worked with nfmpi_inq_attid +C try in data mode, check error + subroutine test_nfmpi_rename_att() + implicit none +#include "tests.inc" + + integer ncid + integer vid + integer err + integer i + integer j + integer k + integer attnum + character*(NF_MAX_NAME) atnam + character*(NF_MAX_NAME) name + character*(NF_MAX_NAME) oldname + character*(NF_MAX_NAME) newname + integer nok !/* count of valid comparisons */ + integer datatype + integer attyp + NFMPI_OFFSET length + NFMPI_OFFSET attlength + NFMPI_OFFSET ndx(1) + character*(MAX_NELS) text + doubleprecision value(MAX_NELS) + doubleprecision expect + + nok = 0 + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_rename_att(ncid, BAD_VARID, 'abc', 'newName') + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + + do 1, i = 0, NVARS + vid = VARID(i) + do 2, j = 1, NATTS(i) + atnam = ATT_NAME(j,i) + err = nfmpi_rename_att(BAD_ID, vid, atnam, + + 'newName') + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_rename_att(ncid, vid, 'noSuch', + + 'newName') + if (err .ne. NF_ENOTATT) + + call errore('bad attname: ', err) + newname = 'new_' // atnam + err = nfmpi_rename_att(ncid, vid, atnam, newname) + if (err .ne. 0) + + call errore('nfmpi_rename_att: ', err) + err = nfmpi_inq_attid(ncid, vid, newname, attnum) + if (err .ne. 0) + + call errore('nfmpi_inq_attid: ', err) + if (attnum .ne. j) + + call error('Unexpected attnum') +2 continue +1 continue + +C /* Close. Reopen & check */ + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_open(comm, scratch, NF_WRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 3, i = 0, NVARS + vid = VARID(i) + do 4, j = 1, NATTS(i) + atnam = ATT_NAME(j,i) + attyp = ATT_TYPE(j,i) + attlength = ATT_LEN(j,i) + newname = 'new_' // atnam + err = nfmpi_inq_attname(ncid, vid, j, name) + if (err .ne. 0) + + call errore('nfmpi_inq_attname: ', err) + if (name .ne. newname) + + call error('nfmpi_inq_attname: unexpected name') + err = nfmpi_inq_att(ncid, vid, name, + + datatype, length) + if (err .ne. 0) + + call errore('nfmpi_inq_att: ', err) + if (datatype .ne. attyp) + + call error('nfmpi_inq_att: unexpected type') + if (length .ne. attlength) + + call error('nfmpi_inq_att: unexpected length') + if (datatype .eq. NF_CHAR) then + err = nfmpi_get_att_text(ncid, vid, name, text) + if (err .ne. 0) + + call errore('nfmpi_get_att_text: ', err) + do 5, k = 1, attlength + ndx(1) = k + expect = hash(datatype, -1, ndx) + if (ichar(text(k:k)) .ne. expect) then + call error( + + 'nfmpi_get_att_text: unexpected value') + else + nok = nok + 1 + end if +5 continue + else + err = nfmpi_get_att_double(ncid, vid, name, + + value) + if (err .ne. 0) + + call errore('nfmpi_get_att_double: ', err) + do 6, k = 1, attlength + ndx(1) = k + expect = hash(datatype, -1, ndx) + if (inRange(expect, datatype)) then + if (.not. equal(value(k),expect,datatype, + + NF_DOUBLE)) then + call error( + + 'nfmpi_get_att_double: unexpected value') + else + nok = nok + 1 + end if + end if +6 continue + end if +4 continue +3 continue + call print_nok(nok) + +C /* Now in data mode */ +C /* Try making names even longer. Then restore original names */ + + do 7, i = 0, NVARS + vid = VARID(i) + do 8, j = 1, NATTS(i) + atnam = ATT_NAME(j,i) + oldname = 'new_' // atnam + newname = 'even_longer_' // atnam + err = nfmpi_rename_att(ncid, vid, oldname, newname) + if (err .ne. NF_ENOTINDEFINE) + + call errore('longer name in data mode: ', err) + err = nfmpi_rename_att(ncid, vid, oldname, atnam) + if (err .ne. 0) + + call errore('nfmpi_rename_att: ', err) + err = nfmpi_inq_attid(ncid, vid, atnam, attnum) + if (err .ne. 0) + + call errore('nfmpi_inq_attid: ', err) + if (attnum .ne. j) + + call error('Unexpected attnum') +8 continue +7 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + + +C Test nfmpi_del_att +C try with bad netCDF handle, check error +C try with bad variable handle, check error +C try with nonexisting att name, check error +C check that proper delete worked using: +C nfmpi_inq_attid, nfmpi_inq_natts, nfmpi_inq_varnatts + subroutine test_nfmpi_del_att() + implicit none +#include "tests.inc" + + integer ncid + integer err + integer i + integer j + integer attnum + integer na + integer numatts + integer vid + character*(NF_MAX_NAME) name !/* of att */ + + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + err = nfmpi_del_att(ncid, BAD_VARID, 'abc') + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + call def_dims(ncid) + call def_vars(ncid) + call put_atts(ncid) + + do 1, i = 0, NVARS + vid = VARID(i) + numatts = NATTS(i) + do 2, j = 1, numatts + name = ATT_NAME(j,i) + err = nfmpi_del_att(BAD_ID, vid, name) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_del_att(ncid, vid, 'noSuch') + if (err .ne. NF_ENOTATT) + + call errore('bad attname: ', err) + err = nfmpi_del_att(ncid, vid, name) + if (err .ne. 0) + + call errore('nfmpi_del_att: ', err) + err = nfmpi_inq_attid(ncid, vid, name, attnum) + if (err .ne. NF_ENOTATT) + + call errore('bad attname: ', err) + if (i .lt. 1) then + err = nfmpi_inq_natts(ncid, na) + if (err .ne. 0) + + call errore('nfmpi_inq_natts: ', err) + if (na .ne. numatts-j) then + call errori('natts: expected: ', numatts-j) + call errori('natts: got: ', na) + end if + end if + err = nfmpi_inq_varnatts(ncid, vid, na) + if (err .ne. 0) + + call errore('nfmpi_inq_natts: ', err) + if (na .ne. numatts-j) then + call errori('natts: expected: ', numatts-j) + call errori('natts: got: ', na) + end if +2 continue +1 continue + +C /* Close. Reopen & check no attributes left */ + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_open(comm, scratch, NF_WRITE, + + MPI_INFO_NULL, ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_natts(ncid, na) + if (err .ne. 0) + + call errore('nfmpi_inq_natts: ', err) + if (na .ne. 0) + + call errori('natts: expected 0, got ', na) + do 3, i = 0, NVARS + vid = VARID(i) + err = nfmpi_inq_varnatts(ncid, vid, na) + if (err .ne. 0) + + call errore('nfmpi_inq_natts: ', err) + if (na .ne. 0) + + call errori('natts: expected 0, got ', na) +3 continue + +C /* restore attributes. change to data mode. try to delete */ + err = nfmpi_redef(ncid) + if (err .ne. 0) + + call errore('nfmpi_redef: ', err) + call put_atts(ncid) + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + + do 4, i = 0, NVARS + vid = VARID(i) + numatts = NATTS(i) + do 5, j = 1, numatts + name = ATT_NAME(j,i) + err = nfmpi_del_att(ncid, vid, name) + if (err .ne. NF_ENOTINDEFINE) + + call errore('in data mode: ', err) +5 continue +4 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) + end + +C parallel-netcdf doesn't implement set_fill, so i have not +C parallel-netcdfified this subroutine +C Test nfmpi_set_fill +C try with bad netCDF handle, check error +C try in read-only mode, check error +C try with bad new_fillmode, check error +C try in data mode, check error +C check that proper set to NF_FILL works for record & non-record variables +C (note that it is not possible to test NF_NOFILL mode!) +C close file & create again for test using attribute _FillValue + subroutine test_nfmpi_set_fill() +#if 0 + implicit none +#include "tests.inc" + + integer ncid + integer vid + integer err + integer i + integer j + integer old_fillmode + integer nok !/* count of valid comparisons */ + character*1 text + doubleprecision value + doubleprecision fill + NFMPI_OFFSET index(MAX_RANK) + NFMPI_OFFSET length + + nok = 0 + value = 0 + +C /* bad ncid */ + err = nfmpi_set_fill(BAD_ID, NF_NOFILL, old_fillmode) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + +C /* try in read-only mode */ + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_set_fill(ncid, NF_NOFILL, old_fillmode) + if (err .ne. NF_EPERM) + + call errore('read-only: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + +C /* create scratch */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + +C /* BAD_FILLMODE */ + err = nfmpi_set_fill(ncid, BAD_FILLMODE, old_fillmode) + if (err .ne. NF_EINVAL) + + call errore('bad fillmode: ', err) + +C /* proper calls */ + err = nfmpi_set_fill(ncid, NF_NOFILL, old_fillmode) + if (err .ne. 0) + + call errore('nfmpi_set_fill: ', err) + if (old_fillmode .ne. NF_FILL) + + call errori('Unexpected old fill mode: ', old_fillmode) + err = nfmpi_set_fill(ncid, NF_FILL, old_fillmode) + if (err .ne. 0) + + call errore('nfmpi_set_fill: ', err) + if (old_fillmode .ne. NF_NOFILL) + + call errori('Unexpected old fill mode: ', old_fillmode) + +C /* define dims & vars */ + call def_dims(ncid) + call def_vars(ncid) + +C /* Change to data mode. Set fillmode again */ + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + err = nfmpi_set_fill(ncid, NF_FILL, old_fillmode) + if (err .ne. 0) + + call errore('nfmpi_set_fill: ', err) + if (old_fillmode .ne. NF_FILL) + + call errori('Unexpected old fill mode: ', old_fillmode) + +C /* Write record number NRECS to force writing of preceding records */ +C /* Assumes variable cr is char vector with UNLIMITED dimension */ + err = nfmpi_inq_varid(ncid, 'cr', vid) + if (err .ne. 0) + + call errore('nfmpi_inq_varid: ', err) + index(1) = NRECS + text = char(NF_FILL_CHAR) + err = nfmpi_put_var1_text(ncid, vid, index, text) + if (err .ne. 0) + + call errore('nfmpi_put_var1_text: ', err) + +C /* get all variables & check all values equal default fill */ + do 1, i = 1, NVARS + if (var_type(i) .eq. NF_CHAR) then + fill = NF_FILL_CHAR + else if (var_type(i) .eq. NF_BYTE) then + fill = NF_FILL_BYTE + else if (var_type(i) .eq. NF_SHORT) then + fill = NF_FILL_SHORT + else if (var_type(i) .eq. NF_INT) then + fill = NF_FILL_INT + else if (var_type(i) .eq. NF_FLOAT) then + fill = NF_FILL_FLOAT + else if (var_type(i) .eq. NF_DOUBLE) then + fill = NF_FILL_DOUBLE + else + stop 'test_nfmpi_set_fill(): impossible var_type(i)' + end if + + do 2, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes()') + if (var_type(i) .eq. NF_CHAR) then + err = nfmpi_get_var1_text(ncid, i, index, text) + if (err .ne. 0) + + call errore('nfmpi_get_var1_text failed: ',err) + value = ichar(text) + else + err = nfmpi_get_var1_double(ncid, i, index, + + value) + if (err .ne. 0) + + call errore + + ('nfmpi_get_var1_double failed: ',err) + end if + if (value .ne. fill .and. + + abs((fill - value)/fill) .gt. 1.0e-9) then + call errord('Unexpected fill value: ', value) + else + nok = nok + 1 + end if +2 continue +1 continue + +C /* close scratch & create again for test using attribute _FillValue */ + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_create(comm, scratch, NF_CLOBBER, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + return + end if + call def_dims(ncid) + call def_vars(ncid) + +C /* set _FillValue = 42 for all vars */ + fill = 42 + text = char(int(fill)) + length = 1 + do 3, i = 1, NVARS + if (var_type(i) .eq. NF_CHAR) then + err = nfmpi_put_att_text(ncid, i, '_FillValue', length, + + text) + if (err .ne. 0) + + call errore('nfmpi_put_att_text: ', err) + else + err = nfmpi_put_att_double(ncid, i, '_FillValue', + + var_type(i),length,fill) + if (err .ne. 0) + + call errore('nfmpi_put_att_double: ', err) + end if +3 continue + +C /* data mode. write records */ + err = nfmpi_enddef(ncid) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + index(1) = NRECS + err = nfmpi_put_var1_text(ncid, vid, index, text) + if (err .ne. 0) + + call errore('nfmpi_put_var1_text: ', err) + +C /* get all variables & check all values equal 42 */ + do 4, i = 1, NVARS + do 5, j = 1, var_nels(i) + err = index2indexes(j, var_rank(i), var_shape(1,i), + + index) + if (err .ne. 0) + + call error('error in index2indexes') + if (var_type(i) .eq. NF_CHAR) then + err = nfmpi_get_var1_text(ncid, i, index, text) + if (err .ne. 0) + + call errore('nfmpi_get_var1_text failed: ',err) + value = ichar(text) + else + err = nfmpi_get_var1_double(ncid, i, + + index, value) + if (err .ne. 0) + + call errore + + ('nfmpi_get_var1_double failed: ', err) + end if + if (value .ne. fill) then + call errord(' Value expected: ', fill) + call errord(' Value read: ', value) + else + nok = nok + 1 + end if +5 continue +4 continue + call print_nok(nok) + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errori('delete of scratch file failed: ', err) +#endif + end + +#if 0 +C * Test nc_set_default_format +C * try with bad default format +C * try with NULL old_formatp +C * try in data mode, check error +C * check that proper set to NC_FILL works for record & non-record variables +C * (note that it is not possible to test NC_NOFILL mode!) +C * close file & create again for test using attribute _FillValue + subroutine test_nfmpi_set_default_format() + implicit none +#include "tests.inc" + + integer ncid + integer err + integer i + integer version + integer old_format + integer nfmpi_get_file_version + +C /* bad format */ + err = nfmpi_set_default_format(3, old_format) + IF (err .ne. NF_EINVAL) + + call errore("bad default format: status = %d", err) + +C /* Cycle through available formats. */ + do 1 i=1, 2 + err = nfmpi_set_default_format(i, old_format) + if (err .ne. 0) + + call errore("setting classic format: status = %d", err) + err = nfmpi_create(comm, scratch, NF_CLOBBER, + + MPI_INFO_NULL, ncid) + if (err .ne. 0) + + call errore("bad nfmpi_create: status = %d", err) + err = nfmpi_put_att_text(ncid, NF_GLOBAL, "testatt", + + 4, "blah") + if (err .ne. 0) call errore("bad put_att: status = %d", err) + err = nfmpi_close(ncid) + if (err .ne. 0) call errore("bad close: status = %d", err) + err = nfmpi_get_file_version(scratch, version) + if (err .ne. 0) call errore("bad file version = %d", err) + if (version .ne. i) + + call errore("bad file version = %d", err) + 1 continue + +C /* Remove the left-over file. */ + err = nfmpi_delete(scratch) + if (err .ne. 0) call errore("remove failed", err) + end + +#endif + +C This function looks in a file for the netCDF magic number. + integer function nfmpi_get_file_version(path, version) + implicit none +#include "tests.inc" + + character*(*) path + integer version, iosnum + character magic*4 + integer ver + integer f + parameter (f = 10) + + open(f, file=path, status='OLD', form='UNFORMATTED', + + access='DIRECT', recl=4) + +C Assume this is not a netcdf file. + nfmpi_get_file_version = NF_ENOTNC + version = 0 + +C Read the magic number, the first 4 bytes of the file. + read(f, rec=1, err = 1) magic + +C If the first three characters are not "CDF" we're done. + if (index(magic, 'CDF') .eq. 1) then + ver = ichar(magic(4:4)) + if (ver .eq. 1) then + version = 1 + nfmpi_get_file_version = NF_NOERR + elseif (ver .eq. 2) then + version = 2 + nfmpi_get_file_version = NF_NOERR + endif + endif + + 1 close(f) + return + end + + Index: /tags/v1-0-3/test/nf_test/test_read.F =================================================================== --- /tags/v1-0-3/test/nf_test/test_read.F (revision 559) +++ /tags/v1-0-3/test/nf_test/test_read.F (revision 559) @@ -0,0 +1,1090 @@ +C********************************************************************* +C Copyright 1996, UCAR/Unidata +C See netcdf/COPYRIGHT file for copying and redistribution conditions. +C $Id$ +C********************************************************************* + +C Test nfmpi_strerror. +C Try on a bad error status. +C Test for each defined error status. +C + subroutine test_nfmpi_strerror() + implicit none +#include "tests.inc" + integer number_of_messages + parameter (number_of_messages = 27) + + integer i + integer status(number_of_messages) + character*80 message + character*80 msg(number_of_messages) + + data status(1) / NF_NOERR/ + data status(2) / NF_EBADID / + data status(3) / NF_EEXIST / + data status(4) / NF_EINVAL / + data status(5) / NF_EPERM / + data status(6) / NF_ENOTINDEFINE / + data status(7) / NF_EINDEFINE / + data status(8) / NF_EINVALCOORDS / + data status(9) / NF_EMAXDIMS / + data status(10) / NF_ENAMEINUSE / + data status(11) / NF_ENOTATT / + data status(12) / NF_EMAXATTS / + data status(13) / NF_EBADTYPE / + data status(14) / NF_EBADDIM / + data status(15) / NF_EUNLIMPOS / + data status(16) / NF_EMAXVARS / + data status(17) / NF_ENOTVAR / + data status(18) / NF_EGLOBAL / + data status(19) / NF_ENOTNC / + data status(20) / NF_ESTS / + data status(21) / NF_EMAXNAME / + data status(22) / NF_EUNLIMIT / + data status(23) / NF_ENORECVARS / + data status(24) / NF_ECHAR / + data status(25) / NF_EEDGE / + data status(26) / NF_ESTRIDE / + data status(27) / NF_EBADNAME / + + data msg(1) / 'No error' / + data msg(2) / 'Not a netCDF id' / + data msg(3) / 'netCDF file exists && NC_NOCLOBBER' / + data msg(4) / 'Invalid argument' / + data msg(5) / 'Write to read only' / + data msg(6) / 'Operation not allowed in data mode' / + data msg(7) / 'Operation not allowed in define mode' / + data msg(8) / 'Index exceeds dimension bound' / + data msg(9) / 'NC_MAX_DIMS exceeded' / + data msg(10) / 'String match to name in use' / + data msg(11) / 'Attribute not found' / + data msg(12) / 'NC_MAX_ATTRS exceeded' / + data msg(13) + + / 'Not a netCDF data type or _FillValue type mismatch' / + data msg(14) / 'Invalid dimension id or name' / + data msg(15) / 'NC_UNLIMITED in the wrong index' / + data msg(16) / 'NC_MAX_VARS exceeded' / + data msg(17) / 'Variable not found' / + data msg(18) / 'Action prohibited on NC_GLOBAL varid' / + data msg(19) / 'Not a netCDF file' / + data msg(20) / 'In Fortran, string too short' / + data msg(21) / 'NC_MAX_NAME exceeded' / + data msg(22) / 'NC_UNLIMITED size already in use' / + data msg(23) / 'nc_rec op when there are no record vars' / + data msg(24) / 'Attempt to convert between text & numbers' / + data msg(25) / 'Edge+start exceeds dimension bound' / + data msg(26) / 'Illegal stride' / + data msg(27) + + / 'Attribute or variable name contains illegal characters' / + +C /* Try on a bad error status */ + message = nfmpi_strerror(-666)!/* should fail */ + if (message .ne. 'Unknown Error') + + call errorc('nfmpi_strerror on bad error status returned: ', + + message) + +C /* Try on each legitimate error status */ + do 1, i=1, number_of_messages + message = nfmpi_strerror(status(i)) + if (message .ne. msg(i)) + + call error('nfmpi_strerror() should return "' + + // msg(i) // '"') +1 continue + end + + +C Test nfmpi_open. +C If in read-only section of tests, +C Try to open a non-existent netCDF file, check error return. +C Open a file that is not a netCDF file, check error return. +C Open a netCDF file with a bad mode argument, check error return. +C Open a netCDF file with NFMPI_NOWRITE mode, try to write, check error. +C Try to open a netcdf twice, check whether returned netcdf ids different. +C If in writable section of tests, +C Open a netCDF file with NFMPI_WRITE mode, write something, close it. +C On exit, any open netCDF files are closed. + subroutine test_nfmpi_open() + implicit none +#include "tests.inc" + integer err + integer ncid + integer ncid2 + +C /* Try to open a nonexistent file */ + err = nfmpi_open(comm, 'tooth-fairy.nc', NF_NOWRITE, + + MPI_INFO_NULL, ncid)!/* should fail */ + if (err .eq. NF_NOERR) + + call error + + ('nfmpi_open of nonexistent file should have failed') + if (.not. NFMPI_ISSYSERR(err)) + + call error( + + 'nfmpi_open of nonexistent file should + + have returned system error') + +C /* Open a file that is not a netCDF file. */ + err = nfmpi_open(comm, 'test_get.F', NF_NOWRITE, MPI_INFO_NULL, + + ncid)!/* should fail */ + if (err .ne. NF_ENOTNC .and. err .ne. NF_EOFILE) + + call errore('nfmpi_open of non-netCDF file: ', err) + +C /* Open a netCDF file in read-only mode, check that write fails */ + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_redef(ncid) !/* should fail */ + if (err .ne. NF_EPERM) + + call error('nfmpi_redef of read-only file should fail') +C /* Opened OK, see if can open again and get a different netCDF ID */ + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid2) + if (err .ne. 0) then + call errore('nfmpi_open: ', err) + else + err = nfmpi_close(ncid2) + end if + if (ncid2 .eq. ncid) + + call error( + + 'netCDF IDs for first and second + + nfmpi_open calls should differ') + + if (.not. readonly) then !/* tests using netCDF scratch file */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, + + MPI_INFO_NULL, ncid2) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + else + err = nfmpi_close(ncid2) + end if + err = nfmpi_open(comm, scratch, NF_WRITE, MPI_INFO_NULL, + + ncid2) + if (err .ne. 0) then + call errore('nfmpi_open: ', err) + else + err = nfmpi_close(ncid2) + end if + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', scratch) + end if + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + +C +C Test nfmpi_close. +C Try to close a netCDF file twice, check whether second close fails. +C Try on bad handle, check error return. +C Try in define mode and data mode. +C + subroutine test_nfmpi_close() + implicit none +#include "tests.inc" + integer ncid + integer err + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + +C /* Close a netCDF file twice, second time should fail */ + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close failed: ', err) + err = nfmpi_close(ncid) + if (err .ne. NF_EBADID) + + call error('nfmpi_close of closed file should have failed') + +C /* Try with a bad netCDF ID */ + err = nfmpi_close(BAD_ID)!/* should fail */ + if (err .ne. NF_EBADID) + + call errore( + + 'nfmpi_close with bad netCDF ID returned wrong error: ', + + err) + +C /* Close in data mode */ + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close in data mode failed: ', err) + + if (.not. readonly) then !/* tests using netCDF scratch file */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, + + MPI_INFO_NULL, ncid) + if (err .ne. 0) + + call errore('nfmpi_create: ', err) + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close in define mode: ', err) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', + + scratch) + end if + end + + +C Test nfmpi_inq. +C Try on bad handle, check error return. +C Try in data mode, check returned values. +C Try asking for subsets of info. +C If in writable section of tests, +C Try in define mode, after adding an unlimited dimension, variable. +C On exit, any open netCDF files are closed. + subroutine test_nfmpi_inq() + implicit none +#include "tests.inc" + integer ncid + integer ncid2 !/* for scratch netCDF dataset */ + integer ndims !/* number of dimensions */ + integer nvars !/* number of variables */ + integer ngatts !/* number of global attributes */ + integer recdim !/* id of unlimited dimension */ + integer err + integer ndims0 + integer nvars0 + integer ngatts0 + integer recdim0 + integer did + integer vid + NFMPI_OFFSET length + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + +C /* Try on bad handle */ + err = nfmpi_inq(BAD_ID, ndims, nvars, ngatts, recdim) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + + err = nfmpi_inq(ncid, ndims, nvars, ngatts, recdim) + if (err .ne. 0) then + call errore('nfmpi_inq: ', err) + else if (ndims .ne. NDIMS) then + call errori + + ('nfmpi_inq: wrong number of dimensions returned: ', ndims) + else if (nvars .ne. NVARS) then + call errori + + ('nfmpi_inq: wrong number of variables returned: ', nvars) + else if (ngatts .ne. NGATTS) then + call errori( + + 'nfmpi_inq: wrong number of global atts returned: ', + + ngatts) + else if (recdim .ne. RECDIM) then + call errori + + ('nfmpi_inq: wrong record dimension ID returned: ', recdim) + end if + + if (.not. readonly) then !/* tests using netCDF scratch file */ + err = nfmpi_create(comm, scratch, NF_NOCLOBBER, + + MPI_INFO_NULL, ncid2) + if (err .ne. 0) then + call errore('nfmpi_create: ', err) + else !/* add dim, var, gatt, check inq */ + err = nfmpi_enddef(ncid2) !/* enter data mode */ + err = nfmpi_inq(ncid2, ndims0, nvars0, + + ngatts0, recdim0) + if (err .ne. 0) + + call errore('nfmpi_inq: ', err) + err = nfmpi_redef(ncid2) !/* enter define mode */ +C /* Check that inquire still works in define mode */ + err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim) + if (err .ne. 0) then + call errore('nfmpi_inq in define mode: ', err) + else if (ndims .ne. ndims0) then + call errori + + ('nfmpi_inq in define mode: ndims wrong, ', ndims) + else if (nvars .ne. nvars0) then + call errori + + ('nfmpi_inq in define mode: nvars wrong, ', nvars) + else if (ngatts .ne. ngatts0) then + call errori( + + 'nfmpi_inq in define mode: ngatts wrong, ', ngatts) + print *, ' expected ', ngatts0 + else if (recdim .ne. recdim0) then + call errori + + ('nfmpi_inq in define mode: recdim wrong, ', recdim) + end if + +C /* Add dim, var, global att */ + length = 1 + err = nfmpi_def_dim(ncid2, 'inqd', length, did) + if (err .ne. 0) + + call errore('nfmpi_def_dim: ', err) + err = nfmpi_def_var(ncid2, 'inqv', NF_FLOAT, + + 0, 0, vid) + if (err .ne. 0) + + call errore('nfmpi_def_var: ', err) + + length = len('stuff') + err = nfmpi_put_att_text(ncid2, NF_GLOBAL, 'inqa', + + length, 'stuff') + if (err .ne. 0) + + call errore('nfmpi_put_att_text: ', err) + +C /* Make sure nfmpi_inq sees the additions while in define mode */ + err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim) + if (err .ne. 0) then + call errore('nfmpi_inq in define mode: ', err) + else if (ndims .ne. ndims0 + 1) then + call errori + + ('nfmpi_inq in define mode: ndims wrong, ', ndims) + else if (nvars .ne. nvars0 + 1) then + call errori + + ('nfmpi_inq in define mode: nvars wrong, ', nvars) + else if (ngatts .ne. ngatts0 + 1) then + call errori + + ('nfmpi_inq in define mode: ngatts wrong, ', ngatts) + print *, ' expected (added attr)', ngatts0 + 1 + end if + err = nfmpi_enddef(ncid2) + if (err .ne. 0) + + call errore('nfmpi_enddef: ', err) + +C /* Make sure nfmpi_inq stills sees additions in data mode */ + err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim) + if (err .ne. 0) then + call errore('nfmpi_inq failed in data mode: ',err) + else if (ndims .ne. ndims0 + 1) then + call errori + + ('nfmpi_inq in define mode: ndims wrong, ', ndims) + else if (nvars .ne. nvars0 + 1) then + call errori + + ('nfmpi_inq in define mode: nvars wrong, ', nvars) + else if (ngatts .ne. ngatts0 + 1) then + call errori + + ('nfmpi_inq in define mode: ngatts wrong, ', ngatts) + end if + err = nfmpi_close(ncid2) + err = nfmpi_delete(scratch, MPI_INFO_NULL) + if (err .ne. 0) + + call errorc('delete of scratch file failed: ', + + scratch) + end if + end if + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_natts() + implicit none +#include "tests.inc" + integer ncid + integer ngatts !/* number of global attributes */ + integer err + + err = nfmpi_inq_natts(BAD_ID, ngatts) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_natts(ncid, ngatts) + if (err .ne. 0) then + call errore('nfmpi_inq_natts: ', err) + else if (ngatts .ne. NGATTS) then + call errori + + ('nfmpi_inq_natts: wrong number of global atts returned, ', + + ngatts) + end if + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_ndims() + implicit none +#include "tests.inc" + integer ncid + integer ndims + integer err + + err = nfmpi_inq_ndims(BAD_ID, ndims) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_ndims(ncid, ndims) + if (err .ne. 0) then + call errore('nfmpi_inq_ndims: ', err) + else if (ndims .ne. NDIMS) then + call errori + + ('nfmpi_inq_ndims: wrong number returned, ', ndims) + end if + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_nvars() + implicit none +#include "tests.inc" + integer ncid + integer nvars + integer err + + err = nfmpi_inq_nvars(BAD_ID, nvars) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_nvars(ncid, nvars) + if (err .ne. 0) then + call errore('nfmpi_inq_nvars: ', err) + else if (nvars .ne. NVARS) then + call errori + + ('nfmpi_inq_nvars: wrong number returned, ', nvars) + end if + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_unlimdim() + implicit none +#include "tests.inc" + integer ncid + integer unlimdim + integer err + + err = nfmpi_inq_unlimdim(BAD_ID, unlimdim) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_unlimdim(ncid, unlimdim) + if (err .ne. 0) then + call errore('nfmpi_inq_unlimdim: ', err) + else if (unlimdim .ne. RECDIM) then + call errori + + ('nfmpi_inq_unlimdim: wrong number returned, ', unlimdim) + print *, 'expected ', RECDIM + end if + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_dimid() + implicit none +#include "tests.inc" + integer ncid + integer dimid + integer i + integer err + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + err = nfmpi_inq_dimid(ncid, 'noSuch', dimid) + if (err .ne. NF_EBADDIM) + + call errore('bad dim name: ', err) + do 1, i = 1, NDIMS + err = nfmpi_inq_dimid(BAD_ID, dim_name(i), dimid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_dimid(ncid, dim_name(i), dimid) + if (err .ne. 0) then + call errore('nfmpi_inq_dimid: ', err) + else if (dimid .ne. i) then + call errori('expected ', i) + call errori('got ', dimid) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_dim() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + character*(NF_MAX_NAME) name + NFMPI_OFFSET length + integer intlen + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NDIMS + err = nfmpi_inq_dim(BAD_ID, i, name, length) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_dim(ncid, BAD_DIMID, name, length) + if (err .ne. NF_EBADDIM) + + call errore('bad dimid: ', err) + err = nfmpi_inq_dim(ncid, i, name, length) + if (err .ne. 0) then + call errore('nfmpi_inq_dim: ', err) + else if (dim_name(i) .ne. name) then + call errorc('name unexpected: ', name) + print *, ' expected ', dim_name(i),' for the ',i,'entry' + else if (dim_len(i) .ne. length) then + intlen = length + call errori('size unexpected: ', intlen) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_dimlen() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + NFMPI_OFFSET length + integer intlen + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NDIMS + err = nfmpi_inq_dimlen(BAD_ID, i, length) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_dimlen(ncid, BAD_DIMID, length) + if (err .ne. NF_EBADDIM) + + call errore('bad dimid: ', err) + err = nfmpi_inq_dimlen(ncid, i, length) + if (err .ne. 0) then + call errore('nfmpi_inq_dimlen: ', err) + else if (dim_len(i) .ne. length) then + intlen = length + call errori('size unexpected: ', intlen) + print *, 'expected ', dim_len(i),' for the ',i,'entry' + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_dimname() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + character*(NF_MAX_NAME) name + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NDIMS + err = nfmpi_inq_dimname(BAD_ID, i, name) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_dimname(ncid, BAD_DIMID, name) + if (err .ne. NF_EBADDIM) + + call errore('bad dimid: ', err) + err = nfmpi_inq_dimname(ncid, i, name) + if (err .ne. 0) then + call errore('nfmpi_inq_dimname: ', err) + else if (dim_name(i) .ne. name) then + call errorc('name unexpected: ', name) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_varid() + implicit none +#include "tests.inc" + integer ncid + integer vid + integer i + integer err + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + err = nfmpi_inq_varid(ncid, 'noSuch', vid) + if (err .ne. NF_ENOTVAR) + + call errore('bad ncid: ', err) + + do 1, i = 1, NVARS + err = nfmpi_inq_varid(BAD_ID, var_name(i), vid) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_varid(ncid, var_name(i), vid) + if (err .ne. 0) then + call errore('nfmpi_inq_varid: ', err) + else if (vid .ne. i) then + call errori('varid unexpected: ', vid) + endif +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_var() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + character*(NF_MAX_NAME) name + integer datatype + integer ndims + integer dimids(MAX_RANK) + integer na + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + err = nfmpi_inq_var(BAD_ID, i, name, datatype, ndims, + + dimids, na) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_var(ncid,BAD_VARID,name,datatype,ndims, + + dimids,na) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_var(ncid, i, name, datatype, ndims, dimids, + + na) + if (err .ne. 0) then + call errore('nfmpi_inq_var: ', err) + else if (var_name(i) .ne. name) then + call errorc('name unexpected: ', name) + else if (var_type(i) .ne. datatype) then + call errori('type unexpected: ', datatype) + else if (var_rank(i) .ne. ndims) then + call errori('ndims expected: ', ndims) + else if (.not.int_vec_eq(var_dimid(1,i),dimids,ndims)) then + call error('unexpected dimid') + else if (var_natts(i) .ne. na) then + call errori('natts unexpected: ', na) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_vardimid() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + integer dimids(MAX_RANK) + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + err = nfmpi_inq_vardimid(BAD_ID, i, dimids) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_vardimid(ncid, BAD_VARID, dimids) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_vardimid(ncid, i, dimids) + if (err .ne. 0) then + call errore('nfmpi_inq_vardimid: ', err) + else if (.not.int_vec_eq(var_dimid(1,i), dimids, + + var_rank(i))) then + call error('unexpected dimid') + print *, ' for variable ', i + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_varname() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + character*(NF_MAX_NAME) name + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + err = nfmpi_inq_varname(BAD_ID, i, name) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_varname(ncid, BAD_VARID, name) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_varname(ncid, i, name) + if (err .ne. 0) then + call errore('nfmpi_inq_varname: ', err) + else if (var_name(i) .ne. name) then + call errorc('name unexpected: ', name) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_varnatts() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + integer na + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 0, NVARS ! start with global attributes + err = nfmpi_inq_varnatts(BAD_ID, i, na) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_varnatts(ncid, BAD_VARID, na) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_varnatts(ncid, VARID(i), na) + if (err .ne. 0) then + call errore('nfmpi_inq_varnatts: ', err) + else if (NATTS(i) .ne. na) then ! works for global attributes + call errori('natts unexpected: ', na) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_varndims() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + integer ndims + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + err = nfmpi_inq_varndims(BAD_ID, i, ndims) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_varndims(ncid, BAD_VARID, ndims) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_varndims(ncid, i, ndims) + if (err .ne. 0) then + call errore('nfmpi_inq_varndims: ', err) + else if (var_rank(i) .ne. ndims) then + call errori('ndims unexpected: ', ndims) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_vartype() + implicit none +#include "tests.inc" + integer ncid + integer i + integer err + integer datatype + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + do 1, i = 1, NVARS + err = nfmpi_inq_vartype(BAD_ID, i, datatype) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_vartype(ncid, BAD_VARID, datatype) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_vartype(ncid, i, datatype) + if (err .ne. 0) then + call errore('nfmpi_inq_vartype: ', err) + else if (var_type(i) .ne. datatype) then + call errori('type unexpected: ', datatype) + end if +1 continue + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_att() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + integer t + NFMPI_OFFSET n + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + do 2, j = 1, NATTS(i) + err = nfmpi_inq_att(BAD_ID, i, ATT_NAME(j,i), t, n) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_att + + (ncid, BAD_VARID, ATT_NAME(j,i), t, n) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_att(ncid, i, 'noSuch', t, n) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute name: ', err) + err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i), t, n) + if (err .ne. 0) then + call error(nfmpi_strerror(err)) + else + if (t .ne. ATT_TYPE(j,i)) + + call error('type not that expected') + if (n .ne. ATT_LEN(j,i)) + + call error('length not that expected') + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_attlen() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + NFMPI_OFFSET len + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + err = nfmpi_inq_attlen(ncid, i, 'noSuch', len) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute name: ', err) + do 2, j = 1, NATTS(i) + err = nfmpi_inq_attlen(BAD_ID, i, + + ATT_NAME(j,i), len) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_attlen + + (ncid, BAD_VARID, ATT_NAME(j,i), len) + if (err .ne. NF_ENOTVAR) + + call errore('bad varid: ', err) + err = nfmpi_inq_attlen(ncid, i, ATT_NAME(j,i), len) + if (err .ne. 0) then + call error(nfmpi_strerror(err)) + else + if (len .ne. ATT_LEN(j,i)) + + call error('len not that expected') + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_atttype() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + integer datatype + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + err = nfmpi_inq_atttype(ncid, i, 'noSuch', datatype) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute name: ', err) + do 2, j = 1, NATTS(i) + err = nfmpi_inq_atttype + + (BAD_ID, i, ATT_NAME(j,i), datatype) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_atttype(ncid, BAD_VARID, ATT_NAME(j,i), + + datatype) + if (err .ne. NF_ENOTVAR) + + call errore('bad varid: ', err) + err = nfmpi_inq_atttype + + (ncid, i, ATT_NAME(j,i), datatype) + if (err .ne. 0) then + call error(nfmpi_strerror(err)) + else + if (datatype .ne. ATT_TYPE(j,i)) + + call error('type not that expected') + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_attname() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + character*(NF_MAX_NAME) name + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + err = nfmpi_inq_attname(ncid, i, BAD_ATTNUM, name) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute number: ', err) + err = nfmpi_inq_attname(ncid, i, NATTS(i)+1, name) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute number: ', err) + do 2, j = 1, NATTS(i) + err = nfmpi_inq_attname(BAD_ID, i, j, name) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_attname(ncid, BAD_VARID, j, name) + if (err .ne. NF_ENOTVAR) + + call errore('bad var id: ', err) + err = nfmpi_inq_attname(ncid, i, j, name) + if (err .ne. 0) then + call error(nfmpi_strerror(err)) + else + if (ATT_NAME(j,i) .ne. name) + + call error('name not that expected') + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end + + + subroutine test_nfmpi_inq_attid() + implicit none +#include "tests.inc" + integer ncid + integer i + integer j + integer err + integer attnum + + err = nfmpi_open(comm, testfile, NF_NOWRITE, MPI_INFO_NULL, + + ncid) + if (err .ne. 0) + + call errore('nfmpi_open: ', err) + + do 1, i = 0, NVARS + err = nfmpi_inq_attid(ncid, i, 'noSuch', attnum) + if (err .ne. NF_ENOTATT) + + call errore('Bad attribute name: ', err) + do 2, j = 1, NATTS(i) + err = nfmpi_inq_attid(BAD_ID, i, + + ATT_NAME(j,i), attnum) + if (err .ne. NF_EBADID) + + call errore('bad ncid: ', err) + err = nfmpi_inq_attid(ncid, BAD_VARID, ATT_NAME(j,i), + + attnum) + if (err .ne. NF_ENOTVAR) + + call errore('bad varid: ', err) + err = nfmpi_inq_attid(ncid, i, + + ATT_NAME(j,i), attnum) + if (err .ne. 0) then + call error(nfmpi_strerror(err)) + else + if (attnum .ne. j) + + call error('attnum not that expected') + end if +2 continue +1 continue + + err = nfmpi_close(ncid) + if (err .ne. 0) + + call errore('nfmpi_close: ', err) + end Index: /tags/v1-0-3/test/test_double_int/Makefile.in =================================================================== --- /tags/v1-0-3/test/test_double_int/Makefile.in (revision 555) +++ /tags/v1-0-3/test/test_double_int/Makefile.in (revision 555) @@ -0,0 +1,33 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +INCDIR = $(srcdir)/../../src/lib +LIBDIR = ../../src/lib + +INCLUDES = -I$(INCDIR) -I$(srcdir)/../common + +CC = @MPICC@ +CFLAGS = @CFLAGS@ $(INCLUDES) + +SRCS = test_read.c test_read_indep.c test_write.c test_write_indep.c +OBJS = $(SRCS:.c=.o) +PROGS = test_read test_read_indep test_write test_write_indep +LDFLAGS = -L$(LIBDIR) -L../common @LDFLAGS@ +LIBS = -lpnetcdf -ltestutils @LIBS@ + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROGS) + +test_read: test_read.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_read_indep: test_read_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write: test_write.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write_indep: test_write_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +clean: + rm -f $(OBJS) $(PROGS) *.nc Index: /tags/v1-0-3/test/test_double_int/test_write_indep.c =================================================================== --- /tags/v1-0-3/test/test_double_int/test_write_indep.c (revision 362) +++ /tags/v1-0-3/test/test_double_int/test_write_indep.c (revision 362) @@ -0,0 +1,238 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to write variable data and only + * deals with double variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + int data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) + fprintf(stderr, "Testing write ... "); + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_DOUBLE, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_DOUBLE, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_DOUBLE, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_DOUBLE, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: non-collective + */ + + status = ncmpi_begin_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_put_vara_int(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_end_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_double_int/test_read_indep.c =================================================================== --- /tags/v1-0-3/test/test_double_int/test_read_indep.c (revision 560) +++ /tags/v1-0-3/test/test_double_int/test_read_indep.c (revision 560) @@ -0,0 +1,365 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_double.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_type type, vartypes[NC_MAX_VARS]; + MPI_Offset attlen, dimlen; + MPI_Offset 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]; + int isRecvar; + 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 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_double.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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + 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(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; + 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); + + /** + * 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; +} Index: /tags/v1-0-3/test/test_double_int/test_write.c =================================================================== --- /tags/v1-0-3/test/test_double_int/test_write.c (revision 362) +++ /tags/v1-0-3/test/test_double_int/test_write.c (revision 362) @@ -0,0 +1,232 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to write variable data and only + * deals with double variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + int data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) + fprintf(stderr, "Testing write ... "); + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_DOUBLE, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_DOUBLE, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_DOUBLE, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_DOUBLE, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: collective + */ + + status = ncmpi_put_vara_int_all(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_double_int/test_read.c =================================================================== --- /tags/v1-0-3/test/test_double_int/test_read.c (revision 560) +++ /tags/v1-0-3/test/test_double_int/test_read.c (revision 560) @@ -0,0 +1,354 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_double.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_type type, vartypes[NC_MAX_VARS]; + MPI_Offset attlen, dimlen; + MPI_Offset 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]; + int isRecvar; + 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 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_double.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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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: collective + */ + + for (i = 0; i < NC_MAX_VAR_DIMS; i++) + start[i] = 0; + for (i = 0; i < nvars; i++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + switch (vartypes[i]) { + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vara_short_all(ncid1, i, start, shape, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_short_all(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_all(ncid1, i, start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(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_all(ncid1, i, start, shape, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(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(int)); + status = ncmpi_get_vara_int_all(ncid1, i, start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid2, varids[i], + start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; + /* handle unexpected types */ + } + } + + /** + * 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; +} Index: /tags/v1-0-3/test/test_double_int/README =================================================================== --- /tags/v1-0-3/test/test_double_int/README (revision 15) +++ /tags/v1-0-3/test/test_double_int/README (revision 15) @@ -0,0 +1,3 @@ +These examples test data transfers of: + + "file NC_DOUBLE var" <---> "memory int" Index: /tags/v1-0-3/test/test_dtype/Makefile.in =================================================================== --- /tags/v1-0-3/test/test_dtype/Makefile.in (revision 492) +++ /tags/v1-0-3/test/test_dtype/Makefile.in (revision 492) @@ -0,0 +1,33 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +INCDIR = $(srcdir)/../../src/lib +LIBDIR = ../../src/lib + +INCLUDES = -I$(INCDIR) + +CC = @MPICC@ +CFLAGS = @CFLAGS@ $(INCLUDES) + +SRCS = test_subarray.c test_darray.c test_nonblocking.c +OBJS = $(SRCS:.c=.o) +PROGS = test_subarray test_darray test_nonblocking +LDFLAGS = -L$(LIBDIR) +LIBS = -lpnetcdf + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROGS) + +test_subarray: test_subarray.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +test_darray: test_darray.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +test_nonblocking: test_nonblocking.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +clean: + rm -f $(OBJS) $(PROGS) *.nc Index: /tags/v1-0-3/test/test_dtype/test_darray.c =================================================================== --- /tags/v1-0-3/test/test_dtype/test_darray.c (revision 493) +++ /tags/v1-0-3/test/test_dtype/test_darray.c (revision 493) @@ -0,0 +1,441 @@ +#include +#include +#include +#include +#include +#include + +#include "test_dtype.h" + +/* Configurable test parameters: edit it as you wish */ +#define TEST_DEFAULT_FILE "test_darray.nc" /* file to be written/read */ +#define TEST_DIMS 3 /* number of dimensions */ +#define TEST_N 64 /* size for the shortest dimension of the array */ +#define TEST_M 0.9 /* size of each dimension is increasingly multiplied by M */ +#define TEST_ARRAY_ORDER MPI_ORDER_C + +int ndims = TEST_DIMS; +char *filename = TEST_DEFAULT_FILE; +int test_n = TEST_N; +double test_m = TEST_M; +int order = TEST_ARRAY_ORDER; + +void parse_args(int argc, char **argv, int rank) { + extern char * optarg; + int c; + + if (argc == 1) + return; + + while ((c=getopt(argc,argv,"h:f:d:n:m:o:"))!=-1) { + switch(c) { + case 'f': + filename = optarg; + break; + + case 'd': + ndims = atoi(optarg); + break; + + case 'n': + test_n = atoi(optarg); + break; + + case 'm': + test_m = atof(optarg); + break; + + case 'o': + if ( !strncmp(optarg, "MPI_ORDER_C", 11) || !strcmp(optarg, "0") ) + order = MPI_ORDER_C; + else if ( !strncmp(optarg, "MPI_ORDER_FORTRAN", 17) || + !strcmp(optarg, "1") ) + order = MPI_ORDER_FORTRAN; + else { + if (rank == 0) { + fprintf(stderr, + "Invalid order_of_array specified in command line args! \n"); + fprintf(stderr, + "[-o ] 0/1: MPI_ORDER_C/MPI_ORDER_FORTRAN\n"); + } + TEST_EXIT(-1); + } + break; + + case 'h': + default: + if (rank == 0) { + /* print help */ + printf("Usage: %s [options]\n", argv[0]); + printf("or %s [options]\n", argv[0]); + printf(" [-h] [-f ] [-d ]\n"); + printf(" [-n ] [-m ]\n"); + printf(" [-o ]\n\n"); + printf("\t[-h] print this help.\n"); + printf("\t[-f] filename to be used.\n"); + printf("\t NOTE: This test will create/overwrite the file!\n"); + printf("\t[-d] ndims of array to be tested. (int)\n"); + printf("\t[-n] size of the first array dimension. (int)\n"); + printf("\t[-m] multiplier for the size of each later dimension\n"); + printf("\t over the size of previous dimension. (int/float)\n"); + printf("\t[-o] memory layout order of the array\n"); + printf("\t 0/1 for MPI_ORDER_C/MPI_ORDER_FORTRAN.\n\n"); + } + + TEST_EXIT( c != 'h' ); + } + } + + return; +} + +void partition_array( /* input parameters : */ + int nprocs, int myrank, int ndims, int *array_of_sizes, + /* output parameters : */ + int *array_of_distribs, int *array_of_dargs, + MPI_Offset *local_starts, + MPI_Offset *local_edges, + MPI_Offset *local_strides, + int *array_of_psizes) +{ + int i; + int cycle, remain_cycle; + int pcoord; + + for (i=0; i=0; i--) { + /* compute the netCDF strided-subarray access parameters */ + pcoord = myrank % array_of_psizes[i]; + myrank /= array_of_psizes[i]; + local_starts[i] = (MPI_Offset)( (pcoord>=array_of_sizes[i])?0:pcoord ); + local_edges[i] = (MPI_Offset)( array_of_sizes[i]/array_of_psizes[i] ); + if ( local_edges[i]*array_of_psizes[i]+pcoord < array_of_sizes[i] ) + local_edges[i]++; + local_strides[i] = (MPI_Offset)array_of_psizes[i]; + } + + return; +} + +int main(int argc, char** argv) { + + int i; + double power_M; + int *array_of_sizes; + int *array_of_distribs, *array_of_dargs; + int *array_of_psizes; + int ncid, *dimids, varid_1, varid_2; + MPI_Offset *local_starts, *local_edges, *local_strides; + char dimname[20]; + ncmpi_type nc_etype; + MPI_Datatype mpi_etype, mpi_darray; + TEST_NATIVE_ETYPE *buf1, *buf2, *tmpbuf; + void *packbuf; + int packsz; + int packpos; + int total_sz, local_sz; + int nprocs, rank; + int status; + int success, successall; + int malloc_failure, malloc_failure_any; + int pass1 = 0, pass2 = 0; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + /* test initializations: nc_file, nc_variables, dimensions, arrays */ + + parse_args(argc, argv, rank); + TEST_SET_NCMPI_ETYPE(nc_etype, mpi_etype); +#ifdef TEST_NCTYPE + nc_etype = TEST_NCTYPE; +#endif + if (rank == 0) { + printf("testing memory darray layout ...\n"); + } + + status = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, + MPI_INFO_NULL, &ncid); + TEST_HANDLE_ERR(status); + + array_of_sizes = (int *) + malloc(sizeof(int)*ndims*5 + sizeof(MPI_Offset)*ndims*3); + array_of_distribs = array_of_sizes + ndims; + array_of_dargs = array_of_distribs + ndims; + array_of_psizes = array_of_dargs + ndims; + dimids = array_of_psizes + ndims; + local_starts = (MPI_Offset *)(dimids + ndims); + local_edges = local_starts + ndims; + local_strides = local_edges + ndims; + + total_sz = 1; + power_M = 1; + for (i=0; i (double)TEST_MAX_INT ){ + /* upper bound check */ + if (rank == 0) { + fprintf(stderr, "Total size of array is too big to be represented\n"); + fprintf(stderr, "Current size = %f, Max size = %d\n", + (double)total_sz*array_of_sizes[i], TEST_MAX_INT); + } + TEST_EXIT(-1); + } + total_sz *= array_of_sizes[i]; + sprintf(dimname, "dim_%d", i); + status = ncmpi_def_dim(ncid, dimname, + (MPI_Offset)array_of_sizes[i], dimids+i); + TEST_HANDLE_ERR(status); + } + + if (order == MPI_ORDER_FORTRAN) { + /* reverse the filearray dimension, since NC always use C ORDER */ + TEST_REVERSE(dimids, ndims, int); + } + + status = ncmpi_def_var(ncid, "var_1", nc_etype, ndims, dimids, &varid_1); + TEST_HANDLE_ERR(status); + + status = ncmpi_enddef(ncid); + TEST_HANDLE_ERR(status); + + if (rank == 0) { + printf("\t Filesize = %2.3fMB, MAX_Memory_needed = %2.3fMB\n\n", + 1*total_sz*TEST_NCTYPE_LEN(nc_etype)/1024.0/1024.0, + ( (2*total_sz + 4*total_sz/nprocs)*sizeof(TEST_NATIVE_ETYPE) + + total_sz*TEST_NCTYPE_LEN(nc_etype) )/1024.0/1024.0 ); + } + + buf1 = (TEST_NATIVE_ETYPE *)malloc(total_sz*sizeof(TEST_NATIVE_ETYPE)*2); + malloc_failure = (buf1 == NULL || + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2 > TEST_MAX_INT); + MPI_Allreduce(&malloc_failure, &malloc_failure_any, 1, MPI_INT, + MPI_LOR, MPI_COMM_WORLD); + if (malloc_failure_any) { + if (rank == 0) { + fprintf(stderr, "malloc(%2.3fMB) failed!\n", + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2/1024/1024); + fprintf(stderr, "The whole array may be too big for malloc to handle!\n"); fprintf(stderr, "Please choose smaller array size.\n"); + } + TEST_EXIT(-1); + } + + buf2 = buf1 + total_sz; + for (i=0; i +#include +#include +#include +#include +#include + +#include "test_dtype.h" + +/* Configurable test parameters: edit it as you wish */ +#define TEST_DEFAULT_FILE "test_subarray.nc" /* file to be written/read */ +#define TEST_DIMS 3 /* number of dimensions */ +#define TEST_N 17 /* size for the shortest dimension of the array */ +#define TEST_M 3 /* size of each dimension is increasingly multiplied by M */ +#define TEST_ARRAY_ORDER MPI_ORDER_C + +int ndims = TEST_DIMS; +char *filename = TEST_DEFAULT_FILE; +int test_n = TEST_N; +double test_m = TEST_M; +int order = TEST_ARRAY_ORDER; + +void parse_args(int argc, char **argv, int rank) { + extern char * optarg; + int c; + + if (argc == 1) + return; + + while ((c=getopt(argc,argv,"h:f:d:n:m:o:"))!=-1) { + switch(c) { + case 'f': + filename = optarg; + break; + + case 'd': + ndims = atoi(optarg); + break; + + case 'n': + test_n = atoi(optarg); + break; + + case 'm': + test_m = atof(optarg); + break; + + case 'o': + if ( !strncmp(optarg, "MPI_ORDER_C", 11) || !strcmp(optarg, "0") ) + order = MPI_ORDER_C; + else if ( !strncmp(optarg, "MPI_ORDER_FORTRAN", 17) || + !strcmp(optarg, "1") ) + order = MPI_ORDER_FORTRAN; + else { + if (rank == 0) { + fprintf(stderr, + "Invalid order_of_array specified in command line args! \n"); + fprintf(stderr, + "[-o ] 0/1: MPI_ORDER_C/MPI_ORDER_FORTRAN\n"); + } + TEST_EXIT(-1); + } + break; + + case 'h': + default: + if (rank == 0) { + /* print help */ + printf("Usage: %s [options]\n", argv[0]); + printf("or %s [options]\n", argv[0]); + printf(" [-h] [-f ] [-d ]\n"); + printf(" [-n ] [-m ]\n"); + printf(" [-o ]\n\n"); + printf("\t[-help] print this help.\n"); + printf("\t[-f] filename to be used.\n"); + printf("\t NOTE: This test will create/overwrite the file!\n"); + printf("\t[-d] ndims of array to be tested. (int)\n"); + printf("\t[-n] size of the first array dimension. (int)\n"); + printf("\t[-m] multiplier for the size of each later dimension\n"); + printf("\t over the size of previous dimension. (int/float)\n"); + printf("\t[-o] memory layout order of the array\n"); + printf("\t 0/1 for MPI_ORDER_C/MPI_ORDER_FORTRAN.\n\n"); + } + + TEST_EXIT( c != 'h' ); + } + } + + return; +} + +void partition_array(int ndims, + int *total_sizes, + int *local_subsizes, + int *local_starts, + int nprocs, + int myrank) +{ + int k; + int odd; + + for (k=0; k 1) { + + /* cut this dimension into two halves: + - [0 : ceiling{nprocs/2}) get first half + - [ceiling{nprocs/2} : nprocs) get second half + */ + + odd = local_subsizes[k] % 2; + local_subsizes[k] /= 2; + if (myrank >= (nprocs+1)/2) { + local_starts[k] += local_subsizes[k]; + local_subsizes[k] += odd; + myrank -= (nprocs+1)/2; /* rank_in_myhalfgroup */ + nprocs /= 2; /* nprocs_in_myhalfgroup */ + } else { + nprocs = (nprocs+1)/2; /* nprocs_in_myhalfgroup */ + } + + /* move to the next dimension */ + if (--k < 0) + k = ndims-1; + } + +} + +int main(int argc, char** argv) { + + int i; + double power_M; + int *array_of_sizes, *array_of_subsizes, *array_of_starts; + int ncid, *dimids, varid_1, varid_2; + MPI_Offset *local_starts, *local_edges, *stride, *imap; + char dimname[20]; + ncmpi_type nc_etype; + MPI_Datatype mpi_etype, mpi_subarray; + TEST_NATIVE_ETYPE *buf1, *buf2, *tmpbuf; + void *packbuf; + int packsz; + int packpos; + int total_sz, local_sz; + int nprocs, rank; + int status; + int success, successall; + int malloc_failure, malloc_failure_any; + NCMPI_Request request; + + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + /* test initializations: nc_file, nc_variables, dimensions, arrays */ + + parse_args(argc, argv, rank); + TEST_SET_NCMPI_ETYPE(nc_etype, mpi_etype); +#ifdef TEST_NCTYPE + nc_etype = TEST_NCTYPE; +#endif + if (rank == 0) { + printf("testing memory subarray layout ...\n"); + } + + status = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, + MPI_INFO_NULL, &ncid); + TEST_HANDLE_ERR(status); + + array_of_sizes = (int *) + malloc(sizeof(int)*ndims*4 + sizeof(MPI_Offset)*ndims*4); + array_of_subsizes = array_of_sizes + ndims; + array_of_starts = array_of_subsizes + ndims; + dimids = array_of_starts + ndims; + local_starts = (MPI_Offset *)(dimids + ndims); + local_edges = local_starts + ndims; + stride = local_edges + ndims; + imap = stride + ndims; + + total_sz = 1; + power_M = 1; + for (i=0; i (double)TEST_MAX_INT ){ + /* upper bound check */ + if (rank == 0) { + fprintf(stderr, "Total size of array is too big to be represented\n"); + fprintf(stderr, "Current size = %f, Max size = %d\n", + (double)total_sz*array_of_sizes[i], TEST_MAX_INT); + } + TEST_EXIT(-1); + } + total_sz *= array_of_sizes[i]; + sprintf(dimname, "dim_%d", i); + status = ncmpi_def_dim(ncid, dimname, + (MPI_Offset)array_of_sizes[i], dimids+i); + TEST_HANDLE_ERR(status); + } + + if (order == MPI_ORDER_FORTRAN) { + /* reverse the filearray dimension, since NC always use C ORDER */ + TEST_REVERSE(dimids, ndims, int); + } + + status = ncmpi_def_var(ncid, "var_1", nc_etype, ndims, dimids, &varid_1); + TEST_HANDLE_ERR(status); + + TEST_REVERSE(dimids, ndims, int); + status = ncmpi_def_var(ncid, "var_2", nc_etype, ndims, dimids, &varid_2); + TEST_HANDLE_ERR(status); + + status = ncmpi_enddef(ncid); + TEST_HANDLE_ERR(status); + + if (rank == 0) { + printf("\t Filesize = %2.3fMB, MAX_Memory_needed = %2.3fMB\n\n", + 2*total_sz*TEST_NCTYPE_LEN(nc_etype)/1024.0/1024.0, + ( (2*total_sz + 4*total_sz/nprocs)*sizeof(TEST_NATIVE_ETYPE) + + total_sz*TEST_NCTYPE_LEN(nc_etype) )/1024.0/1024.0); + } + + buf1 = (TEST_NATIVE_ETYPE *)malloc(total_sz*sizeof(TEST_NATIVE_ETYPE)*2); + malloc_failure = (buf1 == NULL || + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2 > TEST_MAX_INT); + MPI_Allreduce(&malloc_failure, &malloc_failure_any, 1, MPI_INT, + MPI_LOR, MPI_COMM_WORLD); + if (malloc_failure_any) { + if (rank == 0) { + fprintf(stderr, "malloc(%2.3fMB) failed!\n", + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2/1024/1024); + fprintf(stderr, "The whole array may be too big for malloc to handle!\n"); fprintf(stderr, "Please choose smaller array size.\n"); + } + TEST_EXIT(-1); + } + + buf2 = buf1 + total_sz; + for (i=0; i +#include +#include +#include +#include +#include + +#include "test_dtype.h" + +/* Configurable test parameters: edit it as you wish */ +#define TEST_DEFAULT_FILE "test_subarray.nc" /* file to be written/read */ +#define TEST_DIMS 3 /* number of dimensions */ +#define TEST_N 17 /* size for the shortest dimension of the array */ +#define TEST_M 3 /* size of each dimension is increasingly multiplied by M */ +#define TEST_ARRAY_ORDER MPI_ORDER_C + +int ndims = TEST_DIMS; +char *filename = TEST_DEFAULT_FILE; +int test_n = TEST_N; +double test_m = TEST_M; +int order = TEST_ARRAY_ORDER; + +void parse_args(int argc, char **argv, int rank) { + extern char * optarg; + int c; + + if (argc == 1) + return; + + while ((c=getopt(argc,argv,"h:f:d:n:m:o:"))!=-1) { + switch(c) { + case 'f': + filename = optarg; + break; + + case 'd': + ndims = atoi(optarg); + break; + + case 'n': + test_n = atoi(optarg); + break; + + case 'm': + test_m = atof(optarg); + break; + + case 'o': + if ( !strncmp(optarg, "MPI_ORDER_C", 11) || !strcmp(optarg, "0") ) + order = MPI_ORDER_C; + else if ( !strncmp(optarg, "MPI_ORDER_FORTRAN", 17) || + !strcmp(optarg, "1") ) + order = MPI_ORDER_FORTRAN; + else { + if (rank == 0) { + fprintf(stderr, + "Invalid order_of_array specified in command line args! \n"); + fprintf(stderr, + "[-o ] 0/1: MPI_ORDER_C/MPI_ORDER_FORTRAN\n"); + } + TEST_EXIT(-1); + } + break; + + case 'h': + default: + if (rank == 0) { + /* print help */ + printf("Usage: %s [options]\n", argv[0]); + printf("or %s [options]\n", argv[0]); + printf(" [-h] [-f ] [-d ]\n"); + printf(" [-n ] [-m ]\n"); + printf(" [-o ]\n\n"); + printf("\t[-help] print this help.\n"); + printf("\t[-f] filename to be used.\n"); + printf("\t NOTE: This test will create/overwrite the file!\n"); + printf("\t[-d] ndims of array to be tested. (int)\n"); + printf("\t[-n] size of the first array dimension. (int)\n"); + printf("\t[-m] multiplier for the size of each later dimension\n"); + printf("\t over the size of previous dimension. (int/float)\n"); + printf("\t[-o] memory layout order of the array\n"); + printf("\t 0/1 for MPI_ORDER_C/MPI_ORDER_FORTRAN.\n\n"); + } + + TEST_EXIT( c != 'h' ); + } + } + + return; +} + +void partition_array(int ndims, + int *total_sizes, + int *local_subsizes, + int *local_starts, + int nprocs, + int myrank) +{ + int k; + int odd; + + for (k=0; k 1) { + + /* cut this dimension into two halves: + - [0 : ceiling{nprocs/2}) get first half + - [ceiling{nprocs/2} : nprocs) get second half + */ + + odd = local_subsizes[k] % 2; + local_subsizes[k] /= 2; + if (myrank >= (nprocs+1)/2) { + local_starts[k] += local_subsizes[k]; + local_subsizes[k] += odd; + myrank -= (nprocs+1)/2; /* rank_in_myhalfgroup */ + nprocs /= 2; /* nprocs_in_myhalfgroup */ + } else { + nprocs = (nprocs+1)/2; /* nprocs_in_myhalfgroup */ + } + + /* move to the next dimension */ + if (--k < 0) + k = ndims-1; + } + +} + +int main(int argc, char** argv) { + + int i; + double power_M; + int *array_of_sizes, *array_of_subsizes, *array_of_starts; + int ncid, *dimids, varid_1, varid_2; + MPI_Offset *local_starts, *local_edges, *stride, *imap; + char dimname[20]; + ncmpi_type nc_etype; + MPI_Datatype mpi_etype, mpi_subarray; + TEST_NATIVE_ETYPE *buf1, *buf2, *tmpbuf; + void *packbuf; + int packsz; + int packpos; + int total_sz, local_sz; + int nprocs, rank; + int status; + int success, successall; + int malloc_failure, malloc_failure_any; + int pass1 = 0, pass2 = 0, pass3 = 0; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + /* test initializations: nc_file, nc_variables, dimensions, arrays */ + + parse_args(argc, argv, rank); + TEST_SET_NCMPI_ETYPE(nc_etype, mpi_etype); +#ifdef TEST_NCTYPE + nc_etype = TEST_NCTYPE; +#endif + if (rank == 0) { + printf("testing memory subarray layout ...\n"); + } + + status = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, + MPI_INFO_NULL, &ncid); + TEST_HANDLE_ERR(status); + + array_of_sizes = (int *) + malloc(sizeof(int)*ndims*4 + sizeof(MPI_Offset)*ndims*4); + array_of_subsizes = array_of_sizes + ndims; + array_of_starts = array_of_subsizes + ndims; + dimids = array_of_starts + ndims; + local_starts = (MPI_Offset *)(dimids + ndims); + local_edges = local_starts + ndims; + stride = local_edges + ndims; + imap = stride + ndims; + + total_sz = 1; + power_M = 1; + for (i=0; i (double)TEST_MAX_INT ){ + /* upper bound check */ + if (rank == 0) { + fprintf(stderr, "Total size of array is too big to be represented\n"); + fprintf(stderr, "Current size = %f, Max size = %d\n", + (double)total_sz*array_of_sizes[i], TEST_MAX_INT); + } + TEST_EXIT(-1); + } + total_sz *= array_of_sizes[i]; + sprintf(dimname, "dim_%d", i); + status = ncmpi_def_dim(ncid, dimname, + (MPI_Offset)array_of_sizes[i], dimids+i); + TEST_HANDLE_ERR(status); + } + + if (order == MPI_ORDER_FORTRAN) { + /* reverse the filearray dimension, since NC always use C ORDER */ + TEST_REVERSE(dimids, ndims, int); + } + + status = ncmpi_def_var(ncid, "var_1", nc_etype, ndims, dimids, &varid_1); + TEST_HANDLE_ERR(status); + + TEST_REVERSE(dimids, ndims, int); + status = ncmpi_def_var(ncid, "var_2", nc_etype, ndims, dimids, &varid_2); + TEST_HANDLE_ERR(status); + + status = ncmpi_enddef(ncid); + TEST_HANDLE_ERR(status); + + if (rank == 0) { + printf("\t Filesize = %2.3fMB, MAX_Memory_needed = %2.3fMB\n\n", + 2*total_sz*TEST_NCTYPE_LEN(nc_etype)/1024.0/1024.0, + ( (2*total_sz + 4*total_sz/nprocs)*sizeof(TEST_NATIVE_ETYPE) + + total_sz*TEST_NCTYPE_LEN(nc_etype) )/1024.0/1024.0); + } + + buf1 = (TEST_NATIVE_ETYPE *)malloc(total_sz*sizeof(TEST_NATIVE_ETYPE)*2); + malloc_failure = (buf1 == NULL || + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2 > TEST_MAX_INT); + MPI_Allreduce(&malloc_failure, &malloc_failure_any, 1, MPI_INT, + MPI_LOR, MPI_COMM_WORLD); + if (malloc_failure_any) { + if (rank == 0) { + fprintf(stderr, "malloc(%2.3fMB) failed!\n", + (float)total_sz*sizeof(TEST_NATIVE_ETYPE)*2/1024/1024); + fprintf(stderr, "The whole array may be too big for malloc to handle!\n"); fprintf(stderr, "Please choose smaller array size.\n"); + } + TEST_EXIT(-1); + } + + buf2 = buf1 + total_sz; + for (i=0; i +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + float data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + 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 write ... "); + parse_write_args(argc, argv, rank, &opts); + + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_FLOAT, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_FLOAT, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_FLOAT, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_FLOAT, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: non-collective + */ + + status = ncmpi_begin_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_put_vara_float(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_end_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_float/test_read_indep.c =================================================================== --- /tags/v1-0-3/test/test_float/test_read_indep.c (revision 387) +++ /tags/v1-0-3/test/test_float/test_read_indep.c (revision 387) @@ -0,0 +1,362 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_float.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * float square(x, y); + * squre: description = "2-D integer array"; + * + * float cube(x,y,z); + * + * float time(time); // coordinate & record variable + * + * float xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_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]; + int isRecvar; + 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_float.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: + ; /* TODO: 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++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + 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); + + /** + * 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; +} Index: /tags/v1-0-3/test/test_float/test_write.c =================================================================== --- /tags/v1-0-3/test/test_float/test_write.c (revision 363) +++ /tags/v1-0-3/test/test_float/test_write.c (revision 363) @@ -0,0 +1,233 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * float square(x, y); + * squre: description = "2-D integer array"; + * + * float cube(x,y,z); + * + * float time(time); // coordinate & record variable + * + * float xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to write variable data and only + * deals with float variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + float data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) + fprintf(stderr, "Testing write ... "); + + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_FLOAT, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_FLOAT, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_FLOAT, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_FLOAT, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: collective + */ + + status = ncmpi_put_vara_float_all(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_float/test_read.c =================================================================== --- /tags/v1-0-3/test/test_float/test_read.c (revision 387) +++ /tags/v1-0-3/test/test_float/test_read.c (revision 387) @@ -0,0 +1,353 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_float.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * float square(x, y); + * squre: description = "2-D integer array"; + * + * float cube(x,y,z); + * + * float time(time); // coordinate & record variable + * + * float xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to read/write variable data and + * only deals with float variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_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]; + int isRecvar; + 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 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_float.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: + ; + /* TODO: 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: + ; /* TODO: 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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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: collective + */ + + for (i = 0; i < NC_MAX_VAR_DIMS; i++) + start[i] = 0; + for (i = 0; i < nvars; i++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + switch (vartypes[i]) { + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vara_short_all(ncid1, i, start, shape, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_short_all(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_all(ncid1, i, start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(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_all(ncid1, i, start, shape, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(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_all(ncid1, i, start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid2, varids[i], + start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; /* TODO: handle unexpected types */ + } + } + + /** + * 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; +} Index: /tags/v1-0-3/test/test_float/README =================================================================== --- /tags/v1-0-3/test/test_float/README (revision 15) +++ /tags/v1-0-3/test/test_float/README (revision 15) @@ -0,0 +1,3 @@ +These examples test data transfers of: + + "file NC_FLOAT var" <---> "memory float" Index: /tags/v1-0-3/test/common/testutils.c =================================================================== --- /tags/v1-0-3/test/common/testutils.c (revision 117) +++ /tags/v1-0-3/test/common/testutils.c (revision 117) @@ -0,0 +1,48 @@ +#include +#include +#include +#include "mpi.h" +#include "testutils.h" + +void parse_read_args(int argc, char **argv, int rank, params *p) +{ + int inlen, outlen; + if ( rank == 0 ) { + if (argc == 3 ) { + strncpy(p->infname, argv[1], PATH_MAX); + strncpy(p->outfname, argv[2], PATH_MAX); + } else if (argc == 0) { + strncpy(p->infname, "pvfs:../data/test_double.nc", + PATH_MAX); + strncpy(p->outfname, "pvfs:testread.nc", PATH_MAX); + } else { + fprintf(stderr, "Usage: %s: \n", + argv[0]); + MPI_Abort(MPI_COMM_WORLD, 1); + } + inlen = strlen(p->infname); + outlen = strlen(p->outfname); + } + MPI_Bcast(&inlen, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(p->infname, inlen+1, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(&outlen, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(p->outfname, outlen+1, MPI_CHAR, 0, MPI_COMM_WORLD); +} + +void parse_write_args(int argc, char **argv, int rank, params *p) +{ + int outlen; + if ( rank == 0 ) { + if (argc == 2 ) { + strncpy(p->outfname, argv[1], PATH_MAX); + } else if (argc == 0) { + strncpy(p->outfname, "pvfs:testwrite.nc", PATH_MAX); + } else { + fprintf(stderr, "Usage: %s: \n", argv[0]); + MPI_Abort(MPI_COMM_WORLD, 1); + } + outlen = strlen(p->outfname); + } + MPI_Bcast(&outlen, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(p->outfname, outlen+1, MPI_CHAR, 0, MPI_COMM_WORLD); +} Index: /tags/v1-0-3/test/common/Makefile.in =================================================================== --- /tags/v1-0-3/test/common/Makefile.in (revision 115) +++ /tags/v1-0-3/test/common/Makefile.in (revision 115) @@ -0,0 +1,16 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @MPICC@ +CFLAGS = @CFLAGS@ + +OBJS = testutils.o + +all: libtestutils.a + +libtestutils.a: $(OBJS) + ar cru libtestutils.a $(OBJS) +testutils.o: testutils.c testutils.h + +clean: + rm -f *.o *.a Index: /tags/v1-0-3/test/common/testutils.h =================================================================== --- /tags/v1-0-3/test/common/testutils.h (revision 25) +++ /tags/v1-0-3/test/common/testutils.h (revision 25) @@ -0,0 +1,13 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#include + +typedef struct { + char infname[PATH_MAX]; + char outfname[PATH_MAX]; +} params; + +void parse_read_args(int argc, char **argv, int rank, params *p); +void parse_write_args(int argc, char **argv, int rank, params *p); +#endif Index: /tags/v1-0-3/test/test_double/Makefile.in =================================================================== --- /tags/v1-0-3/test/test_double/Makefile.in (revision 555) +++ /tags/v1-0-3/test/test_double/Makefile.in (revision 555) @@ -0,0 +1,33 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +INCDIR = $(srcdir)/../../src/lib +LIBDIR = ../../src/lib + +INCLUDES = -I$(INCDIR) -I$(srcdir)/../common + +CC = @MPICC@ +CFLAGS = @CFLAGS@ $(INCLUDES) + +SRCS = test_read.c test_read_indep.c test_write.c test_write_indep.c +OBJS = $(SRCS:.c=.o) +PROGS = test_read test_read_indep test_write test_write_indep +LDFLAGS = -L$(LIBDIR) -L../common @LDFLAGS@ +LIBS = -lpnetcdf -ltestutils @LIBS@ + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROGS) + +test_read: test_read.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_read_indep: test_read_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write: test_write.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write_indep: test_write_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +clean: + rm -f $(OBJS) $(PROGS) *.nc Index: /tags/v1-0-3/test/test_double/test_write_indep.c =================================================================== --- /tags/v1-0-3/test/test_double/test_write_indep.c (revision 365) +++ /tags/v1-0-3/test/test_double/test_write_indep.c (revision 365) @@ -0,0 +1,304 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to write variable data and only + * deals with double variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + double data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Info info; + params opts; + + 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 write ... "); + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + MPI_Info_create(&info); + MPI_Info_set(info, "striping_factor", "4"); + MPI_Info_set(info, "striping_unit", "20000"); + MPI_Info_set(info, "start_iodevice", "0"); + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, info, &ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_DOUBLE, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_DOUBLE, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_DOUBLE, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_DOUBLE, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: non-collective + */ + + status = ncmpi_begin_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_put_vara_double(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + +{ + /** + * Change a single element and then change it back + * Access Method: single value + * Data Mode API: non-collective + */ + + double singlevalue = 0; + + ncmpi_sync(ncid); + + status = ncmpi_put_var1_double(ncid, square_id, + square_start, &singlevalue); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_put_var1_double(ncid, time_id, + time_start, &singlevalue); + if (status != NC_NOERR) handle_error(status); + + ncmpi_sync(ncid); + + singlevalue = square_start[0]*100 + square_start[1]; + status = ncmpi_put_var1_double(ncid, square_id, + square_start, &singlevalue); + if (status != NC_NOERR) handle_error(status); + + singlevalue = time_start[0]; + status = ncmpi_put_var1_double(ncid, time_id, + time_start, &singlevalue); + if (status != NC_NOERR) handle_error(status); +} + +{ + /** + * Change the whole array for time[] and then change it back + * Access Method: whole array + * Data Mode API: non-collective + */ + + ncmpi_sync(ncid); + + for (i = 0; i < 100; i++ ) + buffer[i] = 0; + + if (rank == 0) { + status = ncmpi_put_var_double(ncid, time_id, buffer); + if (status != NC_NOERR) handle_error(status); + } + + ncmpi_sync(ncid); + + for (i=0; i<100; i++) + buffer[i] = i; + + if (rank == 1) { + status = ncmpi_put_var_double(ncid, time_id, buffer); + if (status != NC_NOERR) handle_error(status); + } +} + + status = ncmpi_end_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + MPI_Info_free(&info); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} Index: /tags/v1-0-3/test/test_double/test_read_indep.c =================================================================== --- /tags/v1-0-3/test/test_double/test_read_indep.c (revision 560) +++ /tags/v1-0-3/test/test_double/test_read_indep.c (revision 560) @@ -0,0 +1,420 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_double.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to read/write variable data and + * only deals with double variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototypes for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_type type, vartypes[NC_MAX_VARS]; + int attlen, dimlen; + MPI_Offset shape[NC_MAX_VAR_DIMS], varsize, start[NC_MAX_VAR_DIMS]; + MPI_Offset stride[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]; + int isRecvar; + 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_double.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 errors */ + } + } + + /* 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 errors */ + } + } + } + + /** + * 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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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, (Cyclic, *, *), 25*100*100 from 100*100*100 + * time: 1-D, Cyclic, 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++) { + isRecvar = 0; + 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; + if (vardims[i][j] == unlimdimid) { + isRecvar = 1; + start[j] = rank; + stride[j] = nprocs; + } else { + start[j] = shape[j] * rank; + } + } else { + stride[j] = 1; + } + varsize *= shape[j]; + } + if (isRecvar) switch (vartypes[i]) { + + /* strided access for record variables */ + + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vars_short(ncid1, i, start, shape, stride, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_short(ncid2, varids[i], + start, shape, stride, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_INT: + valuep = (void *)malloc(varsize * sizeof(int)); + status = ncmpi_get_vars_int(ncid1, i, start, shape, stride, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_int(ncid2, varids[i], + start, shape, stride, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_FLOAT: + valuep = (void *)malloc(varsize * sizeof(float)); + status = ncmpi_get_vars_float(ncid1, i, start, shape, stride, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_float(ncid2, varids[i], + start, shape, stride, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_DOUBLE: + valuep = (void *)malloc(varsize * sizeof(double)); + status = ncmpi_get_vars_double(ncid1, i, start, shape, stride, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_double(ncid2, varids[i], + start, shape, stride, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; + /* handle unexpected errors */ + } + else switch (vartypes[i]) { + + /* subarray access for non-record variable */ + + 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 errors */ + } + } + + 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); + + /** + * 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; +} Index: /tags/v1-0-3/test/test_double/test_write.c =================================================================== --- /tags/v1-0-3/test/test_double/test_write.c (revision 365) +++ /tags/v1-0-3/test/test_double/test_write.c (revision 365) @@ -0,0 +1,243 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to write variable data and only + * deals with double variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset square_stride[2] = {2, 2}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + double data[100][50][50], buffer[100]; + double stride_2d_data[50][50]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) + fprintf(stderr, "Testing write ... "); + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_DOUBLE, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_DOUBLE, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_DOUBLE, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_DOUBLE, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Cyclic, Cyclic), 50*50 from 100*100, strided access + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + /* square_start[0] = */ + cube_start[1] = xytime_start[1] = (rank/2) * 50; + /* square_start[1] = */ + cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + square_start[0] = rank/2; + square_start[1] = rank%2; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = cube_start[1]; j < cube_start[1]+cube_count[1]; j++ ) + for ( k = cube_start[2]; k < cube_start[2]+cube_count[2]; k++ ) + data[i][j-cube_start[1]][k-cube_start[2]] = i*100*100 + j*100 + k; + + /* Data for variable: square */ + for ( i = 0; i < 50; i ++ ) + for ( j = 0; j < 50; j++ ) + stride_2d_data[i][j] = (2*i + rank/2)*100 + (2*j + rank%2); + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: collective + */ + + status = ncmpi_put_vars_double_all(ncid, square_id, + square_start, square_count, square_stride, + &stride_2d_data[0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_double/test_read.c =================================================================== --- /tags/v1-0-3/test/test_double/test_read.c (revision 560) +++ /tags/v1-0-3/test/test_double/test_read.c (revision 560) @@ -0,0 +1,411 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_double.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * double square(x, y); + * squre: description = "2-D integer array"; + * + * double cube(x,y,z); + * + * double time(time); // coordinate & record variable + * + * double xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototypes for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_type type, vartypes[NC_MAX_VARS]; + MPI_Offset attlen, dimlen; + MPI_Offset shape[NC_MAX_VAR_DIMS], varsize, start[NC_MAX_VAR_DIMS]; + MPI_Offset stride[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]; + int isRecvar; + 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 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_double.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: + ; + /* XXX: handle default case */ + } + } + + /* 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: + ; + /* XXX: 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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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, (Cyclic, *, *), 25*100*100 from 100*100*100 + * time: 1-D, Cyclic, 25 from 100 + * + * Data Mode API: collective + */ + + for (i = 0; i < NC_MAX_VAR_DIMS; i++) + start[i] = 0; + for (i = 0; i < nvars; i++) { + isRecvar = 0; + 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; + if (vardims[i][j] == unlimdimid) { + isRecvar = 1; + start[j] = rank; + stride[j] = nprocs; + } else { + start[j] = shape[j] * rank; + } + } else { + stride[j] = 1; + } + varsize *= shape[j]; + } + if (isRecvar) switch (vartypes[i]) { + + /* strided access for record variable */ + + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vars_short_all(ncid1, i, start, shape, stride, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_short_all(ncid2, varids[i], + start, shape, stride, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_INT: + valuep = (void *)malloc(varsize * sizeof(int)); + status = ncmpi_get_vars_int_all(ncid1, i, start, shape, stride, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_int_all(ncid2, varids[i], + start, shape, stride, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_FLOAT: + valuep = (void *)malloc(varsize * sizeof(float)); + status = ncmpi_get_vars_float_all(ncid1, i, start, shape, stride, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_float_all(ncid2, varids[i], + start, shape, stride, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + case NC_DOUBLE: + valuep = (void *)malloc(varsize * sizeof(double)); + status = ncmpi_get_vars_double_all(ncid1, i, start, shape, stride, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vars_double_all(ncid2, varids[i], + start, shape, stride, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; + /* XXX: handle unexpected types */ + } + else switch (vartypes[i]) { + + /* subarray access for non-record variable */ + + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vara_short_all(ncid1, i, start, shape, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_short_all(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_all(ncid1, i, start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(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_all(ncid1, i, start, shape, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(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_all(ncid1, i, start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid2, varids[i], + start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; + /* Handle unexpected types */ + + } + } + + /** + * 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; +} Index: /tags/v1-0-3/test/test_double/README =================================================================== --- /tags/v1-0-3/test/test_double/README (revision 15) +++ /tags/v1-0-3/test/test_double/README (revision 15) @@ -0,0 +1,3 @@ +These examples test data transfers of: + + "file NC_DOUBLE var" <---> "memory double" Index: /tags/v1-0-3/test/test_int/Makefile.in =================================================================== --- /tags/v1-0-3/test/test_int/Makefile.in (revision 209) +++ /tags/v1-0-3/test/test_int/Makefile.in (revision 209) @@ -0,0 +1,33 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +INCDIR = $(srcdir)/../../src/lib +LIBDIR = ../../src/lib + +INCLUDES = -I$(INCDIR) -I$(srcdir)/../common + +CC = @MPICC@ +CFLAGS = @CFLAGS@ $(INCLUDES) + +SRCS = test_read.c test_read_indep.c test_write.c test_write_indep.c +OBJS = $(SRCS:.c=.o) +PROGS = test_read test_read_indep test_write test_write_indep +LDFLAGS = -L$(LIBDIR) -L..//common @LDFLAGS@ +LIBS = -lpnetcdf -ltestutils @LIBS@ + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROGS) + +test_read: test_read.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_read_indep: test_read_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write: test_write.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +test_write_indep: test_write_indep.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) + +clean: + rm -f $(OBJS) $(PROGS) *.nc Index: /tags/v1-0-3/test/test_int/header.txt =================================================================== --- /tags/v1-0-3/test/test_int/header.txt (revision 15) +++ /tags/v1-0-3/test/test_int/header.txt (revision 15) @@ -0,0 +1,67 @@ +0000000 C D F 001 \0 \0 \0 d \0 \0 \0 \n \0 \0 \0 004 + 4344 4601 0000 0064 0000 000a 0000 0004 + 17220 17921 00000 00100 00000 00010 00000 00004 +0000020 \0 \0 \0 001 x \0 \0 \0 \0 \0 \0 d \0 \0 \0 001 + 0000 0001 7800 0000 0000 0064 0000 0001 + 00000 00001 30720 00000 00000 00100 00000 00001 +0000040 y \0 \0 \0 \0 \0 \0 d \0 \0 \0 001 z \0 \0 \0 + 7900 0000 0000 0064 0000 0001 7a00 0000 + 30976 00000 00000 00100 00000 00001 31232 00000 +0000060 \0 \0 \0 d \0 \0 \0 004 t i m e \0 \0 \0 \0 + 0000 0064 0000 0004 7469 6d65 0000 0000 + 00000 00100 00000 00004 29801 28005 00000 00000 +0000100 \0 \0 \0 \f \0 \0 \0 001 \0 \0 \0 005 t i t l + 0000 000c 0000 0001 0000 0005 7469 746c + 00000 00012 00000 00001 00000 00005 29801 29804 +0000120 e \0 \0 \0 \0 \0 \0 002 \0 \0 \0 026 e x a m + 6500 0000 0000 0002 0000 0016 6578 616d + 25856 00000 00000 00002 00000 00022 25976 24941 +0000140 p l e n e t C D F d a t a s + 706c 6520 6e65 7443 4446 2064 6174 6173 + 28780 25888 28261 29763 17478 08292 24948 24947 +0000160 e t \0 \0 \0 \0 \0 013 \0 \0 \0 004 \0 \0 \0 006 + 6574 0000 0000 000b 0000 0004 0000 0006 + 25972 00000 00000 00011 00000 00004 00000 00006 +0000200 s q u a r e \0 \0 \0 \0 \0 002 \0 \0 \0 \0 + 7371 7561 7265 0000 0000 0002 0000 0000 + 29553 30049 29285 00000 00000 00002 00000 00000 +0000220 \0 \0 \0 001 \0 \0 \0 \f \0 \0 \0 001 \0 \0 \0 013 + 0000 0001 0000 000c 0000 0001 0000 000b + 00000 00001 00000 00012 00000 00001 00000 00011 +0000240 d e s c r i p t i o n \0 \0 \0 \0 002 + 6465 7363 7269 7074 696f 6e00 0000 0002 + 25701 29539 29289 28788 26991 28160 00000 00002 +0000260 \0 \0 \0 021 2 - D i n t e g e r + 0000 0011 322d 4420 696e 7465 6765 7220 + 00000 00017 12845 17440 26990 29797 26469 29216 +0000300 a r r a y \0 \0 \0 \0 \0 \0 004 \0 \0 234 @ + 6172 7261 7900 0000 0000 0004 0000 9c40 + 24946 29281 30976 00000 00000 00004 00000 -25536 +0000320 \0 \0 001 T \0 \0 \0 004 c u b e \0 \0 \0 003 + 0000 0154 0000 0004 6375 6265 0000 0003 + 00000 00340 00000 00004 25461 25189 00000 00003 +0000340 \0 \0 \0 \0 \0 \0 \0 001 \0 \0 \0 002 \0 \0 \0 \0 + 0000 0000 0000 0001 0000 0002 0000 0000 + 00000 00000 00000 00001 00000 00002 00000 00000 +0000360 \0 \0 \0 \0 \0 \0 \0 004 \0 = \t \0 \0 \0 235 224 + 0000 0000 0000 0004 003d 0900 0000 9d94 + 00000 00000 00000 00004 00061 02304 00000 -25196 +0000400 \0 \0 \0 004 t i m e \0 \0 \0 001 \0 \0 \0 003 + 0000 0004 7469 6d65 0000 0001 0000 0003 + 00000 00004 29801 28005 00000 00001 00000 00003 +0000420 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 004 \0 \0 \0 004 + 0000 0000 0000 0000 0000 0004 0000 0004 + 00000 00000 00000 00000 00000 00004 00000 00004 +0000440 \0 = 246 224 \0 \0 \0 006 x y t i m e \0 \0 + 003d a694 0000 0006 7879 7469 6d65 0000 + 00061 -22892 00000 00006 30841 29801 28005 00000 +0000460 \0 \0 \0 003 \0 \0 \0 003 \0 \0 \0 \0 \0 \0 \0 001 + 0000 0003 0000 0003 0000 0000 0000 0001 + 00000 00003 00000 00003 00000 00000 00000 00001 +0000500 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 004 \0 \0 234 @ + 0000 0000 0000 0000 0000 0004 0000 9c40 + 00000 00000 00000 00000 00000 00004 00000 -25536 +0000520 \0 = 246 230 + 003d a698 + 00061 -22888 +0000524 Index: /tags/v1-0-3/test/test_int/test_write_indep.c =================================================================== --- /tags/v1-0-3/test/test_int/test_write_indep.c (revision 364) +++ /tags/v1-0-3/test/test_int/test_write_indep.c (revision 364) @@ -0,0 +1,247 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * int square(x, y); + * squre: description = "2-D integer array"; + * + * int cube(x,y,z); + * + * int time(time); // coordinate & record variable + * + * int xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to write variable data and only + * deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + int data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + params opts; + + 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 write ... "); + parse_write_args(argc, argv, rank, &opts); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_INT, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_INT, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_INT, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_INT, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + +/* + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); +*/ + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: non-collective + */ + + status = ncmpi_begin_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_put_vara_int(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + + status = ncmpi_end_indep_data(ncid); + if (status != NC_NOERR) handle_error(status); + +status = ncmpi_redef(ncid); +if (status != NC_NOERR) handle_error(status); +status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); +if (status != NC_NOERR) handle_error(status); +status = ncmpi_enddef(ncid); +if (status != NC_NOERR) handle_error(status); + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +if (rank == 0) + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_int/test_read_indep.c =================================================================== --- /tags/v1-0-3/test/test_int/test_read_indep.c (revision 388) +++ /tags/v1-0-3/test/test_int/test_read_indep.c (revision 388) @@ -0,0 +1,363 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_int.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * int square(x, y); + * squre: description = "2-D integer array"; + * + * int cube(x,y,z); + * + * int time(time); // coordinate & record variable + * + * int xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses non-collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_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]; + int isRecvar; + 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++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + 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); + + /** + * 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; +} Index: /tags/v1-0-3/test/test_int/test_write.c =================================================================== --- /tags/v1-0-3/test/test_int/test_write.c (revision 364) +++ /tags/v1-0-3/test/test_int/test_write.c (revision 364) @@ -0,0 +1,251 @@ +/*********************************************************** + * + * This test program writes a netCDF file using the parallel + * netCDF library using MPI-IO. + * + * The output file is: "testwrite.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * int square(x, y); + * squre: description = "2-D integer array"; + * + * int cube(x,y,z); + * + * int time(time); // coordinate & record variable + * + * int xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to write variable data and only + * deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + + + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + fprintf(stderr, "%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j, k; + int status; + int ncid; + int dimid1, dimid2, dimid3, udimid; + int square_dim[2], cube_dim[3], xytime_dim[3], time_dim[1]; + MPI_Offset square_start[2], cube_start[3] = {0, 0, 0}; + MPI_Offset square_count[2] = {50, 50}, cube_count[3] = {100, 50, 50}; + MPI_Offset xytime_start[3] = {0, 0, 0}; + MPI_Offset xytime_count[3] = {100, 50, 50}; + MPI_Offset time_start[1], time_count[1] = {25}; + int square_id, cube_id, xytime_id, time_id; + static char title[] = "example netCDF dataset"; + static char description[] = "2-D integer array"; + int data[100][50][50], buffer[100]; + int rank; + int nprocs; + MPI_Comm comm = MPI_COMM_WORLD; + double TotalWriteTime; + params opts; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if (rank == 0) + fprintf(stderr, "Testing write ... "); + parse_write_args(argc, argv, rank, &opts); + + MPI_Barrier(MPI_COMM_WORLD); + TotalWriteTime = MPI_Wtime(); + + /********** START OF NETCDF ACCESS **************/ + + /** + * Create the dataset + * File name: "testwrite.nc" + * Dataset API: Collective + */ + + status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid); + if (status != NC_NOERR) handle_error(status); + + + /** + * Create a global attribute: + * :title = "example netCDF dataset"; + */ + + status = ncmpi_put_att_text (ncid, NC_GLOBAL, "title", + strlen(title), title); + if (status != NC_NOERR) handle_error(status); + + /** + * Add 4 pre-defined dimensions: + * x = 100, y = 100, z = 100, time = NC_UNLIMITED + */ + + status = ncmpi_def_dim(ncid, "x", 100L, &dimid1); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "y", 100L, &dimid2); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "z", 100L, &dimid3); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &udimid); + if (status != NC_NOERR) handle_error(status); + + /** + * Define the dimensionality and then add 4 variables: + * square(x, y), cube(x,y,z), time(time), xytime(time, x, y) + */ + + square_dim[0] = cube_dim[0] = xytime_dim[1] = dimid1; + square_dim[1] = cube_dim[1] = xytime_dim[2] = dimid2; + cube_dim[2] = dimid3; + xytime_dim[0] = udimid; + time_dim[0] = udimid; + status = ncmpi_def_var (ncid, "square", NC_INT, 2, square_dim, &square_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "cube", NC_INT, 3, cube_dim, &cube_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "time", NC_INT, 1, time_dim, &time_id); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_def_var (ncid, "xytime", NC_INT, 3, xytime_dim, &xytime_id); + if (status != NC_NOERR) handle_error(status); + + /** + * Add an attribute for variable: + * square: decsription = "2-D integer array" + */ + + status = ncmpi_put_att_text (ncid, square_id, "description", + strlen(description), description); + if (status != NC_NOERR) handle_error(status); + + /** + * End Define Mode (switch to data mode) + * Dataset API: Collective + */ + + status = ncmpi_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + + /** + * Data Partition (Assume 4 processors): + * square: 2-D, (Block, Block), 50*50 from 100*100 + * cube: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * xytime: 3-D, (*, Block, Block), 100*50*50 from 100*100*100 + * time: 1-D, Block-wise, 25 from 100 + */ + + square_start[0] = cube_start[1] = xytime_start[1] = (rank/2) * 50; + square_start[1] = cube_start[2] = xytime_start[2] = (rank%2) * 50; + time_start[0] = (rank%4) * 25; + + + /** + * Packing data in the buffer + */ + + /* Data for variable: time */ + for ( i = time_start[0]; i < time_start[0] + time_count[0]; i++ ) + buffer[i - time_start[0]] = i; + + /* Data for variable: square, cube and xytime */ + for ( i = 0; i < 100; i++ ) + for ( j = square_start[0]; j < square_start[0]+square_count[0]; j++ ) + for ( k = square_start[1]; k < square_start[1]+square_count[1]; k++ ) + data[i][j-square_start[0]][k-square_start[1]] = i*100*100 + j*100 + k; + + /** + * Write data into variables: square, cube, time and xytime + * Access Method: subarray + * Data Mode API: collective + */ + + status = ncmpi_put_vara_int_all(ncid, square_id, + square_start, square_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, cube_id, + cube_start, cube_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, time_id, + time_start, time_count, + (void *)buffer); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(ncid, xytime_id, + xytime_start, xytime_count, + &data[0][0][0]); + if (status != NC_NOERR) handle_error(status); + +/* +status = ncmpi_sync(ncid); +if (status != NC_NOERR) handle_error(status); +status = ncmpi_redef(ncid); +if (status != NC_NOERR) handle_error(status); +status = ncmpi_del_att(ncid, square_id, "description"); +if (status != NC_NOERR) handle_error(status); +status = ncmpi_enddef(ncid); +if (status != NC_NOERR) handle_error(status); +*/ + + /** + * Close the dataset + * Dataset API: collective + */ + + status = ncmpi_close(ncid); + if (status != NC_NOERR) handle_error(status); + + /******************* END OF NETCDF ACCESS ****************/ + +MPI_Barrier(MPI_COMM_WORLD); +TotalWriteTime = MPI_Wtime() - TotalWriteTime; + +if (rank == 0) { + fprintf(stderr, "OK\nFile written to: %s!\n", opts.outfname); + fprintf(stderr, "Total Write Time = %10.8f\n", TotalWriteTime); +} + + MPI_Finalize(); + return 0; +} + Index: /tags/v1-0-3/test/test_int/test_read.c =================================================================== --- /tags/v1-0-3/test/test_int/test_read.c (revision 388) +++ /tags/v1-0-3/test/test_int/test_read.c (revision 388) @@ -0,0 +1,354 @@ +/*********************************************************** + * + * This test program reads a netCDF file, and then write it + * out to another netCDF file, using the parallel netCDF + * library using MPI-IO. The two files should be identical. + * + * Input File: "../data/test_int.nc" generated from original netcdf-3. + * Output File: "testread.nc" + * + * The CDL notation for the test dataset is shown below: + * + * netcdf test { + * + * dimensions: + * + * x = 100, y = 100, z = 100, time = NC_UNLIMITED; + * + * + * variables: // variable types, names, shapes, attributes + * + * int square(x, y); + * squre: description = "2-D integer array"; + * + * int cube(x,y,z); + * + * int time(time); // coordinate & record variable + * + * int xytime(time, x, y); // record variable + * + * + * // global attributes + * + * :title = "example netCDF dataset"; + * + * + * data: // data written for variables + * square = 0, 1, 2, 3, ... , 9999; + * cube = 0, 1, 2, 3, ... , 999999; + * time = 0, 1, 2, 3, ... , 99; // 100 records + * xytime = 0, 1, 2, 3, ... , 9999; // 100 records + * } + * + * + * + * This test uses collective APIs to read/write variable data and + * only deals with integer variables. + * + * This test assume # of processors = 4 + * + **********************************************************/ + +#include +#include +#include +#include +#include "testutils.h" + +/* Prototype for functions used only in this file */ +static void handle_error(int status); + +static void handle_error(int status) { + printf("%s\n", ncmpi_strerror(status)); +} + +int main(int argc, char **argv) { + + int i, j; + int status; + int ncid1, ncid2; + int ndims, nvars, ngatts, unlimdimid; + char name[NC_MAX_NAME]; + ncmpi_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]; + int isRecvar; + 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 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 + * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now) + * 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: collective + */ + + for (i = 0; i < NC_MAX_VAR_DIMS; i++) + start[i] = 0; + for (i = 0; i < nvars; i++) { + isRecvar = 0; + 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]; + if (vardims[i][j] == unlimdimid) + isRecvar = 1; + } + switch (vartypes[i]) { + case NC_CHAR: + break; + case NC_SHORT: + valuep = (void *)malloc(varsize * sizeof(short)); + status = ncmpi_get_vara_short_all(ncid1, i, start, shape, (short *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_short_all(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_all(ncid1, i, start, shape, (int *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_int_all(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_all(ncid1, i, start, shape, (float *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_float_all(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_all(ncid1, i, start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + status = ncmpi_put_vara_double_all(ncid2, varids[i], + start, shape, (double *)valuep); + if (status != NC_NOERR) handle_error(status); + free(valuep); + break; + default: + ; + /* handle unexpected types */ + } + } + + /** + * 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; +} Index: /tags/v1-0-3/test/test_int/README =================================================================== --- /tags/v1-0-3/test/test_int/README (revision 15) +++ /tags/v1-0-3/test/test_int/README (revision 15) @@ -0,0 +1,3 @@ +These examples test data transfers of: + + "file NC_INT var" <---> "memory int" Index: /tags/v1-0-3/test/largefile/large_files.c =================================================================== --- /tags/v1-0-3/test/largefile/large_files.c (revision 531) +++ /tags/v1-0-3/test/largefile/large_files.c (revision 531) @@ -0,0 +1,193 @@ +/* + Copyright 2004-2006, UCAR/Unidata + See COPYRIGHT file for copying and redistribution conditions. + + This is part of netCDF. + + This program also takes a long time to run - it writes some data in + a very large file, and then reads it all back to be sure it's + correct. + + This program is an add-on test to check very large 64-bit offset + files (8 GB, so make sure you have the disk space!). + + $Id$ +*/ + +#include +#include +#include +#include + +#define FILE_NAME "/tmp/large_files.nc" + +void +check_err(const int stat, const int line, const char *file) { + if (stat != NC_NOERR) { + (void) fprintf(stderr, "line %d of %s: %s\n", line, file, ncmpi_strerror(stat)); + exit(1); + } +} + +int +main(int argc, char **argv) { + + int stat; /* return status */ + int ncid; /* netCDF id */ + int rec, i, j, k; + signed char x[] = {42, 21}; + + /* dimension ids */ + int rec_dim; + int i_dim; + int j_dim; + int k_dim; + int n_dim; + +#define NUMRECS 1 +#define I_LEN 4104 +#define J_LEN 1023 +#define K_LEN 1023 +#define N_LEN 2 + + /* dimension lengths */ + size_t rec_len = NC_UNLIMITED; + size_t i_len = I_LEN; + size_t j_len = J_LEN; + size_t k_len = K_LEN; + size_t n_len = N_LEN; + + /* variable ids */ + int var1_id; + int x_id; + + /* rank (number of dimensions) for each variable */ +# define RANK_var1 4 +# define RANK_x 2 + + /* variable shapes */ + int var1_dims[RANK_var1]; + int x_dims[RANK_x]; + + printf("\n*** Testing large files, slowly.\n"); + + printf("*** Creating large file %s...", FILE_NAME); + + MPI_Init(&argc, &argv); + + /* enter define mode */ + stat = ncmpi_create(MPI_COMM_WORLD, FILE_NAME, NC_CLOBBER|NC_64BIT_OFFSET, + MPI_INFO_NULL, &ncid); + check_err(stat,__LINE__,__FILE__); + + /* define dimensions */ + stat = ncmpi_def_dim(ncid, "rec", rec_len, &rec_dim); + check_err(stat,__LINE__,__FILE__); + stat = ncmpi_def_dim(ncid, "i", i_len, &i_dim); + check_err(stat,__LINE__,__FILE__); + stat = ncmpi_def_dim(ncid, "j", j_len, &j_dim); + check_err(stat,__LINE__,__FILE__); + stat = ncmpi_def_dim(ncid, "k", k_len, &k_dim); + check_err(stat,__LINE__,__FILE__); + stat = ncmpi_def_dim(ncid, "n", n_len, &n_dim); + check_err(stat,__LINE__,__FILE__); + + /* define variables */ + + var1_dims[0] = rec_dim; + var1_dims[1] = i_dim; + var1_dims[2] = j_dim; + var1_dims[3] = k_dim; + stat = ncmpi_def_var(ncid, "var1", NC_BYTE, RANK_var1, var1_dims, &var1_id); + check_err(stat,__LINE__,__FILE__); + + x_dims[0] = rec_dim; + x_dims[1] = n_dim; + stat = ncmpi_def_var(ncid, "x", NC_BYTE, RANK_x, x_dims, &x_id); + check_err(stat,__LINE__,__FILE__); + /* don't initialize variables with fill values */ + stat = ncmpi_set_fill(ncid, NC_NOFILL, 0); + check_err(stat,__LINE__,__FILE__); + + /* leave define mode */ + stat = ncmpi_enddef (ncid); + check_err(stat,__LINE__,__FILE__); + + { /* store var1 */ + int n = 0; + static signed char var1[J_LEN][K_LEN]; + static MPI_Offset var1_start[RANK_var1] = {0, 0, 0, 0}; + static MPI_Offset var1_count[RANK_var1] = {1, 1, J_LEN, K_LEN}; + static MPI_Offset x_start[RANK_x] = {0, 0}; + static MPI_Offset x_count[RANK_x] = {1, N_LEN}; + for(rec=0; rec +#include +#include +#include +#include +#include + +/* Test program thanks to From: John Tannahill */ + + +int main (int argc, char *argv[]) { + + const int TOTSIZ_3D[3] = { 10, 20, 30 }; + + + int reorder = 0; + + int isperiodic[3] = { 0, 0, 0 }; + + MPI_Comm comm_cart; + int ierr; + int lat_id, lev_id, lon_id; + int ncid; + int totpes; + int tt_id; + + int dim_id[3]; + + int numpes[3] = { 0, 1, 1 }; /* number of PEs along axes; + determined by MPI where a + zero is specified */ + + + MPI_Init (&argc, &argv); + MPI_Comm_size (MPI_COMM_WORLD, &totpes); + + MPI_Dims_create (totpes, 3, numpes); + MPI_Cart_create (MPI_COMM_WORLD, 3, numpes, isperiodic, reorder, &comm_cart); + + + ierr = ncmpi_create (comm_cart, "pnc_test.nc", NC_CLOBBER, MPI_INFO_NULL, + &ncid); + + ierr = ncmpi_def_dim (ncid, "level", (MPI_Offset) TOTSIZ_3D[0], &lev_id); + ierr = ncmpi_def_dim (ncid, "latitude", (MPI_Offset) TOTSIZ_3D[1], &lat_id); + ierr = ncmpi_def_dim (ncid, "longitude", (MPI_Offset) TOTSIZ_3D[2], &lon_id); + + dim_id[0] = lev_id; + dim_id[1] = lat_id; + dim_id[2] = lon_id; + + ierr = ncmpi_def_var (ncid, "tt", NC_FLOAT, 3, dim_id, &tt_id); + + ierr = ncmpi_enddef (ncid); + + ierr = ncmpi_close (ncid); + + + MPI_Comm_free (&comm_cart); + MPI_Finalize ( ); + return 0; +} Index: /tags/v1-0-3/test/fandc/Makefile.in =================================================================== --- /tags/v1-0-3/test/fandc/Makefile.in (revision 434) +++ /tags/v1-0-3/test/fandc/Makefile.in (revision 434) @@ -0,0 +1,37 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include ../../macros.make + +ALL: pnctestf pnctest csnap pnf_test + +INCDIR = $(srcdir)/../../src/lib +INCDIRF = ../../src/libf/ +LNKDIR = ../../src/lib + +MPICC = @MPICC@ +MPIF77 = @MPIF77@ + +EXECS = pnctestf pnctest csnap pnf_test + +pnctestf: pnctestf.F + $(LINK.F) -o pnctestf $(srcdir)/pnctestf.F -I$(INCDIRF) -L$(LNKDIR) -lpnetcdf -lm $(LIBS) + +pnctest: pnctest.c + $(LINK.c) -o pnctest $(srcdir)/pnctest.c -I$(INCDIR) -L$(LNKDIR) -lpnetcdf -lm $(LIBS) + +csnap: csnap.o + $(LINK.c) -L$(LNKDIR) -o csnap csnap.o -lpnetcdf -lm $(LIBS) + +csnap.o: csnap.c + $(MPICC) -I$(INCDIR) -c $(srcdir)/csnap.c + +pnf_test: pnf_test.o + $(LINK.F) -L$(LNKDIR) -o pnf_test pnf_test.o -lpnetcdf -lm $(LIBS) + +pnf_test.o: pnf_test.F + $(MPIF77) $(FFLAGS) -I$(INCDIRF) -c $(srcdir)/pnf_test.F + +clean: + rm -f $(EXECS) *.o *.nc + Index: /tags/v1-0-3/test/fandc/csnap.c =================================================================== --- /tags/v1-0-3/test/fandc/csnap.c (revision 384) +++ /tags/v1-0-3/test/fandc/csnap.c (revision 384) @@ -0,0 +1,420 @@ +/****************************************************************************** + + This is to test MPInetcdf, the parallel netCDF library being developed + at Argonne National Lab and Northwestern Univ. + + This code writes one or two arrays, tt[k][j][i] (and smf[j][i], if + 'only_3d' is 0), into the file 'csnap.nc.' It then reads the field(s) + from the file, and compares with the original field values. + + i=longitude, j=latitude, k=level + + To run: Set the global sizes, parallel decomposition and other I/O + parameters below. + + By Woo-Sun Yang and Chris Ding + NERSC, Lawrence Berkeley National Laboratory + + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/*** Field parameters ***/ + +const MPI_Offset totsiz_3d[3] = { 256, 256, 256 }; /* global sizes of 3D field */ +MPI_Offset totsiz_2d[2]; /* global sizes of 2D field */ +MPI_Offset locsiz_3d[3]; /* local sizes of 3D fields */ +MPI_Offset locsiz_2d[2]; /* local sizes of 2D fields */ +MPI_Offset istart, jstart, kstart; /* offsets of 3D field */ + +const int random_fields = 0; /* random fields? 1 or 0 */ +const int only_3d = 1; /* I/O 3D field only? 1 or 0 */ + +int has_2d; /* contains valid 2D data? */ + +const int nwrites = 5; /* number of write samples */ +const int nreads = 5; /* number of read samples */ + +const int fillmode = NC_NOFILL; /* NC_FILL or NC_NOFILL; actually + prefilling not supported */ + +/*** Parallel domain decomposition parameters ***/ + +MPI_Comm comm_cart; /* Cartesian communicator */ +int mype; /* rank in comm_cart */ +int totpes; /* total number of PEs */ +int numpes[3] = { 0, 1, 1 }; /* number of PEs along axes; + determined by MPI where + a zero is specified */ +int pe_coords[3]; /* Cartesian PE coords */ + +/*** function prototypes ***/ + +void find_locnx(MPI_Offset nx, int mype, int totpes, MPI_Offset *locnx, MPI_Offset *xbegin); +void write_file(char *filename, double *t); +void read_file(char *filename, double *t); +void get_fields(double *tt, double *smf); +void compare_vec(double *a, double *b, int ndims, MPI_Offset *sizes, int corr_data); + + +int main(int argc, char *argv[]) { + int isperiodic[3] = {0, 0, 0}; + int reorder = 0; + double t[20], t_g[20]; + double file_size; + double rates_l[4], rates_g[4]; + int i; + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD,&totpes); + + MPI_Dims_create(totpes,3,numpes); + MPI_Cart_create(MPI_COMM_WORLD,3,numpes,isperiodic,reorder,&comm_cart); + MPI_Comm_rank(comm_cart,&mype); + MPI_Cart_coords(comm_cart,mype,3,pe_coords); + +/* + Determine local sizes for tt (locsiz_3d) and smf (locsiz_2d). + Also determine whether the current processor contains valid 2D data. + Compute file_size in 1e6 Bytes + */ + + find_locnx(totsiz_3d[0],pe_coords[0],numpes[0],&locsiz_3d[0],&kstart); + find_locnx(totsiz_3d[1],pe_coords[1],numpes[1],&locsiz_3d[1],&jstart); + find_locnx(totsiz_3d[2],pe_coords[2],numpes[2],&locsiz_3d[2],&istart); + + totsiz_2d[0] = totsiz_3d[1]; + totsiz_2d[1] = totsiz_3d[2]; + + locsiz_2d[0] = locsiz_3d[1]; + locsiz_2d[1] = locsiz_3d[2]; + + has_2d = (! only_3d) && (pe_coords[0] == numpes[0] - 1); + + if (only_3d) + file_size = (((double) totsiz_3d[0])*((double) totsiz_3d[1]) + * ((double) totsiz_3d[2])) * 1.0e-6 * sizeof(double); + else + file_size = (((double) totsiz_3d[0])*((double) totsiz_3d[1]) + * ((double) totsiz_3d[2]) + + ((double) totsiz_2d[0])*((double) totsiz_2d[1])) + * 1.0e-6 * sizeof(double); + +/* Print data decomposition information */ + + if (mype == 0) + printf("mype pe_coords totsiz_3d locsiz_3d " + "kstart,jstart,istart\n"); + + MPI_Barrier(comm_cart); + + printf("%3d %2d %2d %2d %4d %4d %4d %4d %4d %4d %6d %6d %6d\n", + mype, pe_coords[0], pe_coords[1], pe_coords[2], + totsiz_3d[0], totsiz_3d[1], totsiz_3d[2], + locsiz_3d[0], locsiz_3d[1], locsiz_3d[2], + kstart, jstart, istart); + +/* Write and then read back */ + + for (i=0; i < 20; t[i++] = DBL_MAX); /* ready for timing */ + + write_file("csnap.nc", &t[ 0]); + read_file ("csnap.nc", &t[10]); + +/* Compute I/O rates */ + + rates_l[0] = file_size / t[1]; /* write rate */ + rates_l[1] = file_size /(t[0] + t[1]); /* effective write rate */ + rates_l[2] = file_size / t[11]; /* read rate */ + rates_l[3] = file_size /(t[10] + t[11]); /* effective read rate */ + + MPI_Allreduce(rates_l, rates_g, 4, MPI_DOUBLE, MPI_MIN, comm_cart); + MPI_Allreduce(t, t_g, 20, MPI_DOUBLE, MPI_MAX, comm_cart); + + if (mype == 0) { + printf("File size: %10.3e MB\n", file_size); + printf(" Write: %9.3f MB/s (eff., %9.3f MB/s)\n", + rates_g[0], rates_g[1]); + printf(" Read : %9.3f MB/s (eff., %9.3f MB/s)\n", + rates_g[2], rates_g[3]); + printf(" %c %10.3e %3d %10.3e %10.3e %8.3f %10.3e %10.3e %8.3f\n", + ((fillmode == NC_FILL) ? 'f' : 'n'), file_size, totpes, + t_g[0], t_g[1], rates_g[1], t_g[10], t_g[11], rates_g[3]); + } + + MPI_Comm_free(&comm_cart); + MPI_Finalize(); + return 0; +} + + +void write_file(char *filename, double *t) { + double *tt = NULL; + double *smf = NULL; + double t1, t2, t3; + int dim_id[3]; + int lon_id, lat_id, lev_id; + int ierr; + int file_id; + int t_id, smf_id; + int ii; + MPI_Offset start_3d[3]; + MPI_Offset count_3d[3]; + MPI_Offset start_2d[2]; + MPI_Offset count_2d[2]; + + start_3d[0] = kstart; + start_3d[1] = jstart; + start_3d[2] = istart; + count_3d[0] = locsiz_3d[0]; + count_3d[1] = locsiz_3d[1]; + count_3d[2] = locsiz_3d[2]; + start_2d[0] = jstart; + start_2d[1] = istart; + count_2d[0] = locsiz_2d[0]; + count_2d[1] = locsiz_2d[1]; + + tt = malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double)); + + if (has_2d) + smf = malloc(locsiz_2d[0]*locsiz_2d[1]*sizeof(double)); + else + smf = malloc(sizeof(double)); + + for (ii = 1; ii <= nwrites; ii++) { + + if(mype == 0) unlink(filename); + + get_fields(tt, smf); + MPI_Barrier(comm_cart); + + t1 = MPI_Wtime(); + + ierr = ncmpi_create(comm_cart, filename, NC_CLOBBER, MPI_INFO_NULL, + &file_id); + +/* ierr = nc_set_fill(file_id,fillmode,&old_fillmode); */ + + ierr = ncmpi_def_dim(file_id,"level", (MPI_Offset) totsiz_3d[0],&lev_id); + ierr = ncmpi_def_dim(file_id,"latitude", (MPI_Offset) totsiz_3d[1],&lat_id); + ierr = ncmpi_def_dim(file_id,"longitude",(MPI_Offset) totsiz_3d[2],&lon_id); + + dim_id[0] = lev_id; dim_id[1] = lat_id; dim_id[2] = lon_id; + + ierr = ncmpi_def_var(file_id,"t",NC_DOUBLE,3,dim_id,&t_id); + + if (! only_3d) + ierr = ncmpi_def_var(file_id,"smf",NC_DOUBLE,2,&dim_id[1],&smf_id); + + ierr = ncmpi_enddef(file_id); + + t2 = MPI_Wtime(); + + ierr = ncmpi_put_vara_double_all(file_id,t_id,start_3d,count_3d,tt); + + if (! only_3d) { + ierr = ncmpi_begin_indep_data(file_id); + + if (has_2d) + ierr = ncmpi_put_vara_double(file_id,smf_id,start_2d,count_2d,smf); + + ierr = ncmpi_end_indep_data(file_id); + } + + ierr = ncmpi_close(file_id); + + MPI_Barrier(comm_cart); + t3 = MPI_Wtime(); + + if (t2 - t1 < t[0]) t[0] = t2 - t1; + if (t3 - t2 < t[1]) t[1] = t3 - t2; + if (mype == 0) printf("write %d: %9.3e %9.3e\n", ii, t2-t1, t3-t2); + } + + free(tt); + free(smf); +} + + +void read_file(char *filename, double *t) { + double *tt = NULL; + double *smf = NULL; + double *buf = NULL; + double t1, t2, t3; + double dt1, dt2; + int ncid; + int vid_t, vid_smf; + int i, j, k, ii, ierr; + + MPI_Offset start_3d[3]; + MPI_Offset count_3d[3]; + MPI_Offset start_2d[2]; + MPI_Offset count_2d[2]; + + start_3d[0] = kstart; + start_3d[1] = jstart; + start_3d[2] = istart; + count_3d[0] = locsiz_3d[0]; + count_3d[1] = locsiz_3d[1]; + count_3d[2] = locsiz_3d[2]; + start_2d[0] = jstart; + start_2d[1] = istart; + count_2d[0] = locsiz_2d[0]; + count_2d[1] = locsiz_2d[1]; + + tt = malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double)); + + if (has_2d) + smf = malloc(locsiz_2d[0]*locsiz_2d[1]*sizeof(double)); + else + smf = malloc(sizeof(double)); + + buf = malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double)); + + get_fields(tt, smf); + + for (ii = 1; ii <= nreads; ii++) { + + double *ptr = buf; + for (k = 0; k < locsiz_3d[0]; k++) + for (j = 0; j < locsiz_3d[1]; j++) + for (i = 0; i < locsiz_3d[2]; i++) + *ptr++ = 4.444; + + MPI_Barrier(comm_cart); + t1 = MPI_Wtime(); + + ierr = ncmpi_open(comm_cart, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); + + ierr = ncmpi_inq_varid(ncid,"t",&vid_t); + if (! only_3d) ierr = ncmpi_inq_varid(ncid,"smf",&vid_smf); + + t2 = MPI_Wtime(); + + ierr = ncmpi_get_vara_double_all(ncid,vid_t,start_3d,count_3d,buf); + + dt1 = MPI_Wtime(); + if (ii == 1) compare_vec(tt,buf,3,locsiz_3d,1); + dt1 = MPI_Wtime() - dt1; + + if (! only_3d) { + ierr = ncmpi_begin_indep_data(ncid); + + if (has_2d) + ierr = ncmpi_get_vara_double(ncid,vid_smf,start_2d,count_2d,buf); + + dt2 = MPI_Wtime(); + if (ii == 1) compare_vec(smf,buf,2,locsiz_2d,has_2d); + dt2 = MPI_Wtime() - dt2; + + ierr = ncmpi_end_indep_data(ncid); + } + + ierr = ncmpi_close(ncid); + + MPI_Barrier(comm_cart); + t3 = MPI_Wtime(); + + if (t2 - t1 < t[0]) t[0] = t2 - t1; + if ((t3 - t2) - (dt1 + dt2) < t[1]) t[1] = (t3 - t2) - (dt1 + dt2); + if (mype == 0) printf(" read %d: %9.3e %9.3e\n", ii, t2-t1, + (t3-t2)-(dt1+dt2)); + } + + free(tt); + free(smf); + free(buf); +} + + +void find_locnx(MPI_Offset nx, int mype, int totpes, MPI_Offset *locnx, MPI_Offset *xbegin) { + MPI_Offset xremain; + + *locnx = nx / totpes; + xremain = nx - totpes*(*locnx); + if (mype < xremain) (*locnx)++; + *xbegin = mype*(nx/totpes) + xremain; + if (mype < xremain) *xbegin += mype - xremain; +} + + +void get_fields(double *tt, double *smf) { + int i, j, k; + + if (random_fields) { + unsigned int seed = (INT_MAX / totpes) * mype; + srand(seed); + + for (k = 0; k < locsiz_3d[0]; k++) + for (j = 0; j < locsiz_3d[1]; j++) + for (i = 0; i < locsiz_3d[2]; i++) + *tt++ = ((double) (rand())) / (RAND_MAX + 1.); + + if (has_2d) + for (j = 0; j < locsiz_2d[0]; j++) + for (i = 0; i < locsiz_2d[1]; i++) + *smf++ = ((double) (rand())) / (RAND_MAX + 1.); + } + else { + for (k = 0; k < locsiz_3d[0]; k++) + for (j = 0; j < locsiz_3d[1]; j++) + for (i = 0; i < locsiz_3d[2]; i++) + *tt++ = (istart + i + 1 + totsiz_3d[2]*(jstart + j + + totsiz_3d[1]*(kstart + k)))*1.e-3; + + if (has_2d) + for (j = 0; j < locsiz_2d[0]; j++) + for (i = 0; i < locsiz_2d[1]; i++) + *smf++ = (istart + i + 1 + totsiz_2d[1]*(jstart + j))*1.e-2; + } +} + + +void compare_vec(double *a, double *b, int ndims, MPI_Offset *sizes, int corr_data) { + double diff, delta, delmax, delmin; + double ws[5], wr[5]; + MPI_Offset totsiz; + int i; + + if (corr_data) { + totsiz = 1; + for (i = 0; i < ndims; i++) + totsiz = totsiz * sizes[i]; + + ws[0] = 0.; /* diff */ + ws[1] = 0.; /* sumsq */ + ws[2] = totsiz; /* totsiz */ + ws[3] = 0.; /* delmax */ + ws[4] = DBL_MAX; /* delmin */ + + for (i = 0; i < totsiz; i++) { + delta = (a[i] - b[i]) * (a[i] - b[i]); + ws[0] = ws[0] + delta; + ws[1] = ws[1] + a[i] * a[i]; + if (delta > ws[3]) ws[3] = delta; + if (delta < ws[4]) ws[4] = delta; + } + } + else { + ws[0] = ws[1] = ws[2] = ws[3] = 0.; + ws[4] = DBL_MAX; + } + + MPI_Allreduce( ws, wr, 3, MPI_DOUBLE, MPI_SUM, comm_cart); + MPI_Allreduce(&ws[3], &delmax, 1, MPI_DOUBLE, MPI_MAX, comm_cart); + MPI_Allreduce(&ws[4], &delmin, 1, MPI_DOUBLE, MPI_MIN, comm_cart); + + diff = sqrt(wr[0]/wr[1]); /* Normalized error */ + delmax = sqrt(wr[2]*delmax/wr[1]); /* Normalized max difference */ + delmin = sqrt(wr[2]*delmin/wr[1]); /* Normalized min difference */ + + if (mype == 0) + printf("diff, delmax, delmin = %9.3e %9.3e %9.3e\n", diff, delmax, delmin); +} Index: /tags/v1-0-3/test/fandc/pnf_test.F =================================================================== --- /tags/v1-0-3/test/fandc/pnf_test.F (revision 398) +++ /tags/v1-0-3/test/fandc/pnf_test.F (revision 398) @@ -0,0 +1,691 @@ + +!============================================================================= +! +! CODE DEVELOPER +! John Tannahill, LLNL +! jrt@llnl.gov +! Note that this code was adapted from csnap.c, which was written by: +! Woo-Sun Yang and Chris Ding +! NERSC, Lawrence Berkeley National Laboratory +! +! FILE +! pnf_test.F +! +! ROUTINES +! Pnf_Test (Program) +! +! The purpose of this program is to test the Fortran interface to the +! parallel netCDF library being developed at Argonne National Lab and +! Northwestern Univ. +! +! This code writes the array, tt(k)(j)(i), into the file 'pnf_test.nc'. It +! then reads the array from the file, and compares it with the original +! values. +! +! i=longitude, j=latitude, k=level +! +!============================================================================= + + program Pnf_Test + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + + +! ----------------------- +! Parameter declarations. +! ----------------------- + + integer NREADS, NWRITES + parameter (NREADS = 5, NWRITES = 5 ) + ! number of read samples + ! number of write samples + + NFMPI_OFFSET TOTSIZ_3D(3) ! global sizes of 3D field + + +! ---------------------- +! Variable declarations. +! ---------------------- + + logical reorder + + logical isperiodic(3) + + integer comm_cart ! Cartesian communicator + integer ierr + NFMPI_OFFSET istart, jstart, kstart ! offsets of 3D field + NFMPI_OFFSET locsiz + integer mype ! rank in comm_cart + integer totpes ! total number of PEs + + NFMPI_OFFSET locsiz_3d(3) ! local sizes of 3D fields + integer pe_coords(3) ! Cartesian PE coords + + integer numpes(3) ! number of PEs along axes; + ! determined by MPI where a + ! zero is specified + + real*4 filsiz + + real*4 rdt_g(2) + real*4 rdt_l(2) + real*4 wrt_g(2) + real*4 wrt_l(2) + + real*4 rrates_g(2) + real*4 rrates_l(2) + real*4 wrates_g(2) + real*4 wrates_l(2) + + + data reorder / .false. / + data isperiodic / .false., .false., .false. / + data numpes / 1, 1, 0 / + data TOTSIZ_3D / 256, 256, 256 / + +! ---------------- +! Begin execution. +! ---------------- + + call MPI_Init (ierr) + + call MPI_Comm_Size (MPI_COMM_WORLD, totpes, ierr) + + call MPI_Dims_Create (totpes, 3, numpes, ierr) + + call MPI_Cart_Create + & (MPI_COMM_WORLD, 3, numpes, isperiodic, reorder, + & comm_cart, ierr) + + call MPI_Comm_Rank (comm_cart, mype, ierr) + + call MPI_Cart_Coords (comm_cart, mype, 3, pe_coords, ierr) + + + rdt_l(1) = 1.0e38 + rdt_l(2) = 1.0e38 + wrt_l(1) = 1.0e38 + wrt_l(2) = 1.0e38 +! rdt_l(:) = Huge (rdt_l) ! initialize for timing +! wrt_l(:) = Huge (wrt_l) + + +! ---------------------------------------- +! Determine local size for tt (locsiz_3d). +! ---------------------------------------- + +! =============== + call Find_Locnx + & (TOTSIZ_3D(1), pe_coords(1), numpes(1), locsiz_3d(1), istart) + call Find_Locnx + & (TOTSIZ_3D(2), pe_coords(2), numpes(2), locsiz_3d(2), jstart) + call Find_Locnx + & (TOTSIZ_3D(3), pe_coords(3), numpes(3), locsiz_3d(3), kstart) +! =============== + + +! ------------------------------- +! Compute file size in 1d6 bytes. +! ------------------------------- + + filsiz = (TOTSIZ_3D(1) * TOTSIZ_3D(2) * TOTSIZ_3D(3)) * + & 1.0d-6 * 4.0d0 + + +! ------------------------------------- +! Print data decomposition information. +! ------------------------------------- + + if (mype == 0) Write (6,900) + + call MPI_Barrier (comm_cart, ierr) + + Write (6, 902) + & mype, pe_coords(1), pe_coords(2), pe_coords(3), + & TOTSIZ_3D(1), TOTSIZ_3D(2), TOTSIZ_3D(3), + & locsiz_3d(1), locsiz_3d(2), locsiz_3d(3), + & kstart, jstart, istart + + 900 format ("mype pe_coords totsiz_3d locsiz_3d ", + & "kstart,jstart,istart") + 902 format (i3,3x,i2,1x,i2,1x,i2,2x,i4,1x,i4,1x,i4,4x,i4,1x,i4,1x,i4, + & 3x,i6,1x,i6,1x,i6) + + +! ------------------------- +! Write and then read back. +! ------------------------- + + locsiz = locsiz_3d(1) * locsiz_3d(2) * locsiz_3d(3) + +! =============== + call Write_File +! =============== + & ("pnf_test.nc", NWRITES, mype, comm_cart, istart, jstart, + & kstart, locsiz, locsiz_3d, TOTSIZ_3D, wrt_l) +!!! Write (6,*) wrt_l(1), wrt_l(2) + +! ============== + call Read_File +! ============== + & ("pnf_test.nc", NREADS, mype, comm_cart, istart, jstart, + & kstart, locsiz, locsiz_3d, TOTSIZ_3D, rdt_l) + + +! ---------------------------- +! Compute and print I/O rates. +! ---------------------------- + + wrates_l(1) = filsiz / wrt_l(2) ! write rate + wrates_l(2) = filsiz / (wrt_l(1) + wrt_l(2)) ! effective write rate + + rrates_l(1) = filsiz / rdt_l(2) ! read rate + rrates_l(2) = filsiz / (rdt_l(1) + rdt_l(2)) ! effective read rate + + + call MPI_Allreduce + & (wrates_l, wrates_g, 2, MPI_REAL, MPI_MIN, comm_cart, ierr) + call MPI_Allreduce + & (rrates_l, rrates_g, 2, MPI_REAL, MPI_MIN, comm_cart, ierr) + + call MPI_Allreduce + & (wrt_l, wrt_g, 2, MPI_REAL, MPI_MAX, comm_cart, ierr) + call MPI_Allreduce + & (rdt_l, rdt_g, 2, MPI_REAL, MPI_MAX, comm_cart, ierr) + + + if (mype == 0) then + Write (6,905) filsiz + Write (6,910) wrates_g(1), wrates_g(2) + Write (6,915) rrates_g(1), rrates_g(2) + Write (6,920) totpes + Write (6,922) wrt_g(1), wrt_g(2), wrates_g(2), + & rdt_g(1), rdt_g(2), rrates_g(2) + end if + + 905 format ("File size: ", e10.3, " MB") + 910 format (" Write: ", f9.3, " MB/s (eff., ", f9.3, " MB/s)") + 915 format (" Read : ", f9.3, " MB/s (eff., ", f9.3, " MB/s)") + 920 format ("Total number PEs: ", i4) + 922 format (e11.3, e11.3, f9.3, e11.3, e11.3, f9.3) + + + call MPI_Comm_Free (comm_cart, ierr) + + call MPI_Finalize (ierr) + + + Stop + + end program Pnf_Test + + +! ------------ + + + subroutine Write_File + & (filename, nwrites, mype, comm_cart, istart, jstart, kstart, + & locsiz, locsiz_3d, totsiz_3d, wrt_l) + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + + +! ---------------------- +! Argument declarations. +! ---------------------- + + character (len=*) filename + integer nwrites + integer mype + integer comm_cart + NFMPI_OFFSET istart, jstart, kstart + NFMPI_OFFSET locsiz + NFMPI_OFFSET locsiz_3d(3) + NFMPI_OFFSET totsiz_3d(3) + real*4 wrt_l(2) + + +! ---------------------------- +! Local variable declarations. +! ---------------------------- + + integer ierr + integer lon_id, lat_id, lev_id + integer ncid + integer nw + integer tt_id + + NFMPI_OFFSET count_3d(3) + NFMPI_OFFSET start_3d(3) + + integer dim_id(3) + + double precision t1, t2, t3 + + integer max_loc_size + parameter( max_loc_size = 20000000 ) + real*4 tt(max_loc_size) ! Need tt(locsiz) + + + if (locsiz .gt. MAX_LOC_SIZE) then + print *, 'locsiz = ', locsiz, ' larger than MAX_LOC_SIZE' + stop + endif +! ---------------- +! Begin execution. +! ---------------- + +! start_3d(1:3) = (/ kstart, jstart, istart /) +! count_3d(:) = locsiz_3d(:) + start_3d(1) = istart + start_3d(2) = jstart + start_3d(3) = kstart + count_3d(1) = locsiz_3d(1) + count_3d(2) = locsiz_3d(2) + count_3d(3) = locsiz_3d(3) + + + do nw = 1, nwrites + +! ============== + call Get_Field +! ============== + & (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt) + + + call MPI_Barrier (comm_cart, ierr) + t1 = MPI_Wtime ( ) + + +! ================= + ierr = Nfmpi_Create +! ================= + & (comm_cart, filename, NF_CLOBBER, MPI_INFO_NULL, ncid) + + +! ================== + ierr = Nfmpi_Def_Dim + & (ncid, "level", totsiz_3d(1), lon_id) + ierr = Nfmpi_Def_Dim + & (ncid, "latitude", totsiz_3d(2), lat_id) + ierr = Nfmpi_Def_Dim + & (ncid, "longitude", totsiz_3d(3), lev_id) +! ================== + + + dim_id(1) = lon_id + dim_id(2) = lat_id + dim_id(3) = lev_id + +! ================== + ierr = Nfmpi_Def_Var +! ================== + & (ncid, "tt", NF_REAL, 3, dim_id, tt_id) + + +! ================= + ierr = Nfmpi_Enddef (ncid) +! ================= + + + t2 = MPI_Wtime ( ) + + +! ============================= + ierr = Nfmpi_Put_Vara_Real_All +! ============================= + & (ncid, tt_id, start_3d, count_3d, tt) + + +! ================ + ierr = Nfmpi_Close (ncid) +! ================ + + + call MPI_Barrier (comm_cart, ierr) + t3 = MPI_Wtime ( ) + + + if (t2 - t1 < wrt_l(1)) wrt_l(1) = t2 - t1 + if (t3 - t2 < wrt_l(2)) wrt_l(2) = t3 - t2 + + if (mype == 0) Write (6,950) nw, t2-t1, t3-t2 + + end do + + + 950 format ("write ", i1, ": ", e9.3, 1x, e9.3) + + + Return + + end + + +! ------------ + + + subroutine Read_File + & (filename, nreads, mype, comm_cart, istart, jstart, kstart, + & locsiz, locsiz_3d, totsiz_3d, rdt_l) + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + + +! ---------------------- +! Argument declarations. +! ---------------------- + + character (len=*) filename + integer nreads + integer mype + integer comm_cart + NFMPI_OFFSET istart, jstart, kstart + NFMPI_OFFSET locsiz + NFMPI_OFFSET locsiz_3d(3) + NFMPI_OFFSET totsiz_3d(3) + real*4 rdt_l(2) + + +! ---------------------------- +! Local variable declarations. +! ---------------------------- + + integer ierr + integer ncid + integer nr + integer tt_id + integer ii + + NFMPI_OFFSET count_3d(3) + NFMPI_OFFSET start_3d(3) + + double precision t1, t2, t3 + + integer max_loc_size + parameter( max_loc_size = 20000000 ) + real*4 buf(max_loc_size) + real*4 tt (max_loc_size) + + +! ---------------- +! Begin execution. +! ---------------- + +! ============== + call Get_Field +! ============== + & (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt) + + +! start_3d(1:3) = (/ kstart, jstart, istart /) +! count_3d(:) = locsiz_3d(:) + start_3d(1) = istart + start_3d(2) = jstart + start_3d(3) = kstart + count_3d(1) = locsiz_3d(1) + count_3d(2) = locsiz_3d(2) + count_3d(3) = locsiz_3d(3) + + + do nr = 1, nreads + + do ii=1,locsiz + buf(ii) = -99.99 + enddo + + + call MPI_Barrier (comm_cart, ierr) + t1 = MPI_Wtime ( ) + + +! =============== + ierr = Nfmpi_Open +! =============== + & (comm_cart, filename, NF_NOWRITE, MPI_INFO_NULL, ncid) + + +! ==================== + ierr = Nfmpi_Inq_Varid +! ==================== + & (ncid, "tt", tt_id) + + + t2 = MPI_Wtime ( ) + + +! ============================= + ierr = Nfmpi_Get_Vara_Real_All +! ============================= + & (ncid, tt_id, start_3d, count_3d, buf) + + +! ================ + ierr = Nfmpi_Close (ncid) +! ================ + + + call MPI_Barrier (comm_cart, ierr) + t3 = MPI_Wtime ( ) + + + if (t2 - t1 < rdt_l(1)) rdt_l(1) = t2 - t1 + if (t3 - t2 < rdt_l(2)) rdt_l(2) = t3 - t2 + + if (mype == 0) Write (6,970) nr, t2-t1, t3-t2 + + + if (nr == 1) then +! ================ + call Compare_Vec +! ================ + & (mype, comm_cart, locsiz, tt, buf) + end if + + end do + + + 970 format (" read ", i1, ": ", e9.3, 1x, e9.3) + + + Return + + end + + +! ------------ + + + subroutine Find_Locnx + & (nx, mype, totpes, locnx, ibegin) + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + +! ---------------------- +! Argument declarations. +! ---------------------- + + NFMPI_OFFSET nx + integer mype + integer totpes + NFMPI_OFFSET locnx + NFMPI_OFFSET ibegin + + +! ---------------------------- +! Local variable declarations. +! ---------------------------- + + NFMPI_OFFSET iremain + + +! ---------------- +! Begin execution. +! ---------------- + + locnx = nx / totpes + + iremain = nx - (totpes * locnx) + + if (mype < iremain) locnx = locnx + 1 + + ibegin = mype * (nx / totpes) + iremain + 1 + + if (mype < iremain) ibegin = ibegin + (mype - iremain) + + + Return + + end + + +! ------------ + + + subroutine Get_Field + & (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt) + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + + +! ---------------------- +! Argument declarations. +! ---------------------- + + NFMPI_OFFSET istart, jstart, kstart + NFMPI_OFFSET locsiz + NFMPI_OFFSET locsiz_3d(3) + NFMPI_OFFSET totsiz_3d(3) + real*4 tt(locsiz) + + +! ---------------------------- +! Local variable declarations. +! ---------------------------- + + integer ii, jj, kk + integer ind + + +! ---------------- +! Begin execution. +! ---------------- + + ind = 1 + + + do kk = 1, locsiz_3d(3) + do jj = 1, locsiz_3d(2) + do ii = 1, locsiz_3d(1) + + tt(ind) = + & (istart-1 +(ii - 1) + 1 + totsiz_3d(3)*(jstart-1 + + & (jj - 1) + totsiz_3d(2)*(kstart-1 + + & (kk-1)))) * 1.0d-3 + ind = ind + 1 + + end do + end do + end do + + + Return + + end + + +! ------------ + + + subroutine Compare_Vec + & (mype, comm_cart, locsiz, tt, buf) + + implicit none + + include "mpif.h" + + +! ---------------------- +! Argument declarations. +! ---------------------- + + integer mype + integer comm_cart + NFMPI_OFFSET locsiz + real*4 tt (locsiz) + real*4 buf(locsiz) + + +! ---------------------------- +! Local variable declarations. +! ---------------------------- + + integer ierr + integer ii + + real*4 delmax, delmin, delta + real*4 diff + + real*4 wr(5) + real*4 ws(5) + + +! ---------------- +! Begin execution. +! ---------------- + + ws(1) = 0.0d0 ! diff + ws(2) = 0.0d0 ! sumsq + ws(3) = locsiz ! locsiz + ws(4) = 0.0d0 ! delmax + ws(5) = 1.0d38 ! Huge (ws) ! delmin + + + do ii = 1, locsiz + delta = (tt(ii) - buf(ii)) * (tt(ii) - buf(ii)) + ws(1) = ws(1) + delta + ws(2) = ws(2) + tt(ii) * tt(ii) + if (delta > ws(4)) ws(4) = delta + if (delta < ws(5)) ws(5) = delta + end do + + + call MPI_Allreduce + & (ws, wr, 3, MPI_REAL, MPI_SUM, comm_cart, ierr) + call MPI_Allreduce + & (ws(4), delmax, 1, MPI_REAL, MPI_MAX, comm_cart, ierr) + call MPI_Allreduce + & (ws(5), delmin, 1, MPI_REAL, MPI_MIN, comm_cart, ierr) + + + diff = Sqrt (wr(1) / wr(2)) ! normalized error + delmax = Sqrt (wr(3) * delmax/wr(2)) ! normalized max difference + delmin = Sqrt (wr(3) * delmin/wr(2)) ! normalized min difference + + + if (mype == 0) Write (6,990) diff, delmax, delmin + + 990 format ("diff, delmax, delmin = ", + & e9.3, 1x, e9.3, 1x, e9.3) + + + + Return + + end + Index: /tags/v1-0-3/test/fandc/pnctestf.F =================================================================== --- /tags/v1-0-3/test/fandc/pnctestf.F (revision 398) +++ /tags/v1-0-3/test/fandc/pnctestf.F (revision 398) @@ -0,0 +1,77 @@ + program Pnf_Test +C Test program thanks to From: John Tannahill + + implicit none + + include "mpif.h" +# include "pnetcdf.inc" + + + NFMPI_OFFSET TOTSIZ_3D(3) + + + logical reorder + + logical isperiodic(3) + + integer comm_cart + integer ierr + integer lat_id, lev_id, lon_id + integer ncid + integer totpes + integer tt_id + + integer dim_id(3) + + integer numpes(3) +C number of PEs along axes; +C determined by MPI where a zero is specified + + data totsiz_3d/10,20,30/ + data reorder /.false./ + data isperiodic /.false., .false., .false./ + data numpes/1,1,0/ + + call MPI_Init (ierr) + + call MPI_Comm_Size (MPI_COMM_WORLD, totpes, ierr) + + call MPI_Dims_Create (totpes, 3, numpes, ierr) + + call MPI_Cart_Create (MPI_COMM_WORLD, 3, numpes, isperiodic, + & reorder, comm_cart, ierr) + + + ierr = Nfmpi_Create (comm_cart, "pnf_test.nc", NF_CLOBBER, + & MPI_INFO_NULL, ncid) + + ierr = Nfmpi_Def_Dim + & (ncid, "level", totsiz_3d(1), lev_id) + ierr = Nfmpi_Def_Dim + & (ncid, "latitude", totsiz_3d(2), lat_id) + ierr = Nfmpi_Def_Dim + & (ncid, "longitude", totsiz_3d(3), lon_id) + + dim_id(1) = lev_id + dim_id(2) = lat_id + dim_id(3) = lon_id + + ierr = Nfmpi_Def_Var + & (ncid, "tt", NF_FLOAT, 3, dim_id, tt_id) + + ierr = Nfmpi_Enddef (ncid) + + ierr = Nfmpi_Close (ncid) + + + call MPI_Comm_Free (comm_cart, ierr) + + call MPI_Finalize (ierr) + + Write (6,10) + + 10 format(" No Errors") + + Stop + + end program Pnf_Test Index: /tags/v1-0-3/test/testcases/Makefile.in =================================================================== --- /tags/v1-0-3/test/testcases/Makefile.in (revision 588) +++ /tags/v1-0-3/test/testcases/Makefile.in (revision 588) @@ -0,0 +1,32 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +INCDIR = $(srcdir)/../../src/lib +LIBDIR = ../../src/lib + +INCLUDES = -I$(INCDIR) + +CC = @MPICC@ +CFLAGS = @CFLAGS@ $(INCLUDES) + +SRCS = $(srcdir)/ncmpi_vars_null_stride.c +OBJS = $(SRCS:.c=.o) +PROGS = ncmpi_vars_null_stride +LDFLAGS = -L$(LIBDIR) @LDFLAGS@ +LIBS = -lpnetcdf @LIBS@ + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROGS) + +ncmpi_vars_null_stride: ncmpi_vars_null_stride.o + $(CC) -o $@ $@.o $(LDFLAGS) $(LIBS) +clean: + rm -f $(OBJS) $(PROGS) *.nc + +test: ncmpi_vars_null_stride + ./ncmpi_vars_null_stride test.nc + @echo '*** Success ***' + +testing: test Index: /tags/v1-0-3/test/testcases/ncmpi_vars_null_stride.c =================================================================== --- /tags/v1-0-3/test/testcases/ncmpi_vars_null_stride.c (revision 571) +++ /tags/v1-0-3/test/testcases/ncmpi_vars_null_stride.c (revision 571) @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +static void handle_error(int status) +{ + fprintf(stderr, "%s\n", ncmpi_strerror(status)); + exit(-1); +} +#define NDIMS 1 +int main(int argc, char **argv) +{ + int ret, ncfile, dimid, varid, ndims=NDIMS; + int i, nprocs, rank; + MPI_Offset start[NDIMS] = {0}; + MPI_Offset count[NDIMS] = {0}; + int buf[512]; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + + ret = ncmpi_create(MPI_COMM_WORLD, argv[1], 0, MPI_INFO_NULL, &ncfile); + if (ret != NC_NOERR) handle_error(ret); + + ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid); + if (ret != NC_NOERR) handle_error(ret); + + ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid); + if (ret != NC_NOERR) handle_error(ret); + + ret = ncmpi_enddef(ncfile); + if (ret != NC_NOERR) handle_error(ret); + + start[0] = rank; + count[0] = 1; + for (i=0; i<512; i++) buf[i] = rank; + ret = ncmpi_put_vars_int_all(ncfile, varid, start, count, NULL, buf); + if (ret != NC_NOERR) handle_error(ret); + + ret = ncmpi_close(ncfile); + if (ret != NC_NOERR) handle_error(ret); + + MPI_Finalize(); + +} Index: /tags/v1-0-3/README.CRAY-X1 =================================================================== --- /tags/v1-0-3/README.CRAY-X1 (revision 454) +++ /tags/v1-0-3/README.CRAY-X1 (revision 454) @@ -0,0 +1,38 @@ +# 2 May 2005 +# pnetcdf on the Cray X1 + +I performed the following steps to get Parallel-NetCDF to build on the Cray X1 +at Oak Ridge (phoenix.ccs.ornl.gov). Note that out-of-tree (or VPATH) builds +do not work for the Fortran interface as of 1.0.0-pre2, but we will try to +address this issue in a future release. + +prompt:$ module load mpt +prompt:$ export CC=cc +prompt:$ export FC=ftn +prompt:$ export MPIF77=$FC +prompt:$ export MPICC=$CC +prompt:$ export FFLAGS="-eh" +prompt:$ ./configure --prefix=/path/to/install +# note: configure takes a fairly long time. +prompt:$ make + +The "nc_test" test will exhaust the available MPI datatypes on the X1. Your +application might see this error: + + MPI has run out of internal datatype entries. + Please set the environment variable MPI_TYPE_MAX for additional space. + The current value of MPI_TYPE_MAX is 2098 + +I did as asked and nc_test completed with MPI_TYPE_MAX set to 4096 + +If you run on the login node, expect to see a lot of these messages: + + Process [nc_test] 89345 generated trap, but has signal 8 held or ignored + epc 0x1219bb4 ra 0x1219b94 badvaddr 0x40004f0004000020 + +The messages don't *appear* to impact the program results, and additionally do +not show up if you submit the job to PBS. + +Fortran codes should use '-eh' so that the Cray ftn compiler will use 1 byte +for int*1 and 2 bytes for int*2. Otherwise, our Fortran bindings will pass +incorrect values to the C routines. Index: /tags/v1-0-3/README.IRIX64 =================================================================== --- /tags/v1-0-3/README.IRIX64 (revision 278) +++ /tags/v1-0-3/README.IRIX64 (revision 278) @@ -0,0 +1,8 @@ +The pnetcdf library should build fine under IRIX. There are just a few +issues not directly related to the library: + +. The IRIX compiler does not like the cnap.c test. gcc compiles the + file without any warnings, even when the tests are configured with + "--enable-strict". Renier Vogelsang reports that the + latest MIPSpro compiler release fixes this issue, so upgrade if + possible. Index: /tags/v1-0-3/Makefile.in =================================================================== --- /tags/v1-0-3/Makefile.in (revision 323) +++ /tags/v1-0-3/Makefile.in (revision 323) @@ -0,0 +1,163 @@ +# $Id$ + +srcdir = @srcdir@ +VPATH = @srcdir@ +INSTALL = @INSTALL@ + +include macros.make + + +PACKAGE = parallel-netcdf +SUBDIRS = src/lib man +DIST_GARBAGE = \ + config.cache \ + config.status +PACKING_LIST = \ + Makefile \ + aclocal.m4 \ + configure \ + configure.in \ + macros.make.in \ + macros.make.def \ + rules.make + + +all: src/lib/all + +install: src/lib/install src/util/install + +uninstall: src/lib/uninstall + +clean: src/lib/clean test/clean + +distclean: src/lib/distclean \ + clean_macros + +tests: + @cd test && $(MAKE) + +testing: + @cd test && $(MAKE) testing + +clean_macros: + -cp macros.make.def macros.make + +# short names for making things in subdirs +test/clean \ +src/lib/all \ +src/lib/test \ +src/lib/install \ +src/lib/uninstall \ +src/lib/clean \ +src/lib/distclean \ +src/util/install \ +src/util/clean \ +: + @subdir=`echo $@ | sed 's,/.*,,'`; \ + target=`echo $@ | sed 's,.*/,,'`; \ + $(MAKE) SUBDIR=$$subdir TGET=$$target subdir_target + +subdir_target: + @echo "" + @cd $(SUBDIR) && \ + echo "Making \`$(TGET)' in directory `pwd`" && \ + echo "" && \ + $(MAKE) $(TGET) || exit 1 + @echo "" + @echo "Returning to directory `pwd`" + @echo "" + +install: whatis +whatis: $(MANDIR)/$(WHATIS) +$(MANDIR)/$(WHATIS): $(MANDIR) + $(MAKEWHATIS_CMD) +uninstall: + rm -f $(MANDIR)/$(WHATIS) + + +################################################################################ +# Distribution: + +# The following rule checks to see that were on the right system. If we're +# not, then the distribution mightn't contain the intended ncgen(1) (not +# to mention that dvips(1) is necessary for building the C++ User's Guide). +# +check_system: FORCE + @case "$(OVERRIDE)" in \ + '') case `uname -sr` in \ + 'SunOS 5'*) \ + exit 0;; \ + *) echo 1>&2 "Error: Not on a SunOS 5 system."; \ + echo 1>&2 "Set macro OVERRIDE to override."; \ + exit 1;; \ + esac;; \ + *) exit 0;; \ + esac + +# Make a compressed, tar(1) file of the source distribution in the current +# directory. +# +tar.Z: check_system FORCE + @version=`cat VERSION`; \ + $(MAKE) $(MFLAGS) $(PACKAGE)-$$version.tar.Z VERSION=$$version + +$(PACKAGE)-$(VERSION).tar.Z: ensure_manifest MANIFEST + id=$(PACKAGE)-$(VERSION) \ + && rm -rf $$id \ + && mkdir $$id \ + && ln -s .. $$id/src \ + && tar $(TARFLAGS) - `sed "s|^|$$id/src/|" MANIFEST` | compress > $@ \ + && rm -r $$id + +MANIFEST: FORCE + $(MAKE) MANIFEST.echo >$@ + +# Make a compressed, tar(1) file of the source distribution in the +# appropriate FTP directory. +# +# NOTE: Making "ftp" will cause the "tar.Z" file to be made even if it +# already exists. This is because the MANIFEST file upon which it +# depends must be remade every time. This is not a waste of time, +# however, if the "tar.Z" target is made in private directories and the +# "ftp" target is made in the "/upc/$(PACKAGE)/build/" directory. +# +ftp: check_system FORCE + version=`cat VERSION`; \ + $(MAKE) $(MFLAGS) $(FTPDIR)/$(PACKAGE)-$$version.tar.Z \ + VERSION=$$version; \ + test -r $(FTPDIR)/$(PACKAGE).tar.Z || exit 0; \ + cd $(FTPDIR) || exit 1; + +$(FTPDIR)/$(PACKAGE)-$(VERSION).tar.Z: $(PACKAGE)-$(VERSION).tar.Z + rm -f $@ + cp $(PACKAGE)-$(VERSION).tar.Z $@ + chmod u+rw,g+rw,o=r $@ + +# Make a compressed, tar(1) file of the binary distribution in the +# appropriate FTP directory. +# +binftp: FORCE + version=`cat VERSION`; \ + $(MAKE) $(MFLAGS) $(FTPBINDIR)/$(PACKAGE)-$$version.tar.Z \ + VERSION=$$version +ftpbin: binftp + +$(FTPBINDIR)/$(PACKAGE)-$(VERSION).tar.Z: + rm -f $@ + id=$(PACKAGE)-$(VERSION) \ + && rm -f $$id \ + && ln -s $(prefix) $$id \ + && tar $(TARFLAGS) - README $$id/bin $$id/include \ + $$id/lib $$id/man | compress > $@ \ + && rm $$id + chmod u+rw,g+rw,o=r $@ + test -r $(FTPBINDIR)/$(PACKAGE).tar.Z || exit 0; \ + cd $(FTPBINDIR) || exit 1; + + +# rule for generating cscope information +cscope: + find $(srcdir) -iname "*.[ch]" > $(srcdir)/cscope.files + ( cd $(srcdir); cscope -be -i $(srcdir)/cscope.files ) + +include $(srcdir)/rules.make Index: /tags/v1-0-3/configure.in =================================================================== --- /tags/v1-0-3/configure.in (revision 628) +++ /tags/v1-0-3/configure.in (revision 628) @@ -0,0 +1,431 @@ +AC_REVISION($Id$)dnl +dnl -*- Mode: shell-script-mode; -*- +dnl Process this file with GNU autoconf(1) to produce a configure script. +dnl + +dnl Defaults: +CPPFLAGS=${CFLAGS} +CFLAGS=${CFLAGS--O} +FPPFLAGS=${FPPFLAGS-} +FFLAGS=${FFLAGS-} + +AC_INIT(src/lib/ncconfig.in) +AC_PREREQ(2.59) +UD_SRCDIR +dnl AC_PREFIX_DEFAULT(`(cd ..; pwd)`) + +dnl must be all on same line +AC_CONFIG_HEADER( src/lib/ncconfig.h:src/lib/ncconfig.in src/libf/pnetcdf.inc src/libf/nfconfig.inc:src/libf/nfconfig.in ) + +AC_CONFIG_AUX_DIR(./scripts) + +dnl these used to live in acconfig.h +AH_TEMPLATE([SIZEOF_OFF_T], [Number of bytes in a off_t]) +AH_TEMPLATE([SIZEOF_SIZE_T], [Number of bytes in a size_t]) +AH_TEMPLATE([NCBYTE_T], [Type of NC_BYTE]) +AH_TEMPLATE([NCSHORT_T], [Type of NC_SHORT]) +AH_TEMPLATE([NF_DOUBLEPRECISION_IS_C_], [C type for Fortran dobule]) +AH_TEMPLATE([NF_INT1_IS_C_], [C type for Fortran INT1]) +AH_TEMPLATE([NF_INT1_T], [Type for Fortran INT1]) +AH_TEMPLATE([NF_INT2_IS_C_], [C type for Fortran INT2]) +AH_TEMPLATE([NF_INT2_T], [Type for Fortran INT2]) +AH_TEMPLATE([NF_INT_IS_C_], [C type for Fortran INT]) +AH_TEMPLATE([NF_REAL_IS_C_], [C type for Fortran REAL]) +AH_TEMPLATE([NO_IEEE_FLOAT], [Does sytem have IEEE FLOAT]) +AH_TEMPLATE([NO_STRERROR], [Define if system lacks strerror]) + +AC_HEADER_STDC + +AC_ARG_ENABLE(fortran, +[ --enable-fortran Turn on support for the Fortran interface. Turn this + off if you only need the C interface (on by default)], + ,enable_fortran=yes) + +dnl I took the "-ansi" off the CFLAGS for the strict case, as it was +dnl preventing PATH_MAX from being defined for some of the test files, +dnl and I was having a tough time figuring out how to get it back! -- RobR +AC_ARG_ENABLE(strict, +[ --enable-strict Turn on strict debugging with gcc], +CFLAGS="$CFLAGS -O2 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wpointer-arith -Wbad-function-cast") +AC_ARG_ENABLE(echo, +[ --enable-echo Turn on strong echoing. The default is enable=no.] +,set -x) + +AC_PROG_INSTALL +AC_PROG_YACC +AC_PROG_LEX + +UD_PROG_M4 +AC_PROG_CC +dnl AC_PROG_CXX +dnl AC_PROG_F77 +if test "$enable_fortran" = "yes" ; then + if test -z "$FC" -a -n "$F77" ; then + FC="$F77" + fi + dnl 'UD_PROG_FC' is quite elaborate and does a whole lot more than just + dnl find a fortran compiler. it also checks fortran types and fortran + dnl calling convention. So don't change this to AC_PROG_FC :> + UD_PROG_FC +fi +UD_PROG_CC_MAKEDEPEND +dnl need a --with-cxx=no and --with-fortran=no +dnl UD_PROG_CXX +dnl UD_PROG_F90 +# Checking for Fortran types also determines the Fortran name mangling +# and places the value into FCALLSCSUB as a the C name corresponding +# to the Fortran name SUB +if test "$enable_fortran" = yes ; then + UD_CHECK_FCALLSCSUB +fi +UD_CHECK_LIB_MATH +UD_PROG_AR() +UD_PROG_NM() +# We could use the PAC check for ranlib (it also makes sure that ranlib works, +# which is not always true, particularly when GNU tools are installed on +# a system that doesn't have (or need) ranlib +AC_PROG_RANLIB + +# +# If we are building the Fortran interface, determine the correct name mapping +if test "$enable_fortran" = yes ; then + case $FCALLSCSUB in + SUB) + AC_DEFINE(F77_NAME_UPPER,,[Define if Fortran names are uppercase]) + ;; + sub_) + # This is the hard case. Gcc uses one _ unless the name includes + # an underscore, in which case it gets two trailing underscores. + # Use essentially the same configure code that the original configure + # used to determine SUB + AC_MSG_CHECKING(for C-equivalent to Fortran routine \"SUB_A\") + dnl " + cat >conftest.f <<\EOF + call sub_a() + end +EOF + doit='$FC -c ${FFLAGS} conftest.f' + if AC_TRY_EVAL(doit); then + FCALLSCSUBA=`$NM $NMFLAGS conftest.o | awk ' + /SUB_A_/{print "SUB_A_";exit} + /SUB_A/ {print "SUB_A"; exit} + /sub_a__/ {print "sub_a__"; exit} + /sub_a_/{print "sub_a_";exit} + /sub_a/ {print "sub_a"; exit}'` + case "$FCALLSCSUBA" in + '') AC_MSG_ERROR(not found) + ;; + *) AC_MSG_RESULT($FCALLSCSUBA) + ;; + esac + else + AC_MSG_ERROR(Could not compile conftest.f) + fi + rm -f conftest* + case "$FCALLSCSUBA" in + sub_a__) + AC_DEFINE(F77_NAME_LOWER_2USCORE,,[Define if Fortran names are lower case with two trailing underscore2]) + ;; + sub_a_) + AC_DEFINE(F77_NAME_LOWER_USCORE,,[Define if Fortran names are lower case with one trailing underscore]) + ;; + *) + AC_MSG_WARN([Unrecognized Fortran name mapping]) + ;; + esac + ;; + sub) + AC_DEFINE(F77_NAME_LOWER,,[Define if Fortran names are lower case]) + ;; + *) + AC_MSG_WARN([Unrecognized Fortran name mapping]) + ;; + esac +fi + +dnl do the automatic mpi-compiler-checking if MPICC and MPIF77 are not set +if test x${MPICC} = x -a x${MPIF77} = x ; then + MPICC=$CC + AC_MSG_CHECKING(mpi implementation) + AC_ARG_WITH(mpi, + [ --with-mpi=/path/to/implementation + installation prefix for mpi implementation], + if test x"$withval" = xyes; then + AC_MSG_ERROR(--with-mpi must be given a pathname) + else + AC_MSG_RESULT(using $withval) + MPICC=${withval}/bin/mpicc + if test ! -x "${MPICC}"; then + AC_MSG_WARN($MPICC either does not exist or is not executable: falling back to $CC) + MPICC="$CC" + fi + MPIF77=${withval}/bin/mpif77 + if test ! -x "${MPIF77}"; then + AC_MSG_WARN($MPIF77 either does not exist or is not executable: falling back to $FC) + MPIF77="$FC" + fi + + fi + ) +fi + + +AC_ARG_ENABLE(mpi-io-test, +[ --enable-mpi-io-test Check for MPI-IO support in MPI implementation. + Turn this off if you know your MPI + implementation has MPI-IO support but the + configure test fails to find it (on by default)] + ,,enable_mpi_io_test=yes ) + +if test "$enable_mpi_io_test" = "yes" ; then + AC_MSG_CHECKING(MPI-IO support in MPI implementation) + saveCC="$CC" + CC=$MPICC + AC_TRY_COMPILE([#include "mpi.h"], [int a = MPI_MODE_RDWR;], + AC_MSG_RESULT(yes), + AC_MSG_ERROR([mpi implementation does not support MPI-IO]) + ) + CC="$saveCC" +fi +AC_SUBST(MPICC) +AC_SUBST(MPIF77) + +AC_CHECK_HEADERS(stdlib.h sys/types.h mpio.h) + +AC_CHECK_FUNC(strerror, ,AC_DEFINE(NO_STRERROR)) +AC_FUNC_ALLOCA +AC_STRUCT_ST_BLKSIZE +UD_CHECK_IEEE +AC_TYPE_SIZE_T + +dnl +dnl *** SWITCHING TO USING MPICC *** +dnl +saveCC="$CC" +CC=$MPICC + +dnl compile-only check for size of MPI_Offset (thanks Christopher Subich +dnl ) + +AC_DEFUN([UD_MPI_OFFSET], [ + if test ! "$ac_cv_sizeof_MPI_Offset"; then + AC_MSG_CHECKING(if MPI_Offset is size $1) + AC_COMPILE_IFELSE([ + #include "mpi.h" + #include + int main (int argc, char **argv) + { + static int test_array [[sizeof (MPI_Offset) == $1 ? 1 : -1 ]]; + return 0; + }], AC_MSG_RESULT(yes) + ac_cv_sizeof_MPI_Offset=$1, + AC_MSG_RESULT(no)) + fi +]) + +UD_MPI_OFFSET(8) +UD_MPI_OFFSET(4) +UD_MPI_OFFSET(16) + +# the nonblocking routines need these functions +enable_nonblocking=yes +AC_CHECK_FUNCS(MPI_Request_get_status MPI_Type_dup,, + enable_nonblocking=no +) + +AC_CHECK_FUNCS(MPI_Info_dup,,) + +if test "$enable_nonblocking" = "yes" ; then + AC_DEFINE(ENABLE_NONBLOCKING,,[Define if able to support nonblocking routines]) +fi + +dnl Check for presence of various MPI_COMBINERs. These could be +dnl enums, so we have to do compile checks. + +AC_DEFUN([UD_HAS_MPI_COMBINER], [ + AC_MSG_CHECKING(if MPI includes $1) + AC_TRY_COMPILE([ #include ], + [int combiner = $1; ], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_$1, 1, available), + AC_MSG_RESULT(no) + ) + ] +) + +UD_HAS_MPI_COMBINER(MPI_COMBINER_DUP) +UD_HAS_MPI_COMBINER(MPI_COMBINER_HVECTOR_INTEGER) +UD_HAS_MPI_COMBINER(MPI_COMBINER_HINDEXED_INTEGER) +UD_HAS_MPI_COMBINER(MPI_COMBINER_SUBARRAY) +UD_HAS_MPI_COMBINER(MPI_COMBINER_DARRAY) +UD_HAS_MPI_COMBINER(MPI_COMBINER_RESIZED) +UD_HAS_MPI_COMBINER(MPI_COMBINER_STRUCT_INTEGER) +UD_HAS_MPI_COMBINER(MPI_COMBINER_INDEXED_BLOCK) +UD_HAS_MPI_COMBINER(MPI_COMBINER_F90_REAL) +UD_HAS_MPI_COMBINER(MPI_COMBINER_F90_INTEGER) +UD_HAS_MPI_COMBINER(MPI_COMBINER_F90_COMPLEX) + +dnl Check for presence of Fortran types +dnl +dnl We do this for a couple of reasons. First, the MPI might have been +dnl built without Fortran support, in which case these types might not +dnl exist. Second, we need to map these types to corresponding C types +dnl where possible to simplify processing at runtime. + +AC_DEFUN([UD_HAS_MPI_TYPE], [ + AC_MSG_CHECKING(if MPI includes $1) + AC_TRY_COMPILE([ #include ], + [int datatype = $1; ], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_$1, 1, available), + AC_MSG_RESULT(no) + ) + ] +) + +UD_HAS_MPI_TYPE(MPI_CHARACTER) +UD_HAS_MPI_TYPE(MPI_REAL) +UD_HAS_MPI_TYPE(MPI_INTEGER) +UD_HAS_MPI_TYPE(MPI_DOUBLE_PRECISION) +UD_HAS_MPI_TYPE(MPI_INTEGER1) +UD_HAS_MPI_TYPE(MPI_INTEGER2) +UD_HAS_MPI_TYPE(MPI_INTEGER4) +UD_HAS_MPI_TYPE(MPI_INTEGER8) +UD_HAS_MPI_TYPE(MPI_INTEGER16) +UD_HAS_MPI_TYPE(MPI_REAL4) +UD_HAS_MPI_TYPE(MPI_REAL8) +UD_HAS_MPI_TYPE(MPI_REAL16) +UD_HAS_MPI_TYPE(MPI_COMPLEX8) +UD_HAS_MPI_TYPE(MPI_COMPLEX16) +UD_HAS_MPI_TYPE(MPI_COMPLEX32) +UD_HAS_MPI_TYPE(MPI_UB) +UD_HAS_MPI_TYPE(MPI_LB) + +dnl +dnl *** GOING BACK TO REGULAR CC *** +dnl +CC="$saveCC" + +AC_TYPE_OFF_T +AC_CHECK_TYPES([ssize_t, ptrdiff_t, uchar]) +AC_C_CHAR_UNSIGNED +AC_C_BIGENDIAN +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(float) +AC_CHECK_SIZEOF(double) +AC_CHECK_SIZEOF(size_t) + +dnl Check the size of MPI_Offset +dnl As some platforms don't allow running MPI-linked executives directly, +dnl the test program is only compiled with MPICC inorder to know "mpi.h" +dnl and is linked with CC to allow direct run in the script. +AC_CACHE_CHECK([sizeof MPI_Offset],ac_cv_sizeof_MPI_Offset, +[ + cat >conftest.c < +int main( int argc, char **argv ) +{ + MPI_Offset a; + FILE *f = fopen("conftestval", "w" ); + if (! f) return 1; + fprintf( f, "%ld\n", (long)sizeof(a) ); + fclose(f); + return 0; +} +EOF + +if $MPICC -c conftest.c && $MPICC -o conftest conftest.o ; then + if ./conftest ; then + #success + ac_cv_sizeof_MPI_Offset=`cat conftestval` + else + # failure + AC_MSG_WARN([Unable to run the program to determine sizeof MPI_Offset]) + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -f conftest* +else + AC_MSG_ERROR([Unable to compile or link the test program]) +fi +]) + +dnl according to autoconf-2.57, this is the correct way to use AC_CACHE_CHECK: call AC_DEFINE after AC_CACHE_CHECK +AC_DEFINE_UNQUOTED(SIZEOF_MPI_OFFSET, $ac_cv_sizeof_MPI_Offset, [The number of bytes in an MPI_Offset]) + +if test "$enable_fortran" = yes ; then + UD_FORTRAN_TYPES + + NFMPI_OFFSET="integer*$ac_cv_sizeof_MPI_Offset" + AC_MSG_CHECKING(for Fortran \"$NFMPI_OFFSET\") # " + cat >conftest.f <pnetcdf.inc && mv pnetcdf.inc src/libf/pnetcdf.inc +sed -e "s%/\*%!%g" -e "s%\*/%%g" nfconfig.inc && mv nfconfig.inc src/libf/nfconfig.inc + +if test "$enable_mpi_io_test" != "yes" ; then + AC_MSG_WARN([ +"NOTE: disabling the MPI-IO test is a VERY bad idea. Please make sure you know what you are doing"]) +fi + +echo "" +echo "parallel-netCDF features:" +if test "$ac_cv_sizeof_off_t" -gt 4 ; then + echo ". parallel-netcdf configured WITH support for large files" +else + echo ". parallel-netcdf configured WITHOUT support for large files" +fi +if test "$enable_fortran" = "yes" ; then + echo ". parallel-netcdf configured WITH fortran bindings" +else + echo ". parallel-netcdf configured WITHOUT fortran bindings" +fi +if test "$enable_nonblocking" = "yes" ; then + echo ". parallel-netcdf configured WITH nonblocking routines" +else + echo ". parallel-netcdf configured WITHOUT nonblocking routines" +fi Index: /tags/v1-0-3/README.SX =================================================================== --- /tags/v1-0-3/README.SX (revision 500) +++ /tags/v1-0-3/README.SX (revision 500) @@ -0,0 +1,37 @@ +# Current notes for NEC SX; based on pnetcdf version 1.0.0; 28 July, 2005 + +. SX Cross compiler environment is not supported yet (the check for a working + ftruncate is not possible). Configure steps have to be invoked on the SX directly. + Configuring on the target host and then cross-compling works fine when setting + up necessary aliases on the configrue host (cc -> sxcc, etc) or vice versa + on the compile host (sxcc -> cc). + +. With the following environment variables a pnetcdflib.a has been + built successfully + + MPICC=mpic++ + MPIF77=mpif90 + FC=f90 + CC=c++ + FFLAGS=-dW + +. Built on NEC SX6 with: + - Operating system SUPER-UX 14.1 + - C++/SX compiler rev.061 2004/01/06 + - f90/SX compiler rev.285 2003/09/25 + +. Note on nf_test + -dW disables promotion of Integer*2. However no interfaces + for Integer*1 are built. This causes 2 compile time errors + in util.F . Lines 1158 and 1226 have to be turned into valid + Fortran syntax. + +. Note on test_dtype + The executables have to be compiled with -pvctl loopcnt=186048. + To avoid run time error in test_array the vectorisation of the + loop starting at line 256 needs to be disabled with + #pragma cdir novector + +Rob Latham +Rene Redler +Joachim Worringen Index: /tags/v1-0-3/scripts/install-sh =================================================================== --- /tags/v1-0-3/scripts/install-sh (revision 156) +++ /tags/v1-0-3/scripts/install-sh (revision 156) @@ -0,0 +1,250 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 Index: /tags/v1-0-3/src/utils/Makefile.in =================================================================== --- /tags/v1-0-3/src/utils/Makefile.in (revision 321) +++ /tags/v1-0-3/src/utils/Makefile.in (revision 321) @@ -0,0 +1,22 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ +SUBDIRS = ncgen ncdump + +all: ncmpigen ncmpidump + +ncmpigen: + cd ncgen && $(MAKE) + +ncmpidump: + cd ncdump && $(MAKE) + +clean: + set -e; for i in $(SUBDIRS); do ( cd $$i && $(MAKE) clean ; ) ; done + +install: ncgen_install ncdump_install + +ncgen_install: + cd ncgen && $(MAKE) install + +ncdump_install: + cd ncdump && $(MAKE) install Index: /tags/v1-0-3/src/utils/ncdump/depend =================================================================== --- /tags/v1-0-3/src/utils/ncdump/depend (revision 314) +++ /tags/v1-0-3/src/utils/ncdump/depend (revision 314) @@ -0,0 +1,13 @@ +dumplib.o: $(srcdir)/../../../src/lib/pnetcdf.h +dumplib.o: dumplib.c +dumplib.o: dumplib.h +ncdump.o: $(srcdir)/../../../src/lib/pnetcdf.h +ncdump.o: dumplib.h +ncdump.o: ncdump.c +ncdump.o: ncdump.h +ncdump.o: vardata.h +vardata.o: $(srcdir)/../../../src/lib/pnetcdf.h +vardata.o: dumplib.h +vardata.o: ncdump.h +vardata.o: vardata.c +vardata.o: vardata.h Index: /tags/v1-0-3/src/utils/ncdump/test0.cdl =================================================================== --- /tags/v1-0-3/src/utils/ncdump/test0.cdl (revision 314) +++ /tags/v1-0-3/src/utils/ncdump/test0.cdl (revision 314) @@ -0,0 +1,41 @@ +netcdf test0 { + +dimensions: + i = 2; + j = 3; + k = unlimited; + l = 3 ; + +variables: + char broiled(i,j,l); + broiled:act = "text string\n\t123"; + broiled:acb = 10b; + broiled:acs = -200s ; + broiled:acl = 17000 ; + broiled:acf = -2.0f, 1.f, 0.0f ; + broiled:acd = -1.0, 2.7182818284590455; + short order(i,j); + int rigue(i,j); + float a_loan(i,j); + double entendre(i,j); + char cscalar; + double dscalar; + char cnodata(i); + short snodata(i); + int inodata(i); + float fnodata(i); + double dnodata(i); + int i(i); + float j(j); + + :glob = "Global attribute" ; + +data: + broiled = "indistinguishable" ; + order = 1s, 2s, 3s, 4s, 5s, 6s; + rigue = 2, 3, 4, 5, 6, 7 ; + a_loan = 3.f, 4.f, 5.f, 6.f, 7.f, 1.0e12f ; + entendre = '\4', 5s, 6, 7.0f, 8.0, 1.0e30 ; + i = 10, 20; + j = 2, 4, 6; +} Index: /tags/v1-0-3/src/utils/ncdump/Makefile.in =================================================================== --- /tags/v1-0-3/src/utils/ncdump/Makefile.in (revision 322) +++ /tags/v1-0-3/src/utils/ncdump/Makefile.in (revision 322) @@ -0,0 +1,63 @@ +# Makefile for ncmpidump(1). +# +# $Id$ + +srcdir = @srcdir@ +VPATH = @srcdir@ +INSTALL = @INSTALL@ + +include ../../../macros.make + +NCGEN = ../ncgen/ncmpigen +INCLUDES = -I$(srcdir)/../../../src/lib -I$(srcdir) + +c_sources = ncdump.c vardata.c dumplib.c +headers = ncdump.h vardata.h dumplib.h + +PROGRAM = ncmpidump + +PACKING_LIST = $(c_sources) $(headers) depend \ + test0.cdl ncmpidump.1 Makefile +MANUAL = ncmpidump.1 + +lib_netcdf = ../../../src/lib/libpnetcdf.a +ld_netcdf = -L../../../src/lib -lpnetcdf + +OBJS = ncdump.o vardata.o dumplib.o +GARBAGE = $(PROGRAM) test0.nc test1.nc test1.cdl test2.cdl + +all: $(PROGRAM) + +$(PROGRAM): $(lib_netcdf) $(OBJS) + $(LINK.c) $(OBJS) $(ld_netcdf) $(LIBS) + +test: $(PROGRAM) FORCE + $(NCGEN) -b $(srcdir)/test0.cdl -o `pwd`/test0.nc + ./$(PROGRAM) -n test1 test0.nc > test1.cdl + $(NCGEN) -b `pwd`/test1.cdl -o `pwd`/test1.nc + ./$(PROGRAM) test1.nc > test2.cdl + @cmp test1.cdl test2.cdl && \ + echo "*** $(PROGRAM) test successful ***" + +install: + $(INSTALL) -d -m 755 $(MANDIR)/manl + $(INSTALL) -m 644 $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL) + + $(INSTALL) -d $(BINDIR) + $(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM) + +uninstall: + -rm -f $(BINDIR)/$(PROGRAM) + -rm -f $(MANDIR)/man1/$(MANUAL) + +$(PROGRAM)_oc : $(c_sources) + #setopt primary_language C + #load -C $(CPPFLAGS) $(c_sources) + #load -C $(LIBS) + #setopt program_name $(PROGRAM) + +TAGS: FORCE + etags `echo $(PACKING_LIST) | fmt -1 | egrep '\.c|\.h' + +include $(srcdir)/../../../rules.make +include $(srcdir)/depend Index: /tags/v1-0-3/src/utils/ncdump/dumplib.h =================================================================== --- /tags/v1-0-3/src/utils/ncdump/dumplib.h (revision 430) +++ /tags/v1-0-3/src/utils/ncdump/dumplib.h (revision 430) @@ -0,0 +1,72 @@ +/********************************************************************* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +extern char *progname; /* for error messages */ + +#define NO_NETCDF_2 /* assert we aren't using any netcdf-2 stuff */ + +#ifndef EXIT_FAILURE +#ifndef vms +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#else +#define EXIT_SUCCESS 1 +#define EXIT_FAILURE 0 +#endif +#endif + +#define FLT_DIGITS 7 /* default sig. digits for float data */ +#define DBL_DIGITS 15 /* default sig. digits for double data */ + +extern int float_precision_specified; /* -p option specified float precision */ +extern int double_precision_specified; /* -p option specified double precision */ +extern char float_var_fmt[]; +extern char double_var_fmt[]; +extern char float_att_fmt[]; +extern char double_att_fmt[]; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Print error message to stderr and exit */ +extern void error ( const char *fmt, ... ); + +/* set position in line before lput() calls */ +extern void set_indent ( int indent ); + +/* set maximum line length */ +extern void set_max_len ( int len ); + +/* splits lines to keep them short */ +extern void lput ( const char *string ); + +/* In case different formats specified with -d option, set them here. */ +extern void set_formats ( int flt_digs, int dbl_digs ); + +/* Determine print format to use for each value for this variable. */ +const char * get_fmt ( int ncid, int varid, nc_type type ); + +/* structure for list of variables specified with -v option */ +struct vnode +{ + struct vnode* next; + int id; +}; +typedef struct vnode vnode; + +/* Get new variable list */ +extern vnode* newvlist ( void ); + +/* Add a variable id to variable list */ +extern void varadd ( vnode* vlist, int varid ); + +/* Test if a variable id is in variable list */ +extern int varmember ( const vnode* vlist, int varid ); + +#ifdef __cplusplus +} +#endif Index: /tags/v1-0-3/src/utils/ncdump/vardata.c =================================================================== --- /tags/v1-0-3/src/utils/ncdump/vardata.c (revision 430) +++ /tags/v1-0-3/src/utils/ncdump/vardata.c (revision 430) @@ -0,0 +1,862 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include +#include +#include +#include +#ifndef NO_FLOAT_H +#include /* for FLT_EPSILON, DBL_EPSILON */ +#endif /* NO_FLOAT_H */ + +#include +#include "ncdump.h" +#include "dumplib.h" +#include "vardata.h" + +static float float_epsilon(void); +static double double_epsilon(void); +static void init_epsilons(void); +static void printbval(char* sout, const char* fmt, const struct ncvar* varp, + signed char val); +static void printsval(char* sout, const char* fmt, const struct ncvar* varp, + short val); +static void printival(char* sout, const char* fmt, const struct ncvar* varp, + int val); +static void printfval(char* sout, const char* fmt, const struct ncvar* varp, + float val); +static void printdval(char* sout, const char* fmt, const struct ncvar* varp, + double val); +static void lastdelim(boolean more, boolean lastrow); +static void annotate(const struct ncvar* vp, const struct fspec* fsp, + const MPI_Offset* cor, long iel); +static void pr_tvals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const char *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static void pr_bvals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const signed char *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static void pr_svals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const short *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static void pr_ivals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const int *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static void pr_fvals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const float *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static void pr_dvals(const struct ncvar *vp, size_t len, const char *fmt, + boolean more, boolean lastrow, const double *vals, + const struct fspec* fsp, const MPI_Offset *cor); +static int upcorner(const size_t* dims, int ndims, MPI_Offset* odom, + const size_t* add); +static void lastdelim2 (boolean more, boolean lastrow); + +#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) + +static float float_eps; +static double double_eps; + +static float +float_epsilon(void) +{ + float float_eps; +#ifndef NO_FLOAT_H + float_eps = FLT_EPSILON; +#else /* NO_FLOAT_H */ + { + float etop, ebot, eps; + float one = 1.0; + float two = 2.0; + etop = 1.0; + ebot = 0.0; + eps = ebot + (etop - ebot)/two; + while (eps != ebot && eps != etop) { + float epsp1; + + epsp1 = one + eps; + if (epsp1 > one) + etop = eps; + else + ebot = eps; + eps = ebot + (etop - ebot)/two; + } + float_eps = two * etop; + } +#endif /* NO_FLOAT_H */ + return float_eps; +} + + +static double +double_epsilon(void) +{ + double double_eps; +#ifndef NO_FLOAT_H + double_eps = DBL_EPSILON; +#else /* NO_FLOAT_H */ + { + double etop, ebot, eps; + double one = 1.0; + double two = 2.0; + etop = 1.0; + ebot = 0.0; + eps = ebot + (etop - ebot)/two; + while (eps != ebot && eps != etop) { + double epsp1; + + epsp1 = one + eps; + if (epsp1 > one) + etop = eps; + else + ebot = eps; + eps = ebot + (etop - ebot)/two; + } + double_eps = two * etop; + } +#endif /* NO_FLOAT_H */ + return double_eps; +} + + +static void +init_epsilons(void) +{ + float_eps = float_epsilon(); + double_eps = double_epsilon(); +} + +/* + * Output a value of a byte variable, except if there is a fill value for + * the variable and the value is the fill value, print the fill-value string + * instead. + */ +static void +printbval( + char *sout, /* string where output goes */ + const char *fmt, /* printf format used for value */ + const struct ncvar *varp, /* variable */ + signed char val /* value */ + ) +{ + if (varp->has_fillval) { + double fillval = varp->fillval; + if(fillval == val) { + (void) sprintf(sout, FILL_STRING); + return; + } + } + (void) sprintf(sout, fmt, val); +} + +/* + * Output a value of a short variable, except if there is a fill value for + * the variable and the value is the fill value, print the fill-value string + * instead. + */ +static void +printsval( + char *sout, /* string where output goes */ + const char *fmt, /* printf format used for value */ + const struct ncvar *varp, /* variable */ + short val /* value */ + ) +{ + if (varp->has_fillval) { + double fillval = varp->fillval; + if(fillval == val) { + (void) sprintf(sout, FILL_STRING); + return; + } + } + (void) sprintf(sout, fmt, val); +} + + +/* + * Output a value of an int variable, except if there is a fill value for + * the variable and the value is the fill value, print the fill-value string + * instead. + */ +static void +printival( + char *sout, /* string where output goes */ + const char *fmt, /* printf format used for value */ + const struct ncvar *varp, /* variable */ + int val /* value */ + ) +{ + if (varp->has_fillval) { + int fillval = (int)varp->fillval; + if(fillval == val) { + (void) sprintf(sout, FILL_STRING); + return; + } + } + (void) sprintf(sout, fmt, val); +} + + +#define absval(x) ( (x) < 0 ? -(x) : (x) ) + +/* + * Output a value of a float variable, except if there is a fill value for + * the variable and the value is the fill value, print the fill-value string + * instead. Floating-point fill values need only be within machine epsilon of + * defined fill value. + */ +static void +printfval( + char *sout, /* string where output goes */ + const char *fmt, /* printf format used for value */ + const struct ncvar *varp, /* variable */ + float val /* value */ + ) +{ + if(varp->has_fillval) { + double fillval = varp->fillval; + if((val > 0) == (fillval > 0) && /* prevents potential overflow */ + (absval(val - fillval) <= absval(float_eps * fillval))) { + (void) sprintf(sout, FILL_STRING); + return; + } + } + (void) sprintf(sout, fmt, val); +} + + +/* + * Output a value of a double variable, except if there is a fill value for + * the variable and the value is the fill value, print the fill-value string + * instead. Floating-point fill values need only be within machine epsilon of + * defined fill value. + */ +static void +printdval( + char *sout, /* string where output goes */ + const char *fmt, /* printf format used for value */ + const struct ncvar *varp, /* variable */ + double val /* value */ + ) +{ + if(varp->has_fillval) { + double fillval = varp->fillval; + if((val > 0) == (fillval > 0) && /* prevents potential overflow */ + (absval(val - fillval) <= absval(double_eps * fillval))) { + (void) sprintf(sout, FILL_STRING); + return; + } + } + (void) sprintf(sout, fmt, val); +} + + +/* + * print last delimiter in each line before annotation (, or ;) + */ +static void +lastdelim (boolean more, boolean lastrow) +{ + if (more) { + Printf(", "); + } else { + if(lastrow) { + Printf(";"); + } else { + Printf(","); + } + } +} + +/* + * print last delimiter in each line before annotation (, or ;) + */ +static void +lastdelim2 (boolean more, boolean lastrow) +{ + if (more) { + lput(", "); + } else { + if(lastrow) { + lput(" ;"); + lput("\n"); + } else { + lput(",\n"); + lput(" "); + } + } +} + + +/* + * Annotates a value in data section with var name and indices in comment + */ +static void +annotate( + const struct ncvar *vp, /* variable */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor, /* corner coordinates */ + long iel /* which element in current row */ + ) +{ + int vrank = vp->ndims; + int id; + + /* print indices according to data_lang */ + (void) printf(" // %s(", vp->name); + switch (fsp->data_lang) { + case LANG_C: + /* C variable indices */ + for (id = 0; id < vrank-1; id++) + Printf("%lu,", (unsigned long) cor[id]); + Printf("%lu", (unsigned long) cor[id] + iel); + break; + case LANG_F: + /* Fortran variable indices */ + Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1); + for (id = vrank-2; id >=0 ; id--) { + Printf(",%lu", 1 + (unsigned long) cor[id]); + } + break; + } + Printf(")\n "); +} + + +/* + * Print a number of char variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_tvals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const char *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + const char *sp; + unsigned char uc; + char sout[100]; /* temporary string for each encoded output */ + + if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */ + Printf("\""); + /* adjust len so trailing nulls don't get printed */ + sp = vals + len; + while (len != 0 && *--sp == '\0') + len--; + for (iel = 0; iel < len; iel++) + switch (uc = *vals++ & 0377) { + case '\b': + Printf("\\b"); + break; + case '\f': + Printf("\\f"); + break; + case '\n': /* generate linebreaks after new-lines */ + Printf("\\n\",\n \""); + break; + case '\r': + Printf("\\r"); + break; + case '\t': + Printf("\\t"); + break; + case '\v': + Printf("\\v"); + break; + case '\\': + Printf("\\\\"); + break; + case '\'': + Printf("\\\'"); + break; + case '\"': + Printf("\\\""); + break; + default: + if (isprint(uc)) + Printf("%c",uc); + else + Printf("\\%.3o",uc); + break; + } + Printf("\""); + if (fsp->full_data_cmnts) { + Printf("\""); + lastdelim (more, lastrow); + annotate (vp, fsp, (MPI_Offset*)cor, 0L); + } + } else { /* use format from C_format attribute */ + for (iel = 0; iel < len-1; iel++) { + if (fsp->full_data_cmnts) { + Printf(fmt, *vals++); + Printf(", "); + annotate (vp, fsp, (MPI_Offset *)cor, iel); + } else { + (void) sprintf(sout, fmt, *vals++); + (void) strcat(sout, ", "); + lput(sout); + } + } + if (fsp->full_data_cmnts) { + Printf(fmt, *vals++); + lastdelim (more, lastrow); + annotate (vp, fsp, (MPI_Offset *)cor, iel); + } else { + (void) sprintf(sout, fmt, *vals++); + lput(sout); + } + } + if (!fsp->full_data_cmnts) { + lastdelim2 (more, lastrow); + } +} + + +/* + * Print a number of byte variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_bvals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const signed char *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + char sout[100]; /* temporary string for each encoded output */ + + for (iel = 0; iel < len-1; iel++) { + printbval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + Printf(","); + annotate (vp, fsp, cor, iel); + } else { + (void) strcat(sout, ", "); + lput(sout); + } + } + printbval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + lastdelim (more, lastrow); + annotate (vp, fsp, cor, iel); + } else { + lput(sout); + lastdelim2 (more, lastrow); + } +} + + +/* + * Print a number of short variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_svals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const short *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + char sout[100]; /* temporary string for each encoded output */ + + for (iel = 0; iel < len-1; iel++) { + printsval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + Printf(","); + annotate (vp, fsp, cor, iel); + } else { + (void) strcat(sout, ", "); + lput(sout); + } + } + printsval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + lastdelim (more, lastrow); + annotate (vp, fsp, cor, iel); + } else { + lput(sout); + lastdelim2 (more, lastrow); + } +} + + + + +/* + * Print a number of int variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_ivals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const int *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + char sout[100]; /* temporary string for each encoded output */ + + for (iel = 0; iel < len-1; iel++) { + printival(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + Printf(","); + annotate (vp, fsp, cor, iel); + } else { + (void) strcat(sout, ", "); + lput(sout); + } + } + printival(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + lastdelim (more, lastrow); + annotate (vp, fsp, cor, iel); + } else { + lput(sout); + lastdelim2 (more, lastrow); + } +} + + +/* + * Print a number of float variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_fvals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const float *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + char sout[100]; /* temporary string for each encoded output */ + + for (iel = 0; iel < len-1; iel++) { + printfval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + Printf(","); + annotate (vp, fsp, cor, iel); + } else { + (void) strcat(sout, ", "); + lput(sout); + } + } + printfval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + lastdelim (more, lastrow); + annotate (vp, fsp, cor, iel); + } else { + lput(sout); + lastdelim2 (more, lastrow); + } +} + + +/* + * Print a number of double variable values, where the optional comments + * for each value identify the variable, and each dimension index. + */ +static void +pr_dvals( + const struct ncvar *vp, /* variable */ + size_t len, /* number of values to print */ + const char *fmt, /* printf format used for each value. If + * ncmpi_type is NC_CHAR and this is NULL, + * character arrays will be printed as + * strings enclosed in quotes. */ + boolean more, /* true if more data for this row will + * follow, so add trailing comma */ + boolean lastrow, /* true if this is the last row for this + * variable, so terminate with ";" instead + * of "," */ + const double *vals, /* pointer to block of values */ + const struct fspec* fsp, /* formatting specs */ + const MPI_Offset *cor /* corner coordinates */ + ) +{ + long iel; + char sout[100]; /* temporary string for each encoded output */ + + for (iel = 0; iel < len-1; iel++) { + printdval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + Printf(","); + annotate (vp, fsp, cor, iel); + } else { + (void) strcat(sout, ", "); + lput(sout); + } + } + printdval(sout, fmt, vp, *vals++); + if (fsp->full_data_cmnts) { + Printf(sout); + lastdelim (more, lastrow); + annotate (vp, fsp, cor, iel); + } else { + lput(sout); + lastdelim2 (more, lastrow); + } +} + + +/* + * Updates a vector of ints, odometer style. Returns 0 if odometer + * overflowed, else 1. + */ +static int +upcorner( + const size_t *dims, /* The "odometer" limits for each dimension */ + int ndims, /* Number of dimensions */ + MPI_Offset* odom, /* The "odometer" vector to be updated */ + const size_t* add /* A vector to "add" to odom on each update */ + ) +{ + int id; + int ret = 1; + + for (id = ndims-1; id > 0; id--) { + odom[id] += add[id]; + if(odom[id] >= dims[id]) { + odom[id-1]++; + odom[id] -= dims[id]; + } + } + odom[0] += add[0]; + if (odom[0] >= dims[0]) + ret = 0; + return ret; +} + + +/* Output the data for a single variable, in CDL syntax. */ +int +vardata( + const struct ncvar *vp, /* variable */ + size_t vdims[], /* variable dimension sizes */ + int ncid, /* netcdf id */ + int varid, /* variable id */ + const struct fspec* fsp /* formatting specs */ + ) +{ + MPI_Offset cor[NC_MAX_DIMS]; /* corner coordinates */ + MPI_Offset edg[NC_MAX_DIMS]; /* edges of hypercube */ + size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ +#define VALBUFSIZ 1000 + double vals[VALBUFSIZ] ; /* aligned buffer */ + + int gulp = VALBUFSIZ; + + int id; + int ir; + size_t nels; + size_t ncols; + size_t nrows; + int vrank = vp->ndims; + static int initeps = 0; + + /* printf format used to print each value */ + const char *fmt = get_fmt(ncid, varid, vp->type); + + if (!initeps) { /* make sure epsilons get initialized */ + init_epsilons(); + initeps = 1; + } + + nels = 1; + for (id = 0; id < vrank; id++) { + cor[id] = 0; + edg[id] = 1; + nels *= vdims[id]; /* total number of values for variable */ + } + + if (vrank <= 1) { + Printf("\n %s = ", vp->name); + set_indent ((int)strlen(vp->name) + 4); + } else { + Printf("\n %s =\n ", vp->name); + set_indent (2); + } + + if (vrank < 1) { + ncols = 1; + } else { + ncols = vdims[vrank-1]; /* size of "row" along last dimension */ + edg[vrank-1] = vdims[vrank-1]; + for (id = 0; id < vrank; id++) + add[id] = 0; + if (vrank > 1) + add[vrank-2] = 1; + } + nrows = nels/ncols; /* number of "rows" */ + + for (ir = 0; ir < nrows; ir++) { + /* + * rather than just printing a whole row at once (which might exceed + * the capacity of MSDOS platforms, for example), we break each row + * into smaller chunks, if necessary. + */ + size_t corsav = 0; + int left = (int)ncols; + boolean lastrow; + + if (vrank > 0) { + corsav = cor[vrank-1]; + if (fsp->brief_data_cmnts != false + && vrank > 1 + && left > 0) { /* print brief comment with indices range */ + Printf("// %s(",vp->name); + switch (fsp->data_lang) { + case LANG_C: + /* print brief comment with C variable indices */ + for (id = 0; id < vrank-1; id++) + Printf("%lu,", (unsigned long)cor[id]); + if (vdims[vrank-1] == 1) + Printf("0"); + else + Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); + break; + case LANG_F: + /* print brief comment with Fortran variable indices */ + if (vdims[vrank-1] == 1) + Printf("1"); + else + Printf("1-%lu ", (unsigned long)vdims[vrank-1]); + for (id = vrank-2; id >=0 ; id--) { + Printf(",%lu", (unsigned long)(1 + cor[id])); + } + break; + } + Printf(")\n "); + set_indent(4); + } + } + lastrow = (boolean)(ir == nrows-1); + while (left > 0) { + size_t toget = left < gulp ? left : gulp; + if (vrank > 0) + edg[vrank-1] = toget; + switch(vp->type) { + case NC_CHAR: + NC_CHECK( + ncmpi_get_vara_text_all(ncid, varid, cor, edg, (char *)vals) ); + pr_tvals(vp, toget, fmt, left > toget, lastrow, + (char *) vals, fsp, cor); + break; + case NC_BYTE: + NC_CHECK( + ncmpi_get_vara_schar_all(ncid, varid, cor, edg, (signed char *)vals) ); + pr_bvals(vp, toget, fmt, left > toget, lastrow, + (signed char *) vals, fsp, cor); + break; + case NC_SHORT: + NC_CHECK( + ncmpi_get_vara_short_all(ncid, varid, cor, edg, (short *)vals) ); + pr_svals(vp, toget, fmt, left > toget, lastrow, + (short *) vals, fsp, cor); + break; + case NC_INT: + NC_CHECK( + ncmpi_get_vara_int_all(ncid, varid, cor, edg, (int *)vals) ); + pr_ivals(vp, toget, fmt, left > toget, lastrow, + (int *) vals, fsp, cor); + break; + case NC_FLOAT: + NC_CHECK( + ncmpi_get_vara_float_all(ncid, varid, cor, edg, (float *)vals) ); + pr_fvals(vp, toget, fmt, left > toget, lastrow, + (float *) vals, fsp, cor); + break; + case NC_DOUBLE: + NC_CHECK( + ncmpi_get_vara_double_all(ncid, varid, cor, edg, (double *)vals) ); + pr_dvals(vp, toget, fmt, left > toget, lastrow, + (double *) vals, fsp, cor); + break; + default: + error("vardata: bad type"); + } + left -= toget; + if (vrank > 0) + cor[vrank-1] += toget; + } + if (vrank > 0) + cor[vrank-1] = corsav; + if (ir < nrows-1) + if (!upcorner(vdims,vp->ndims,cor,add)) + error("vardata: odometer overflowed!"); + set_indent(2); + } + + return 0; +} Index: /tags/v1-0-3/src/utils/ncdump/ncdump.c =================================================================== --- /tags/v1-0-3/src/utils/ncdump/ncdump.c (revision 598) +++ /tags/v1-0-3/src/utils/ncdump/ncdump.c (revision 598) @@ -0,0 +1,732 @@ +/********************************************************************* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/README file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ncdump.h" +#include "dumplib.h" +#include "vardata.h" + +static void usage(void); +static char* name_path(const char* path); +static const char* type_name(ncmpi_type type); +static void tztrim(char* ss); +static void pr_att_string(size_t len, const char* string); +static void pr_att_vals(ncmpi_type type, size_t len, const double* vals); +static void pr_att(int ncid, int varid, const char *varname, int ia); +static void do_ncdump(const char* path, struct fspec* specp); +static void make_lvars(char* optarg, struct fspec* fspecp); +static void set_sigdigs( const char* optarg); +static void set_precision( const char *optarg); +int main(int argc, char** argv); + +#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) + +char *progname; + +static void +usage(void) +{ +#define USAGE "\ + [-c] Coordinate variable data and header information\n\ + [-h] Header information only, no data\n\ + [-v var1[,...]] Data for variable(s) ,... only\n\ + [-b [c|f]] Brief annotations for C or Fortran indices in data\n\ + [-f [c|f]] Full annotations for C or Fortran indices in data\n\ + [-l len] Line length maximum in data section (default 80)\n\ + [-n name] Name for netCDF (default derived from file name)\n\ + [-p n[,n]] Display floating-point values with less precision\n\ + file File name of input netCDF file\n" + + (void) fprintf(stderr, + "%s [-c|-h] [-v ...] [[-b|-f] [c|f]] [-l len] [-n name] [-p n[,n]] file\n%s", + progname, + USAGE); + + (void) fprintf(stderr, + "netcdf library version %s\n", + ncmpi_inq_libvers()); + exit(EXIT_FAILURE); +} + + +/* + * convert pathname of netcdf file into name for cdl unit, by taking + * last component of path and stripping off any extension. + */ +static char * +name_path(const char *path) +{ + const char *cp; + char *new; + char *sp; + +#ifdef vms +#define FILE_DELIMITER ']' +#endif +#ifdef MSDOS +#define FILE_DELIMITER '\\' +#endif +#ifndef FILE_DELIMITER /* default to unix */ +#define FILE_DELIMITER '/' +#endif + cp = strrchr(path, FILE_DELIMITER); + if (cp == 0) /* no delimiter */ + cp = path; + else /* skip delimeter */ + cp++; + new = (char *) malloc((unsigned) (strlen(cp)+1)); + if (new == 0) { + error("out of memory!"); + } + (void) strcpy(new, cp); /* copy last component of path */ + if ((sp = strrchr(new, '.')) != NULL) + *sp = '\0'; /* strip off any extension */ + return new; +} + + +static const char * +type_name(ncmpi_type type) +{ + switch (type) { + case NC_BYTE: + return "byte"; + case NC_CHAR: + return "char"; + case NC_SHORT: + return "short"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "float"; + case NC_DOUBLE: + return "double"; + default: + error("type_name: bad type %d", type); + return "bogus"; + } +} + + +/* + * Remove trailing zeros (after decimal point) but not trailing decimal + * point from ss, a string representation of a floating-point number that + * might include an exponent part. + */ +static void +tztrim(char *ss) +{ + char *cp, *ep; + + cp = ss; + if (*cp == '-') + cp++; + while(isdigit((int)*cp) || *cp == '.') + cp++; + if (*--cp == '.') + return; + ep = cp+1; + while (*cp == '0') + cp--; + cp++; + if (cp == ep) + return; + while (*ep) + *cp++ = *ep++; + *cp = '\0'; + return; +} + + +/* + * Print attribute string, for text attributes. + */ +static void +pr_att_string( + size_t len, + const char *string + ) +{ + int iel; + const char *cp; + const char *sp; + unsigned char uc; + + cp = string; + Printf ("\""); + /* adjust len so trailing nulls don't get printed */ + sp = cp + len - 1; + while (len != 0 && *sp-- == '\0') + len--; + for (iel = 0; iel < len; iel++) + switch (uc = *cp++ & 0377) { + case '\b': + Printf ("\\b"); + break; + case '\f': + Printf ("\\f"); + break; + case '\n': /* generate linebreaks after new-lines */ + Printf ("\\n\",\n \""); + break; + case '\r': + Printf ("\\r"); + break; + case '\t': + Printf ("\\t"); + break; + case '\v': + Printf ("\\v"); + break; + case '\\': + Printf ("\\\\"); + break; + case '\'': + Printf ("\\'"); + break; + case '\"': + Printf ("\\\""); + break; + default: + Printf ("%c",uc); + break; + } + Printf ("\""); + +} + + +/* + * Print list of attribute values, for numeric attributes. Attribute values + * must be printed with explicit type tags, because CDL doesn't have explicit + * syntax to declare an attribute type. + */ +static void +pr_att_vals( + ncmpi_type type, + size_t len, + const double *vals + ) +{ + int iel; + signed char sc; + short ss; + int ii; + char gps[30]; + float ff; + double dd; + + if (len == 0) + return; + for (iel = 0; iel < len-1; iel++) { + switch (type) { + case NC_BYTE: + sc = (signed char) vals[iel] & 0377; + Printf ("%db, ", sc); + break; + case NC_SHORT: + ss = vals[iel]; + Printf ("%ds, ", ss); + break; + case NC_INT: + ii = (int) vals[iel]; + Printf ("%d, ", ii); + break; + case NC_FLOAT: + ff = vals[iel]; + (void) sprintf(gps, float_att_fmt, ff); + tztrim(gps); /* trim trailing 0's after '.' */ + Printf ("%s, ", gps); + break; + case NC_DOUBLE: + dd = vals[iel]; + (void) sprintf(gps, double_att_fmt, dd); + tztrim(gps); + Printf ("%s, ", gps); + break; + default: + error("pr_att_vals: bad type"); + } + } + switch (type) { + case NC_BYTE: + sc = (signed char) vals[iel] & 0377; + Printf ("%db", sc); + break; + case NC_SHORT: + ss = vals[iel]; + Printf ("%ds", ss); + break; + case NC_INT: + ii = (int) vals[iel]; + Printf ("%d", ii); + break; + case NC_FLOAT: + ff = vals[iel]; + (void) sprintf(gps, float_att_fmt, ff); + tztrim(gps); + Printf ("%s", gps); + break; + case NC_DOUBLE: + dd = vals[iel]; + (void) sprintf(gps, double_att_fmt, dd); + tztrim(gps); + Printf ("%s", gps); + break; + default: + error("pr_att_vals: bad type"); + } +} + + +static void +pr_att( + int ncid, + int varid, + const char *varname, + int ia + ) +{ + struct ncatt att; /* attribute */ + + NC_CHECK( ncmpi_inq_attname(ncid, varid, ia, att.name) ); + + Printf ("\t\t%s:%s = ", varname, att.name); + + NC_CHECK( ncmpi_inq_att(ncid, varid, att.name, &att.type, &att.len) ); + + if (att.len == 0) { /* show 0-length attributes as empty strings */ + att.type = NC_CHAR; + att.len = 1; + } + switch (att.type) { + case NC_CHAR: + att.string = (char *) malloc(att.len); + if (!att.string) { + error("Out of memory!"); + NC_CHECK( ncmpi_close(ncid) ); + return; + } + NC_CHECK( ncmpi_get_att_text(ncid, varid, att.name, att.string ) ); + pr_att_string(att.len, att.string); + free(att.string); + break; + default: + att.vals = (double *) malloc(att.len * sizeof(double)); + if (!att.vals) { + error("Out of memory!"); + NC_CHECK( ncmpi_close(ncid) ); + return; + } + NC_CHECK( ncmpi_get_att_double(ncid, varid, att.name, att.vals ) ); + pr_att_vals(att.type, att.len, att.vals); + free(att.vals); + break; + } + Printf (" ;\n"); +} + + +static void +do_ncdump(const char *path, struct fspec* specp) +{ + int ndims; /* number of dimensions */ + int nvars; /* number of variables */ + int ngatts; /* number of global attributes */ + int xdimid; /* id of unlimited dimension */ + int dimid; /* dimension id */ + int varid; /* variable id */ + struct ncdim dims[NC_MAX_DIMS]; /* dimensions */ + size_t vdims[NC_MAX_DIMS]; /* dimension sizes for a single variable */ + struct ncvar var; /* variable */ + struct ncatt att; /* attribute */ + int id; /* dimension number per variable */ + int ia; /* attribute number */ + int iv; /* variable number */ + int is_coord; /* true if variable is a coordinate variable */ + int ncid; /* netCDF id */ + vnode* vlist = 0; /* list for vars specified with -v option */ + int ncmpi_status; /* return from netcdf calls */ + + ncmpi_status = ncmpi_open(MPI_COMM_WORLD, path, NC_NOWRITE, MPI_INFO_NULL, &ncid); + if (ncmpi_status != NC_NOERR) { + error("%s: %s", path, ncmpi_strerror(ncmpi_status)); + } + /* + * If any vars were specified with -v option, get list of associated + * variable ids + */ + if (specp->nlvars > 0) { + vlist = newvlist(); /* list for vars specified with -v option */ + for (iv=0; iv < specp->nlvars; iv++) { + NC_CHECK( ncmpi_inq_varid(ncid, specp->lvars[iv], &varid) ); + varadd(vlist, varid); + } + } + + /* if name not specified, derive it from path */ + if (specp->name == (char *)0) { + specp->name = name_path (path); + } + + Printf ("netcdf %s {\n", specp->name); + /* + * get number of dimensions, number of variables, number of global + * atts, and dimension id of unlimited dimension, if any + */ + NC_CHECK( ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &xdimid) ); + /* get dimension info */ + if (ndims > 0) + Printf ("dimensions:\n"); + for (dimid = 0; dimid < ndims; dimid++) { + NC_CHECK( ncmpi_inq_dim(ncid, dimid, dims[dimid].name, &dims[dimid].size) ); + if (dimid == xdimid) + Printf ("\t%s = %s ; // (%Ld currently)\n",dims[dimid].name, + "UNLIMITED", dims[dimid].size); + else + Printf ("\t%s = %Ld ;\n", dims[dimid].name, dims[dimid].size); + } + + if (nvars > 0) + Printf ("variables:\n"); + /* get variable info, with variable attributes */ + for (varid = 0; varid < nvars; varid++) { + NC_CHECK( ncmpi_inq_var(ncid, varid, var.name, &var.type, &var.ndims, + var.dims, &var.natts) ); + Printf ("\t%s %s", type_name(var.type), var.name); + if (var.ndims > 0) + Printf ("("); + for (id = 0; id < var.ndims; id++) { + Printf ("%s%s", + dims[var.dims[id]].name, + id < var.ndims-1 ? ", " : ")"); + } + Printf (" ;\n"); + + /* get variable attributes */ + for (ia = 0; ia < var.natts; ia++) + pr_att(ncid, varid, var.name, ia); /* print ia-th attribute */ + } + + + /* get global attributes */ + if (ngatts > 0) + Printf ("\n// global attributes:\n"); + for (ia = 0; ia < ngatts; ia++) + pr_att(ncid, NC_GLOBAL, "", ia); /* print ia-th global attribute */ + + if (! specp->header_only) { + if (nvars > 0) { + Printf ("data:\n"); + } + /* output variable data */ + for (varid = 0; varid < nvars; varid++) { + /* if var list specified, test for membership */ + if (specp->nlvars > 0 && ! varmember(vlist, varid)) + continue; + NC_CHECK( ncmpi_inq_var(ncid, varid, var.name, &var.type, &var.ndims, + var.dims, &var.natts) ); + if (specp->coord_vals) { + /* Find out if this is a coordinate variable */ + is_coord = 0; + for (dimid = 0; dimid < ndims; dimid++) { + if (strcmp(dims[dimid].name, var.name) == 0 && + var.ndims == 1) { + is_coord = 1; + break; + } + } + if (! is_coord) /* don't get data for non-coordinate vars */ + continue; + } + /* + * Only get data for variable if it is not a record variable, + * or if it is a record variable and at least one record has + * been written. + */ + if (var.ndims == 0 + || var.dims[0] != xdimid + || dims[xdimid].size != 0) { + + /* Collect variable's dim sizes */ + for (id = 0; id < var.ndims; id++) + vdims[id] = dims[var.dims[id]].size; + var.has_fillval = 1; /* by default, but turn off for bytes */ + + /* get _FillValue attribute */ + ncmpi_status = ncmpi_inq_att(ncid,varid,_FillValue,&att.type,&att.len); + if(ncmpi_status == NC_NOERR && + att.type == var.type && att.len == 1) { + if(var.type == NC_CHAR) { + char fillc; + NC_CHECK( ncmpi_get_att_text(ncid, varid, _FillValue, + &fillc ) ); + var.fillval = fillc; + } else { + NC_CHECK( ncmpi_get_att_double(ncid, varid, _FillValue, + &var.fillval) ); + } + } else { + switch (var.type) { + case NC_BYTE: + /* don't do default fill-values for bytes, too risky */ + var.has_fillval = 0; + break; + case NC_CHAR: + var.fillval = NC_FILL_CHAR; + break; + case NC_SHORT: + var.fillval = NC_FILL_SHORT; + break; + case NC_INT: + var.fillval = NC_FILL_INT; + break; + case NC_FLOAT: + var.fillval = NC_FILL_FLOAT; + break; + case NC_DOUBLE: + var.fillval = NC_FILL_DOUBLE; + break; + default: + break; + } + } + if (vardata(&var, vdims, ncid, varid, specp) == -1) { + error("can't output data for variable %s", var.name); + NC_CHECK( + ncmpi_close(ncid) ); + if (vlist) + free(vlist); + return; + } + } + } + } + + Printf ("}\n"); + NC_CHECK( + ncmpi_close(ncid) ); + if (vlist) + free(vlist); +} + + +static void +make_lvars(char *optarg, struct fspec* fspecp) +{ + char *cp = optarg; + int nvars = 1; + char ** cpp; + + /* compute number of variable names in comma-delimited list */ + fspecp->nlvars = 1; + while (*cp++) + if (*cp == ',') + nvars++; + + fspecp->lvars = (char **) malloc(nvars * sizeof(char*)); + if (!fspecp->lvars) { + error("out of memory"); + } + + cpp = fspecp->lvars; + /* copy variable names into list */ + for (cp = strtok(optarg, ","); + cp != NULL; + cp = strtok((char *) NULL, ",")) { + + *cpp = (char *) malloc(strlen(cp) + 1); + if (!*cpp) { + error("out of memory"); + } + strcpy(*cpp, cp); + cpp++; + } + fspecp->nlvars = nvars; +} + + +/* + * Extract the significant-digits specifiers from the -d argument on the + * command-line and update the default data formats appropriately. + */ +static void +set_sigdigs(const char *optarg) +{ + char *ptr1 = 0; + char *ptr2 = 0; + int flt_digits = FLT_DIGITS; /* default floating-point digits */ + int dbl_digits = DBL_DIGITS; /* default double-precision digits */ + + if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') + flt_digits = (int)strtol(optarg, &ptr1, 10); + + if (flt_digits < 1 || flt_digits > 20) { + error("unreasonable value for float significant digits: %d", + flt_digits); + } + if (*ptr1 == ',') + dbl_digits = (int)strtol(ptr1+1, &ptr2, 10); + if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) { + error("unreasonable value for double significant digits: %d", + dbl_digits); + } + set_formats(flt_digits, dbl_digits); +} + + +/* + * Extract the significant-digits specifiers from the -p argument on the + * command-line, set flags so we can override C_format attributes (if any), + * and update the default data formats appropriately. + */ +static void +set_precision(const char *optarg) +{ + char *ptr1 = 0; + char *ptr2 = 0; + int flt_digits = FLT_DIGITS; /* default floating-point digits */ + int dbl_digits = DBL_DIGITS; /* default double-precision digits */ + + if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') { + flt_digits = (int)strtol(optarg, &ptr1, 10); + float_precision_specified = 1; + } + + if (flt_digits < 1 || flt_digits > 20) { + error("unreasonable value for float significant digits: %d", + flt_digits); + } + if (*ptr1 == ',') { + dbl_digits = (int) strtol(ptr1+1, &ptr2, 10); + double_precision_specified = 1; + } + if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) { + error("unreasonable value for double significant digits: %d", + dbl_digits); + } + set_formats(flt_digits, dbl_digits); +} + + +int +main(int argc, char *argv[]) +{ + extern int optind; + extern int opterr; + extern char *optarg; + static struct fspec fspec = /* defaults, overridden on command line */ + { + 0, /* construct netcdf name from file name */ + false, /* print header info only, no data? */ + false, /* just print coord vars? */ + false, /* brief comments in data section? */ + false, /* full annotations in data section? */ + LANG_C, /* language conventions for indices */ + 0, /* if -v specified, number of variables */ + 0 /* if -v specified, list of variable names */ + }; + int c; + int i; + int max_len = 80; /* default maximum line length */ + int nameopt = 0; + + MPI_Init(&argc, &argv); + + opterr = 1; + progname = argv[0]; + set_formats(FLT_DIGITS, DBL_DIGITS); /* default for float, double data */ + + while ((c = getopt(argc, argv, "b:cf:hl:n:v:d:p:")) != EOF) + switch(c) { + case 'h': /* dump header only, no data */ + fspec.header_only = true; + break; + case 'c': /* header, data only for coordinate dims */ + fspec.coord_vals = true; + break; + case 'n': /* + * provide different name than derived from + * file name + */ + fspec.name = optarg; + nameopt = 1; + break; + case 'b': /* brief comments in data section */ + fspec.brief_data_cmnts = true; + switch (tolower(optarg[0])) { + case 'c': + fspec.data_lang = LANG_C; + break; + case 'f': + fspec.data_lang = LANG_F; + break; + default: + error("invalid value for -b option: %s", optarg); + } + break; + case 'f': /* full comments in data section */ + fspec.full_data_cmnts = true; + switch (tolower(optarg[0])) { + case 'c': + fspec.data_lang = LANG_C; + break; + case 'f': + fspec.data_lang = LANG_F; + break; + default: + error("invalid value for -f option: %s", optarg); + } + break; + case 'l': /* maximum line length */ + max_len = (int) strtol(optarg, 0, 0); + if (max_len < 10) { + error("unreasonably small line length specified: %d", max_len); + } + break; + case 'v': /* variable names */ + /* make list of names of variables specified */ + make_lvars (optarg, &fspec); + break; + case 'd': /* specify precision for floats (old option) */ + set_sigdigs(optarg); + break; + case 'p': /* specify precision for floats */ + set_precision(optarg); + break; + case '?': + usage(); + break; + } + + set_max_len(max_len); + + argc -= optind; + argv += optind; + + i = 0; + + do { + if (!nameopt) fspec.name = (char *)0; + if (argc > 0) + do_ncdump(argv[i], &fspec); + } while (++i < argc); + + MPI_Finalize(); +#ifdef vms + exit(EXIT_SUCCESS); +#else + return EXIT_SUCCESS; +#endif +} Index: /tags/v1-0-3/src/utils/ncdump/vardata.h =================================================================== --- /tags/v1-0-3/src/utils/ncdump/vardata.h (revision 314) +++ /tags/v1-0-3/src/utils/ncdump/vardata.h (revision 314) @@ -0,0 +1,27 @@ +/********************************************************************* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +extern char *progname; /* for error messages */ + +/* Display for user-defined fill values and default floating-point fill + values; should match what ncgen looks for in ../ncgen/ncgen.l */ +#define FILL_STRING "_" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Output the data for a single variable, in CDL syntax. */ +extern int vardata ( const struct ncvar*, /* variable */ + size_t [], /* variable dimension lengths */ + int, /* netcdf id */ + int, /* variable id */ + const struct fspec* /* formatting specs */ + ); + +#ifdef __cplusplus +} +#endif Index: /tags/v1-0-3/src/utils/ncdump/ncmpidump.1 =================================================================== --- /tags/v1-0-3/src/utils/ncdump/ncmpidump.1 (revision 319) +++ /tags/v1-0-3/src/utils/ncdump/ncmpidump.1 (revision 319) @@ -0,0 +1,178 @@ +.\" $Header$ +.TH NCDUMP 1 "$Date$" "Printed: \n(yr-\n(mo-\n(dy" "UNIDATA UTILITIES" +.SH NAME +ncdump \- Convert netCDF files to ASCII form (CDL) +.SH SYNOPSIS +.ft B +.HP +ncdump +.nh +\%[-c] +\%[-h] +\%[-v \fIvar1,...\fP] +\%[-b \fIlang\fP] +\%[-f \fIlang\fP] +\%[-l \fIlen\fP] +\%[-n \fIname\fP] +\%[-p \fIf_digits[,d_digits]\fP] +\%\fIfile\fP +.hy +.ft +.SH DESCRIPTION +\fBncdump\fP generates an ASCII representation of a specified netCDF file on +standard output. The ASCII representation is in a form called CDL +(``network Common Data form Language'') that can be viewed, edited, or serve +as input to \fBncgen\fP. \fBncgen\fP is a companion program that can +generate a binary netCDF file from a CDL file. Hence \fBncgen\fP and +\fBncdump\fP can be used as inverses to transform the data representation +between binary and ASCII representations. See \fBncgen\fP for a description +of CDL and netCDF representations. +.LP +\fBncdump\fP defines a default format used for each type of netCDF data, but +this can be changed if a `C_format' attribute is defined for a netCDF +variable. In this case, \fBncdump\fP will use the `C_format' attribute to +format each value. For example, if floating-point data for the netCDF +variable `Z' is known to be accurate to only three significant digits, it +would be appropriate to use the variable attribute +.RS +.HP +Z:C_format = "%.3g" +.RE +.LP +\fBncdump\fP may also be used as a simple browser for netCDF data +files, to display the dimension names and sizes; variable names, types, +and shapes; attribute names and values; and optionally, the values of +data for all variables or selected variables in a netCDF file. +.LP +\fBncdump\fP uses `_' to represent data values that are equal to the +`_FillValue' attribute for a variable, intended to represent data that +has not yet been written. If a variable has no `_FillValue' attribute, the +default fill value for the variable type is used if the variable is not of +byte type. +.SH OPTIONS +.IP "\fB-c\fP" +Show the values of \fIcoordinate\fP variables (variables that are also +dimensions) as well as the declarations of all dimensions, variables, and +attribute values. Data values of non-coordinate variables are not included +in the output. This is the most suitable option to use for a brief look at +the structure and contents of a netCDF file. +.IP "\fB-h\fP" +Show only the \fIheader\fP information in the output, that is the +declarations of dimensions, variables, and attributes but no data values for +any variables. The output is identical to using the \fB-c\fP option except +that the values of coordinate variables are not included. (At most one of +\fB-c\fP or \fB-h\fP options may be present.) +.IP "\fB-v\fP \fIvar1,...,varn\fP" +The output will include data values for the specified variables, in addition +to the declarations of all dimensions, variables, and attributes. One or +more variables must be specified by name in the comma-delimited list +following this option. The list must be a single argument to the command, +hence cannot contain blanks or other white space characters. The named +variables must be valid netCDF variables in the input-file. The default, +without this option and in the absence of the \fB-c\fP or \fB-h\fP +options, is to include data values for \fIall\fP variables in the output. +.IP "\fB-b\fP \fIlang\fP" +A brief annotation in the form of a CDL comment (text beginning with the +characters ``//'') will be included in the data section of the output for +each `row' of data, to help identify data values for multidimensional +variables. If \fIlang\fP begins with `C' or `c', then C language +conventions will be used (zero-based indices, last dimension varying +fastest). If \fIlang\fP begins with `F' or `f', then Fortran language +conventions will be used (one-based indices, first dimension varying +fastest). In either case, the data will be presented in the same order; +only the annotations will differ. This option is useful for browsing +through large volumes of multidimensional data. +.IP "\fB-f\fP \fIlang\fP" +Full annotations in the form of trailing CDL comments (text beginning with +the characters ``//'') for every data value (except individual characters in +character arrays) will be included in the data section. If \fIlang\fP +begins with `C' or `c', then C language conventions will be used (zero-based +indices, last dimension varying fastest). If \fIlang\fP begins with `F' or +`f', then Fortran language conventions will be used (one-based indices, +first dimension varying fastest). In either case, the data will be +presented in the same order; only the annotations will differ. This option +may be useful for piping data into other filters, since each data value +appears on a separate line, fully identified. +.IP "\fB-l\fP \fIlen\fP" +Changes the default maximum line length (80) used in formatting lists of +non-character data values. +.IP "\fB-n\fP \fIname\fP" +CDL requires a name for a netCDF data set, for use by \fBncgen -b\fP in +generating a default netCDF file name. By default, \fIncdump\fP constructs +this name from the last component of the pathname of the input netCDF file +by stripping off any extension it has. Use the \fB-n\fP option to specify a +different name. Although the output file name used by \fBncgen -b\fP can be +specified, it may be wise to have \fIncdump\fP change the default name to +avoid inadvertantly overwriting a valuable netCDF file when using +\fBncdump\fP, editing the resulting CDL file, and using \fBncgen -b\fP to +generate a new netCDF file from the edited CDL file. +.IP "\fB-p\fP \fIfloat_digits[,double_digits]\fP" +Specifies default precision (number of significant digits) to use in displaying +floating-point or double precision data values for attributes and variables. +If specified, this value overrides the value of the `C_format' attribute for +any variable that has such an attribute. +Floating-point data will be displayed with +\fIfloat_digits\fP significant digits. If \fIdouble_digits\fP is also +specified, double-precision values will be displayed with that many +significant digits. In the absence of any +\fB-p\fP specifications, floating-point and double-precision data are +displayed with 7 and 15 significant digits respectively. CDL files can be +made smaller if less precision is required. If both floating-point and +double-presision precisions are specified, the two values must appear +separated by a comma (no blanks) as a single argument to the command. +If you really want every last bit of precision from the netCDF file +represented in the CDL file for all possible floating-point values, you will +have to specify this with \fB-p 9,17\fP (according to Theorem 15 of the +paper listed under REFERENCES). + +.SH EXAMPLES +.LP +Look at the structure of the data in the netCDF file `\fBfoo.nc\fP': +.RS +.HP +ncdump -c foo.nc +.RE +.LP +Produce an annotated CDL version of the structure and data in the +netCDF file `\fBfoo.nc\fP', using C-style indexing for the annotations: +.RS +.HP +ncdump -b c foo.nc > foo.cdl +.RE +.LP +Output data for only the variables `uwind' and `vwind' from the netCDF file +`\fBfoo.nc\fP', and show the floating-point data with only three significant +digits of precision: +.RS +.HP +ncdump -v uwind,vwind -p 3 foo.nc +.RE +.LP +Produce a fully-annotated (one data value per line) listing of the data for +the variable `omega', using Fortran conventions for indices, and changing the +netCDF dataset name in the resulting CDL file to `omega': +.RS +.HP +ncdump -v omega -f fortran -n omega foo.nc > Z.cdl +.RE +.SH REFERENCES + \fIWhat +Every Computer Scientist should Know About Floating-Point Arithmetic\fP, D. +Goldberg, \fBACM Computing Surveys, Vol. 23, No. 1\fP, March 1991, pp. 5-48. + +.SH "SEE ALSO" +.LP +.BR ncgen (1), +.BR netcdf (3) +.SH BUGS +.LP +Character arrays that contain a null-byte are treated like C strings, so no +characters after the null byte appear in the output. + +Multidimensional character string arrays are not handled well, since the CDL +syntax for breaking a long character string into several shorter lines is +weak. + +There should be a way to specify that the data should be displayed in +`record' order, that is with the all the values for `record' variables +together that have the same value of the record dimension. Index: /tags/v1-0-3/src/utils/ncdump/ncdump.h =================================================================== --- /tags/v1-0-3/src/utils/ncdump/ncdump.h (revision 560) +++ /tags/v1-0-3/src/utils/ncdump/ncdump.h (revision 560) @@ -0,0 +1,79 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + + +/* error checking macro */ +#define NC_CHECK(status) {\ + int nc_status = status;\ + if(nc_status != NC_NOERR)\ + error(ncmpi_strerror(nc_status));\ + } + +#define Printf (void) printf + +typedef int boolean; +enum {false=0, true=1}; + +struct ncdim { /* dimension */ + char name[NC_MAX_NAME]; + MPI_Offset size; +}; + +struct ncvar { /* variable */ + char name[NC_MAX_NAME]; + nc_type type; + int ndims; + int dims[NC_MAX_VAR_DIMS]; + int natts; + boolean has_fillval; + double fillval; +}; + +struct ncatt { /* attribute */ + int var; + char name[NC_MAX_NAME]; + nc_type type; + MPI_Offset len; + char *string; /* for text attributes (type = NC_CHAR) */ + double *vals; /* for numeric attributes of all types */ +}; + +typedef +enum {LANG_C, LANG_F} Nclang; + +struct fspec { /* specification for how to format dump */ + + char *name; /* name specified with -n or derived from + * file name */ + + boolean header_only; /* if true, don't print any variable data */ + + boolean coord_vals; /* if true, print header and coordinate + * dimension values (values of variables + * that are also dimensions), but no other + * variable data */ + + boolean brief_data_cmnts; /* if true, put // comments in data section + * identifying variable and indices, useful + * for navigating through large + * multi-dimensional data lists. */ + + boolean full_data_cmnts; /* if true, put // comments in data section + * identifying every value, useful for + * navigating through large + * multi-dimensional data lists. */ + + Nclang data_lang; /* Specifies index conventions used in data + * comments, either LANG_C (C, 0-based, + * column major) or LANG_F (Fortran, + * 1-based, row major) */ + + int nlvars; /* Number of variables specified with -v + * option on command line */ + + char** lvars; /* list of variable names specified with -v + * option on command line */ +}; Index: /tags/v1-0-3/src/utils/ncdump/dumplib.c =================================================================== --- /tags/v1-0-3/src/utils/ncdump/dumplib.c (revision 600) +++ /tags/v1-0-3/src/utils/ncdump/dumplib.c (revision 600) @@ -0,0 +1,225 @@ +/********************************************************************* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/README file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +/* + * We potentially include before in order to obtain a + * definition for va_list from the GNU C compiler. + */ +#include +#include +#include +#include + +#include "pnetcdf.h" +#include "dumplib.h" + +#define ncmpi_advise(x, y, z) + +static char* has_c_format_att(int ncid, int varid); +static vnode* newvnode(void); + +int float_precision_specified = 0; /* -p option specified float precision */ +int double_precision_specified = 0; /* -p option specified double precision */ +char float_var_fmt[] = "%.NNg"; +char double_var_fmt[] = "%.NNg"; +char float_att_fmt[] = "%#.NNgf"; +char double_att_fmt[] = "%#.NNg"; + +/* + * Print error message to stderr and exit + */ +void +error(const char *fmt, ...) +{ + va_list args ; + + (void) fprintf(stderr,"%s: ", progname); + va_start(args, fmt) ; + (void) vfprintf(stderr,fmt,args) ; + va_end(args) ; + + (void) fprintf(stderr, "\n") ; + (void) fflush(stderr); /* to ensure log files are current */ + exit(EXIT_FAILURE); +} + +#define LINEPIND " " /* indent of continued lines */ + +static int linep; +static int max_line_len; + +void +set_indent(int in) +{ + linep = in; +} + + +void +set_max_len(int len) +{ + max_line_len = len-2; +} + + +void +lput(const char *cp) +{ + size_t nn = strlen(cp); + + if (nn+linep > max_line_len && nn > 2) { + (void) fputs("\n", stdout); + (void) fputs(LINEPIND, stdout); + linep = (int)strlen(LINEPIND); + } + (void) fputs(cp,stdout); + linep += nn; +} + +/* In case different formats specified with -d option, set them here. */ +void +set_formats(int float_digits, int double_digits) +{ + (void) sprintf(float_var_fmt, "%%.%dg", float_digits); + (void) sprintf(double_var_fmt, "%%.%dg", double_digits); + (void) sprintf(float_att_fmt, "%%#.%dgf", float_digits); + (void) sprintf(double_att_fmt, "%%#.%dg", double_digits); +} + + +static char * +has_c_format_att( + int ncid, /* netcdf id */ + int varid /* variable id */ + ) +{ + ncmpi_type cfmt_type; + MPI_Offset cfmt_len; +#define C_FMT_NAME "C_format" /* name of C format attribute */ +#define MAX_CFMT_LEN 100 /* max length of C format attribute */ + static char cfmt[MAX_CFMT_LEN]; + + /* we expect ncmpi_inq_att to fail if there is no "C_format" attribute */ + int ncmpi_stat = ncmpi_inq_att(ncid, varid, "C_format", &cfmt_type, &cfmt_len); + + switch(ncmpi_stat) { + case NC_NOERR: + if (cfmt_type == NC_CHAR && cfmt_len != 0 && cfmt_len < MAX_CFMT_LEN) { + ncmpi_stat = ncmpi_get_att_text(ncid, varid, "C_format", cfmt); + if(ncmpi_stat != NC_NOERR) + ncmpi_advise("Getting 'C_format' attribute", ncmpi_stat, ""); + return &cfmt[0]; + } + break; + case NC_ENOTATT: + break; + default: + ncmpi_advise("Inquiring about 'C_format' attribute", ncmpi_stat, ""); + break; + } + return 0; +} + + +/* + * Determine print format to use for each value for this variable. Use value + * of attribute C_format if it exists, otherwise a sensible default. + */ +const char * +get_fmt( + int ncid, /* netcdf id */ + int varid, /* variable id */ + ncmpi_type type /* netCDF data type */ + ) +{ + char *c_format_att; + + /* float or double precision specified with -p option overrides any + C_format attribute value, so check for that first. */ + + if (float_precision_specified && type == NC_FLOAT) + return float_var_fmt; + + if (double_precision_specified && type == NC_DOUBLE) + return double_var_fmt; + + /* If C_format attribute exists, return it */ + c_format_att = has_c_format_att(ncid, varid); + if (c_format_att) + return c_format_att; + + /* Otherwise return sensible default. */ + switch (type) { + case NC_BYTE: + return "%d"; + case NC_CHAR: + return "%s"; + case NC_SHORT: + return "%d"; + case NC_INT: + return "%d"; + case NC_FLOAT: + return float_var_fmt; + case NC_DOUBLE: + return double_var_fmt; + default: + error("pr_vals: bad type"); + } + + return 0; +} + + +static vnode* +newvnode(void) +{ + vnode *newvp = (vnode*) malloc(sizeof(vnode)); + + if (!newvp) { + error("out of memory!"); + } + return newvp; +} + + +/* + * Get a new, empty variable list. + */ +vnode* +newvlist(void) +{ + vnode *vp = newvnode(); + + vp -> next = 0; + vp -> id = -1; /* bad id */ + + return vp; +} + + +void +varadd(vnode* vlist, int varid) +{ + vnode *newvp = newvnode(); + + newvp -> next = vlist -> next; + newvp -> id = varid; + vlist -> next = newvp; +} + + +int +varmember(const vnode* vlist, int varid) +{ + vnode *vp = vlist -> next; + + for (; vp ; vp = vp->next) + if (vp->id == varid) + return 1; + return 0; +} + + Index: /tags/v1-0-3/src/utils/ncgen/depend =================================================================== --- /tags/v1-0-3/src/utils/ncgen/depend (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/depend (revision 313) @@ -0,0 +1,48 @@ +close.o: $(srcdir)/../../lib/pnetcdf.h +close.o: close.c +close.o: generic.h +close.o: genlib.h +close.o: ncgen.h +escapes.o: $(srcdir)/../../lib/pnetcdf.h +escapes.o: escapes.c +escapes.o: generic.h +escapes.o: genlib.h +escapes.o: ncgen.h +genlib.o: $(srcdir)/../../lib/pnetcdf.h +genlib.o: generic.h +genlib.o: genlib.c +genlib.o: genlib.h +genlib.o: ncgen.h +getfill.o: $(srcdir)/../../lib/pnetcdf.h +getfill.o: generic.h +getfill.o: genlib.h +getfill.o: getfill.c +getfill.o: ncgen.h +init.o: $(srcdir)/../../lib/pnetcdf.h +init.o: generic.h +init.o: init.c +init.o: ncgen.h +load.o: $(srcdir)/../../lib/pnetcdf.h +load.o: generic.h +load.o: genlib.h +load.o: load.c +load.o: ncgen.h +main.o: $(srcdir)/../../lib/pnetcdf.h +main.o: generic.h +main.o: genlib.h +main.o: main.c +main.o: ncgen.h +msofttab.o: $(srcdir)/../../lib/pnetcdf.h +msofttab.o: generic.h +msofttab.o: msofttab.c +msofttab.o: ncgen.h +msofttab.o: ncgenyy.c +msoftyy.o: msoftyy.c +ncgenyy.o: ncgenyy.c +vms_yy.o: vms_yy.c +vmstab.o: $(srcdir)/../../lib/pnetcdf.h +vmstab.o: generic.h +vmstab.o: genlib.h +vmstab.o: ncgen.h +vmstab.o: ncgenyy.c +vmstab.o: vmstab.c Index: /tags/v1-0-3/src/utils/ncgen/ncmpigen.1 =================================================================== --- /tags/v1-0-3/src/utils/ncgen/ncmpigen.1 (revision 320) +++ /tags/v1-0-3/src/utils/ncgen/ncmpigen.1 (revision 320) @@ -0,0 +1,361 @@ +.\" $Header$ +.TH NCGEN 1 "$Date$" "Printed: \n(yr-\n(mo-\n(dy" "UNIDATA UTILITIES" +.SH NAME +ncgen \- From a CDL file generate a netCDF file, a C program, or a Fortran +program +.SH SYNOPSIS +.HP +ncgen +.nh +\%[-b] +\%[-c] +\%[-f] +\%[-n] +\%[-o \fInetcdf_filename\fP] +\%\fIinput_file\fP +.hy +.ft +.SH DESCRIPTION +\fBncgen\fP generates either a netCDF file, or C or Fortran source code to +create a netCDF file. The input to \fBncgen\fP is a description of a netCDF +file in a small language known as CDL (network Common Data form Language), +described below. +If no options are specified in invoking \fBncgen\fP, it merely checks the +syntax of the input CDL file, producing error messages for +any violations of CDL syntax. Other options can be used to create the +corresponding netCDF file, to generate a C program that uses the netCDF C +interface to create the netCDF file, or to generate a Fortran program that +uses the netCDF Fortran interface to create the same netCDF file. +.LP +\fBncgen\fP may be used with the companion program \fBncdump\fP to perform +some simple operations on netCDF files. For example, to rename a dimension +in a netCDF file, use \fBncdump\fP to get a CDL version of the netCDF file, +edit the CDL file to change the name of the dimensions, and use \fBncgen\fP +to generate the corresponding netCDF file from the edited CDL file. +.SH OPTIONS +.IP "\fB-b\fP" +Create a (binary) netCDF file. If the \fB-o\fP option is absent, a default +file name will be constructed from the netCDF name (specified after the +\fBnetcdf\fP keyword in the input) by appending the `.nc' extension. If a +file already exists with the specified name, it will be overwritten. +.IP "\fB-c\fP" +Generate +.B C +source code that will create a netCDF file +matching the netCDF specification. The C source code is written to +standard output. +.IP "\fB-f\fP" +Generate +.B Fortran +source code that will create a netCDF file +matching the netCDF specification. The Fortran source code is written +to standard output. +.IP "\fB-o\fP \fRnetcdf_file\fP" +Name for the binary netCDF file created. If this option is specified, it implies +the "\fB-b\fP" option. (This option is necessary because netCDF files +cannot be written directly to standard output, since standard output is not +seekable.) +.IP "\fB-n\fP" +Like \fB-b\fP option, except creates netCDF file with the obsolete `.cdf' +extension instead of the `.nc' extension, in the absence of an output +filename specified by the \fB-o\fP option. This option is only supported +for backward compatibility. +.SH EXAMPLES +.LP +Check the syntax of the CDL file `\fBfoo.cdl\fP': +.RS +.HP +ncgen foo.cdl +.RE +.LP +From the CDL file `\fBfoo.cdl\fP', generate an equivalent binary netCDF file +named `\fBx.nc\fP': +.RS +.HP +ncgen -o x.nc foo.cdl +.RE +.LP +From the CDL file `\fBfoo.cdl\fP', generate a C program containing the +netCDF function invocations necessary to create an equivalent binary netCDF +file named `\fBx.nc\fP': +.RS +.HP +ncgen -c -o x.nc foo.cdl +.RE +.LP +.SH USAGE +.SS "CDL Syntax Summary" +.LP +Below is an example of CDL syntax, describing a netCDF file with several +named dimensions (lat, lon, and time), variables (Z, t, p, rh, lat, lon, +time), variable attributes (units, long_name, valid_range, _FillValue), and +some data. CDL keywords are in boldface. (This example is intended to +illustrate the syntax; a real CDL file would have a more complete set of +attributes so that the data would be more completely self-describing.) + +.RS +.nf +\fBnetcdf\fP foo { // an example netCDF specification in CDL + +\fBdimensions\fP: + lat = 10, lon = 5, time = \fBunlimited\fP ; + +\fBvariables\fP: + \fBlong\fP lat(lat), lon(lon), time(time); + \fBfloat\fP Z(time,lat,lon), t(time,lat,lon); + \fBdouble\fP p(time,lat,lon); + \fBlong\fP rh(time,lat,lon); + + // variable attributes + lat:long_name = "latitude"; + lat:units = "degrees_north"; + lon:long_name = "longitude"; + lon:units = "degrees_east"; + time:units = "seconds since 1992-1-1 00:00:00"; + Z:units = "geopotential meters"; + Z:valid_range = 0., 5000.; + p:_FillValue = -9999.; + rh:_FillValue = -1; + +\fBdata\fP: + lat = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90; + lon = -140, -118, -96, -84, -52; +} +.fi +.RE +.LP +All CDL statements are terminated by a semicolon. Spaces, tabs, +and newlines can be used freely for readability. +Comments may follow the characters `//' on any line. +.LP +A CDL description consists of three optional parts: \fIdimensions\fP, +\fIvariables\fP, and \fIdata\fP, beginning with the keyword +.BR dimensions: , +.BR variables: , +and +.BR data , +respectively. +The variable part may contain \fIvariable +declarations\fP and \fIattribute assignments\fP. +.LP +A netCDF \fIdimension\fP is used to define the shape of one or more of the +multidimensional variables contained in the netCDF file. A netCDF +dimension has a name and a size. At most one dimension in a netCDF file +can have the \fBunlimited\fP size, which means a variable using this +dimension can grow to any length (like a record number in a file). +.LP +A \fIvariable\fP represents a multidimensional array of values of the +same type. A variable has a name, a data type, and a shape described +by its list of dimensions. Each variable may also have associated +\fIattributes\fP (see below) as well as data values. The name, data +type, and shape of a variable are specified by its declaration in the +\fIvariable\fP section of a CDL description. A variable may have the same +name as a dimension; by convention such a variable is one-dimensional +and contains coordinates of the dimension it names. Dimensions need +not have corresponding variables. +.LP +A netCDF \fIattribute\fP contains information about a netCDF variable or +about the whole netCDF dataset. Attributes are used +to specify such properties as units, special values, maximum and +minimum valid values, scaling factors, offsets, and parameters. Attribute +information is represented by single values or arrays of values. For +example, "units" is an attribute represented by a character array such +as "celsius". An attribute has an associated variable, a name, +a data type, a length, and a value. In contrast to variables that are +intended for data, attributes are intended for metadata (data about +data). +.LP +In CDL, an attribute is designated by a variable and attribute name, +separated by `:'. It is possible to assign \fIglobal\fP attributes +not associated with any variable to the netCDF as a whole by using +`:' before the attribute name. The data type of an attribute in CDL +is derived from the type of the value assigned to it. The length of +an attribute is the number of data values assigned to it, or the +number of characters in the character string assigned to it. Multiple +values are assigned to non-character attributes by separating the +values with commas. All values assigned to an attribute must be of +the same type. +.LP +The names for CDL dimensions, variables, and attributes must begin with an +alphabetic character or `_', and subsequent characters may be alphanumeric +or `_' or `-'. +.LP +The optional \fIdata\fP section of a CDL specification is where +netCDF variables may be initialized. The syntax of an initialization +is simple: a variable name, an equals sign, and a +comma-delimited list of constants (possibly separated by spaces, tabs +and newlines) terminated with a semicolon. For multi-dimensional +arrays, the last dimension varies fastest. Thus row-order rather than +column order is used for matrices. If fewer values are supplied than +are needed to fill a variable, it is extended with a type-dependent +`fill value', which can be overridden by supplying a value for a +distinguished variable attribute named `_FillValue'. The +types of constants need not match the type declared for a variable; +coercions are done to convert integers to floating point, for example. +The constant `_' can be used to designate the fill value for a variable. +.SS "Primitive Data Types" +.LP +.RS +.nf +\fBchar\fP characters +\fBbyte\fP 8-bit data +\fBshort\fP 16-bit signed integers +\fBlong\fP 32-bit signed integers +\fBint\fP (synonymous with \fBlong\fP) +\fBfloat\fP IEEE single precision floating point (32 bits) +\fBreal\fP (synonymous with \fBfloat\fP) +\fBdouble\fP IEEE double precision floating point (64 bits) +.fi +.RE +.LP +Except for the added data-type \fBbyte\fP and the lack of +\fBunsigned\fP, +CDL supports the same primitive data types as C. +The names for the primitive data types are reserved words in CDL, +so the names of variables, dimensions, and attributes must not be +type names. In declarations, type names may be specified +in either upper or lower case. +.LP +Bytes differ from characters in that they are intended to hold a full eight +bits of data, and the zero byte has no special significance, as it +does for character data. +\fBncgen\fP converts \fBbyte\fP declarations to \fBchar\fP +declarations in the output C code and to the nonstandard \fBBYTE\fP +declaration in output Fortran code. +.LP +Shorts can hold values between -32768 and 32767. +\fBncgen\fP converts \fBshort\fP declarations to \fBshort\fP +declarations in the output C code and to the nonstandard \fBINTEGER*2\fP +declaration in output Fortran code. +.LP +Longs can hold values between -2147483648 and 2147483647. +\fBncgen\fP converts \fBlong\fP declarations to \fBlong\fP +declarations in the output C code and to \fBINTEGER\fP +declarations in output Fortran code. \fBint\fP and \fBinteger\fP are +accepted as synonyms for \fBlong\fP in CDL declarations. +Now that there are platforms with 64-bit representations for C longs, it may +be better to use the \fBint\fP synonym to avoid confusion. +.LP +Floats can hold values between about -3.4+38 and 3.4+38. Their +external representation is as 32-bit IEEE normalized single-precision +floating point numbers. \fBncgen\fP converts \fBfloat\fP +declarations to \fBfloat\fP declarations in the output C code and to +\fBREAL\fP declarations in output Fortran code. \fBreal\fP is accepted +as a synonym for \fBfloat\fP in CDL declarations. +.LP +Doubles can hold values between about -1.7+308 and 1.7+308. Their +external representation is as 64-bit IEEE standard normalized +double-precision floating point numbers. \fBncgen\fP converts +\fBdouble\fP declarations to \fBdouble\fP declarations in the output C +code and to \fBDOUBLE PRECISION\fP declarations in output Fortran +code. +.LP +.SS "CDL Constants" +.LP +Constants assigned to attributes or variables may be of any of the +basic netCDF types. The syntax for constants is similar to C syntax, +except that type suffixes must be appended to shorts and floats to +distinguish them from longs and doubles. +.LP +A \fIbyte\fP constant is represented by a single character or multiple +character escape sequence enclosed in single quotes. For example, +.RS +.nf + 'a' // ASCII `a' + '\\0' // a zero byte + '\\n' // ASCII newline character + '\\33' // ASCII escape character (33 octal) + '\\x2b' // ASCII plus (2b hex) + '\\377' // 377 octal = 255 decimal, non-ASCII +.fi +.RE +.LP +Character constants are enclosed in double quotes. A character array +may be represented as a string enclosed in double quotes. The usual C +string escape conventions are honored. For example +.RS +.nf +"a" // ASCII `a' +"Two\\nlines\\n" // a 10-character string with two embedded newlines +"a bell:\\007" // a string containing an ASCII bell +.fi +.RE +Note that the netCDF character array "a" would fit in a one-element +variable, since no terminating NULL character is assumed. However, a zero +byte in a character array is interpreted as the end of the significant +characters by the \fBncdump\fP program, following the C convention. +Therefore, a NULL byte should not be embedded in a character string unless +at the end: use the \fIbyte\fP data type instead for byte arrays that +contain the zero byte. NetCDF and CDL have no string type, but only +fixed-length character arrays, which may be multi-dimensional. +.LP +\fIshort\fP integer constants are intended for representing 16-bit +signed quantities. The form of a \fIshort\fP constant is an integer +constant with an `s' or `S' appended. If a \fIshort\fP constant +begins with `0', it is interpreted as octal, except that if it begins with +`0x', it is interpreted as a hexadecimal constant. For example: +.RS +.nf +-2s // a short -2 +0123s // octal +0x7ffs //hexadecimal +.fi +.RE +.LP +\fILong\fP integer constants are intended for representing 32-bit signed +quantities. The form of a \fIlong\fP constant is an ordinary integer +constant, although it is acceptable to append an optional `l' or +`L'. If a \fIlong\fP constant begins with `0', it is interpreted as +octal, except that if it begins with `0x', it is interpreted as a hexadecimal +constant. Examples of valid \fIlong\fP constants include: +.RS +.nf +-2 +1234567890L +0123 // octal +0x7ff // hexadecimal +.fi +.RE +.LP +Floating point constants of type \fIfloat\fP are appropriate for representing +floating point data with about seven significant digits of precision. +The form of a \fIfloat\fP constant is the same as a C floating point +constant with an `f' or `F' appended. For example the following +are all acceptable \fIfloat\fP constants: +.RS +.nf +-2.0f +3.14159265358979f // will be truncated to less precision +1.f +.1f +.fi +.RE +.LP +Floating point constants of type \fIdouble\fP are appropriate for +representing floating point data with about sixteen significant digits +of precision. The form of a \fIdouble\fP constant is the same as a C +floating point constant. An optional `d' or `D' may be appended. +For example the following are all acceptable \fIdouble\fP constants: +.RS +.nf +-2.0 +3.141592653589793 +1.0e-20 +1.d +.fi +.RE + +.SH BUGS +.LP +The programs generated by \fBncgen\fP when using the \fB-c\fP or \fB-f\fP +use initialization statements to store data in variables, and will fail to +produce compilable programs if you try to use them for large datasets, since +the resulting statements may exceed the line length or number of +continuation statements permitted by the compiler. +.LP +The CDL syntax makes it easy to assign what looks like an array of +variable-length strings to a netCDF variable, but the strings will simply be +concatenated into a single array of characters, since netCDF cannot +represent an array of variable-length strings in one netCDF variable. +.LP +NetCDF and CDL do not yet support a type corresponding to a 64-bit integer. Index: /tags/v1-0-3/src/utils/ncgen/load.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/load.c (revision 430) +++ /tags/v1-0-3/src/utils/ncgen/load.c (revision 430) @@ -0,0 +1,559 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +#include +#include +#include +#include +#include +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + +extern int netcdf_flag; +extern int c_flag; +extern int fortran_flag; + +#define fpr (void) fprintf + + +/* + * Remove trailing zeros (after decimal point) but not trailing decimal + * point from ss, a string representation of a floating-point number that + * might include an exponent part. + */ +static void +tztrim( + char *ss /* returned string representing dd */ + ) +{ + char *cp, *ep; + + cp = ss; + if (*cp == '-') + cp++; + while(isdigit((int)*cp) || *cp == '.') + cp++; + if (*--cp == '.') + return; + ep = cp+1; + while (*cp == '0') + cp--; + cp++; + if (cp == ep) + return; + while (*ep) + *cp++ = *ep++; + *cp = '\0'; + return; +} + + +/* generate C to put netCDF record from in-memory data */ +static void +gen_load_c( + void *rec_start + ) +{ + int idim, ival; + char *val_string; + char *charvalp = NULL; + short *shortvalp = NULL; + int *intvalp = NULL; + float *floatvalp = NULL; + double *doublevalp = NULL; + char stmnt[C_MAX_STMNT]; + size_t stmnt_len; + char s2[C_MAX_STMNT]; + + if (!vars[varnum].has_data) + return; + + cline(""); + sprintf(stmnt, " {\t\t\t/* store %s */", vars[varnum].name); + cline(stmnt); + + if (vars[varnum].ndims > 0) { + if (vars[varnum].dims[0] == rec_dim) { + sprintf(stmnt, " static size_t %s_start[RANK_%s];", + vars[varnum].lname, vars[varnum].lname); + cline(stmnt); + + sprintf(stmnt, " static size_t %s_count[RANK_%s];", + vars[varnum].lname, vars[varnum].lname); + cline(stmnt); + } + + /* load variable with data values using static initialization */ + sprintf(stmnt, " static %s %s[] = {", + ncctype(vars[varnum].type), + vars[varnum].lname); + + stmnt_len = strlen(stmnt); + switch (vars[varnum].type) { + case NC_CHAR: + val_string = cstrstr((char *) rec_start, var_len); + sprintf(s2, "%s", val_string); + strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) ); + free(val_string); + break; + default: + switch (vars[varnum].type) { + 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; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + } + for (ival = 0; ival < var_len-1; ival++) { + switch (vars[varnum].type) { + case NC_BYTE: + sprintf(s2, "%d, ", *charvalp++); + break; + case NC_SHORT: + sprintf(s2, "%d, ", *shortvalp++); + break; + case NC_INT: + sprintf(s2, "%ld, ", (long)*intvalp++); + break; + case NC_FLOAT: + sprintf(s2, "%.8g, ", *floatvalp++); + break; + case NC_DOUBLE: + sprintf(s2, "%#.16g", *doublevalp++); + tztrim(s2); + strcat(s2, ", "); + break; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + + } + stmnt_len += strlen(s2); + if (stmnt_len < C_MAX_STMNT) + strcat(stmnt, s2); + else { + cline(stmnt); + strcpy(stmnt,s2); + stmnt_len = strlen(stmnt); + } + } + for (;ival < var_len; ival++) { + switch (vars[varnum].type) { + case NC_BYTE: + sprintf(s2, "%d", *charvalp); + break; + case NC_SHORT: + sprintf(s2, "%d", *shortvalp); + break; + case NC_INT: + sprintf(s2, "%ld", (long)*intvalp); + break; + case NC_FLOAT: + sprintf(s2, "%.8g", *floatvalp); + break; + case NC_DOUBLE: + sprintf(s2, "%#.16g", *doublevalp++); + tztrim(s2); + break; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + } + stmnt_len += strlen(s2); + if (stmnt_len < C_MAX_STMNT) + strcat(stmnt, s2); + else { + cline(stmnt); + strcpy(stmnt,s2); + stmnt_len = strlen(stmnt); + } + } + break; + } + strcat(stmnt,"};"); + cline(stmnt); + + if (vars[varnum].dims[0] == rec_dim) { + sprintf(stmnt, + " %s_len = %lu; /* number of records of %s data */", + dims[rec_dim].lname, + (unsigned long)vars[varnum].nrecs, /* number of recs for this variable */ + vars[varnum].name); + cline(stmnt); + + for (idim = 0; idim < vars[varnum].ndims; idim++) { + sprintf(stmnt, " %s_start[%d] = 0;", + vars[varnum].lname, + idim); + cline(stmnt); + } + + for (idim = 0; idim < vars[varnum].ndims; idim++) { + sprintf(stmnt, " %s_count[%d] = %s_len;", + vars[varnum].lname, + idim, + dims[vars[varnum].dims[idim]].lname); + cline(stmnt); + } + } + + if (vars[varnum].dims[0] == rec_dim) { + sprintf(stmnt, + " stat = ncmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s);", + ncstype(vars[varnum].type), + vars[varnum].lname, + vars[varnum].lname, + vars[varnum].lname, + vars[varnum].lname); + cline(stmnt); + } else { /* non-record variables */ + cline(" ncmpi_begin_indep_data(ncid);"); + sprintf(stmnt, + " stat = ncmpi_put_var_%s(ncid, %s_id, %s);", + ncstype(vars[varnum].type), + vars[varnum].lname, + vars[varnum].lname); + cline(stmnt); + cline(" ncmpi_end_indep_data(ncid);"); + } + } else { /* scalar variables */ + /* load variable with data values using static initialization */ + sprintf(stmnt, " static %s %s = ", + ncctype(vars[varnum].type), + vars[varnum].lname); + + switch (vars[varnum].type) { + case NC_CHAR: + val_string = cstrstr((char *) rec_start, var_len); + val_string[strlen(val_string)-1] = '\0'; + sprintf(s2, "'%s'", &val_string[1]); + free(val_string); + break; + case NC_BYTE: + charvalp = (char *) rec_start; + sprintf(s2, "%d", *charvalp); + break; + case NC_SHORT: + shortvalp = (short *) rec_start; + sprintf(s2, "%d", *shortvalp); + break; + case NC_INT: + intvalp = (int *) rec_start; + sprintf(s2, "%ld", (long)*intvalp); + break; + case NC_FLOAT: + floatvalp = (float *) rec_start; + sprintf(s2, "%.8g", *floatvalp); + break; + case NC_DOUBLE: + doublevalp = (double *) rec_start; + sprintf(s2, "%#.16g", *doublevalp++); + tztrim(s2); + break; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + } + strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) ); + strcat(stmnt,";"); + cline(stmnt); + cline(" ncmpi_begin_indep_data(ncid);"); + sprintf(stmnt, + " stat = ncmpi_put_var_%s(ncid, %s_id, &%s);", + ncstype(vars[varnum].type), + vars[varnum].lname, + vars[varnum].lname); + cline(stmnt); + cline(" ncmpi_end_indep_data(ncid);"); + } + cline(" check_err(stat,__LINE__,__FILE__);"); + cline(" }"); +} + + +/* + * Add to a partial Fortran statement, checking if it's too long. If it is too + * long, output the first part of it as a single statement with continuation + * characters and start a new (probably invalid) statement with the remainder. + * This will cause a Fortran compiler error, but at least all the information + * will be available. + */ +static void +fstrcat( + char *s, /* source string of stement being built */ + const char *t, /* string to be appended to source */ + size_t *slenp /* pointer to length of source string */ + ) +{ + *slenp += strlen(t); + if (*slenp >= FORT_MAX_STMNT) { + derror("FORTRAN statement too long: %s",s); + fline(s); + strcpy(s, t); + *slenp = strlen(s); + } else { + strcat(s, t); + } +} + +/* + * Create Fortran data statement to initialize numeric variable with + * values. + */ +static void +f_var_init( + int varnum, /* which variable */ + void *rec_start /* start of data */ + ) +{ + char *val_string; + char *charvalp; + short *shortvalp; + int *intvalp; + float *floatvalp; + double *doublevalp; + char stmnt[FORT_MAX_STMNT]; + size_t stmnt_len; + char s2[FORT_MAX_STMNT]; + int ival; + + /* load variable with data values */ + sprintf(stmnt, "data %s /",vars[varnum].lname); + stmnt_len = strlen(stmnt); + switch (vars[varnum].type) { + case NC_BYTE: + charvalp = (char *) rec_start; + for (ival = 0; ival < var_len-1; ival++) { + val_string = fstring(NC_BYTE,(void *)charvalp++,0); + sprintf(s2, "%s, ", val_string); + fstrcat(stmnt, s2, &stmnt_len); + free(val_string); + } + val_string = fstring(NC_BYTE,(void *)charvalp++,0); + fstrcat(stmnt, val_string, &stmnt_len); + free(val_string); + break; + case NC_SHORT: + shortvalp = (short *) rec_start; + for (ival = 0; ival < var_len-1; ival++) { + sprintf(s2, "%d, ", *shortvalp++); + fstrcat(stmnt, s2, &stmnt_len); + } + sprintf(s2, "%d", *shortvalp); + fstrcat(stmnt, s2, &stmnt_len); + break; + case NC_INT: + intvalp = (int *) rec_start; + for (ival = 0; ival < var_len-1; ival++) { + sprintf(s2, "%ld, ", (long)*intvalp++); + fstrcat(stmnt, s2, &stmnt_len); + } + sprintf(s2, "%ld", (long)*intvalp); + fstrcat(stmnt, s2, &stmnt_len); + break; + case NC_FLOAT: + floatvalp = (float *) rec_start; + for (ival = 0; ival < var_len-1; ival++) { + sprintf(s2, "%.8g, ", *floatvalp++); + fstrcat(stmnt, s2, &stmnt_len); + } + sprintf(s2, "%.8g", *floatvalp); + fstrcat(stmnt, s2, &stmnt_len); + break; + case NC_DOUBLE: + doublevalp = (double *) rec_start; + for (ival = 0; ival < var_len-1; ival++) { + sprintf(s2, "%#.16g", *doublevalp++); + tztrim(s2); + expe2d(s2); /* change 'e' to 'd' in exponent */ + fstrcat(s2, ", ", &stmnt_len); + fstrcat(stmnt, s2, &stmnt_len); + } + sprintf(s2, "%#.16g", *doublevalp++); + tztrim(s2); + expe2d(s2); + fstrcat(stmnt, s2, &stmnt_len); + break; + default: + derror("fstrstr: bad type"); + break; + } + fstrcat(stmnt, "/", &stmnt_len); + + /* For record variables, store data statement for later use; + otherwise, just print it. */ + if (vars[varnum].ndims > 0 && vars[varnum].dims[0] == rec_dim) { + char *dup_stmnt = emalloc(strlen(stmnt)+1); + strcpy(dup_stmnt, stmnt); /* ULTRIX missing strdup */ + vars[varnum].data_stmnt = dup_stmnt; + } else { + fline(stmnt); + } +} + + +/* make Fortran to put record */ +static void +gen_load_fortran( + void *rec_start + ) +{ + char stmnt[FORT_MAX_STMNT]; + struct vars *v = &vars[varnum]; + + if (!v->has_data) + return; + + if (v->ndims == 0 || v->dims[0] != rec_dim) { + sprintf(stmnt, "* store %s", v->name); + fline(stmnt); + } + + /* generate code to initialize variable with values found in CDL input */ + if (v->type != NC_CHAR) { + f_var_init(varnum, rec_start); + } else { + v->data_stmnt = fstrstr(rec_start, valnum); + } + + if (v->ndims >0 && v->dims[0] == rec_dim) { + return; + } + if (v->type != NC_CHAR) { + sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)", + nfftype(v->type), v->lname, v->lname); + } else { + char *char_expr = fstrstr(rec_start, valnum); + sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)", + nfftype(v->type), v->lname, char_expr); + free(char_expr); + } + + fline(stmnt); + fline("call check_err(iret)"); +} + + +/* invoke netcdf calls (or generate C or Fortran code) to load netcdf variable + * from in-memory data. Assumes following global variables set from yacc + * parser: + * int varnum - number of variable to be loaded. + * struct vars[varnum] - structure containing info on variable, specifically + * name, type, ndims, dims, fill_value, has_data + * int rec_dim - id of record dimension, or -1 if none + * struct dims[] - structure containing name and size of dimensions. + */ +int +put_variable( + void *rec_start /* points to data to be loaded */ + ) +{ + if (netcdf_flag) + load_netcdf(rec_start); /* put variable values */ + if (c_flag) /* create C code to put values */ + gen_load_c(rec_start); + if (fortran_flag) /* create Fortran code to put values */ + gen_load_fortran(rec_start); + + return 0; +} + + +/* write out variable's data from in-memory structure */ +void +load_netcdf( + void *rec_start + ) +{ + int idim; + int stat = NC_NOERR; + MPI_Offset start[NC_MAX_VAR_DIMS]; + MPI_Offset count[NC_MAX_VAR_DIMS]; + char *charvalp = NULL; + short *shortvalp = NULL; + int *intvalp = NULL; + float *floatvalp = NULL; + double *doublevalp = NULL; + + /* 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; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + } + 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; + } + + switch (vars[varnum].type) { + case NC_BYTE: + stat = ncmpi_put_vara_schar(ncid, varnum, start, count, + (signed char *)charvalp); + break; + case NC_CHAR: + stat = ncmpi_put_vara_text_all(ncid, varnum, start, count, charvalp); + break; + case NC_SHORT: + stat = ncmpi_put_vara_short_all(ncid, varnum, start, count, shortvalp); + break; + case NC_INT: + stat = ncmpi_put_vara_int_all(ncid, varnum, start, count, intvalp); + break; + case NC_FLOAT: + stat = ncmpi_put_vara_float_all(ncid, varnum, start, count, floatvalp); + break; + case NC_DOUBLE: + stat = ncmpi_put_vara_double_all(ncid, varnum, start, count, doublevalp); + break; + default: + derror("Unhandled type %d\n", vars[varnum].type); + break; + } + check_err(stat); +} Index: /tags/v1-0-3/src/utils/ncgen/ncgen.h =================================================================== --- /tags/v1-0-3/src/utils/ncgen/ncgen.h (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/ncgen.h (revision 313) @@ -0,0 +1,56 @@ +#ifndef NC_NCGEN_H +#define NC_NCGEN_H +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#define MAX_NC_ATTSIZE 20000 /* max size of attribute (for ncgen) */ +#define MAXTRST 5000 /* max size of string value (for ncgen) */ + +#include "generic.h" + +extern int ncid; /* handle for netCDF */ +extern int ndims; /* number of dimensions declared for netcdf */ +extern int nvars; /* number of variables declared for netcdf */ +extern int natts; /* number of attributes */ +extern int nvdims; /* number of dimensions for variables */ +extern int dimnum; /* dimension number index for variables */ +extern int varnum; /* variable number index for attributes */ +extern int valnum; /* number of values specified for variable */ +extern int rec_dim; /* number of the unlimited dimension, if any */ +extern size_t rec_len; /* number of elements for a record of data */ +extern size_t var_len; /* variable length (product of dimensions) */ +extern size_t var_size; /* size of each element of variable */ + +extern struct dims { + size_t size; + char *name; + char *lname; /* with no "-" characters, for C and Fortran */ +} *dims; /* table of dimensions */ + +extern struct vars { + char *name; + nc_type type; + int ndims; + int *dims; /* array of dimension ids */ + union generic fill_value; /* set to value of _FillValue attribute */ + int has_data; /* 1 if data specified, 0 otherwise */ + size_t nrecs; /* for record variables, number of records + * of data in CDL */ + char *data_stmnt; /* for record variables, to avoid + * two passes with -f option */ + char *lname; /* with no "-" characters, for C and Fortran */ +} *vars; /* table of variables */ + + +extern struct atts { + int var; /* number of variable for this attribute */ + char *name; + nc_type type; + size_t len; + void *val; + char *lname; /* with no "-" characters, for C and Fortran */ +} *atts; /* table of variable and global attributes */ +#endif /*!NC_NCGEN_H*/ Index: /tags/v1-0-3/src/utils/ncgen/genlib.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/genlib.c (revision 601) +++ /tags/v1-0-3/src/utils/ncgen/genlib.c (revision 601) @@ -0,0 +1,1894 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include +#include +#include +#include /* for isprint() */ +#ifndef NO_STDARG +#include +#else +/* try varargs instead */ +#include +#endif /* !NO_STDARG */ +#include +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + +#include +extern char *netcdf_name; /* output netCDF filename, if on command line. */ +extern int netcdf_flag; +extern int c_flag; +extern int fortran_flag; +extern int giantfile_flag; +extern int nofill_flag; + +int lineno = 1; +int derror_count = 0; + + + +/* create netCDF from in-memory structure */ +static void +gen_netcdf( + char *filename) /* name for output netcdf file */ +{ + int idim, ivar, iatt; + int dimid; + int varid; + int stat; + + if (!giantfile_flag) { + stat = ncmpi_create(MPI_COMM_WORLD, filename, + NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncid); + check_err(stat); + } else { + stat = ncmpi_create(MPI_COMM_WORLD, filename, + NC_CLOBBER, MPI_INFO_NULL, &ncid); + } + + /* define dimensions from info in dims array */ + for (idim = 0; idim < ndims; idim++) { + stat = ncmpi_def_dim(ncid, dims[idim].name, dims[idim].size, &dimid); + check_err(stat); + } + + /* define variables from info in vars array */ + for (ivar = 0; ivar < nvars; ivar++) { + stat = ncmpi_def_var(ncid, + vars[ivar].name, + vars[ivar].type, + vars[ivar].ndims, + vars[ivar].dims, + &varid); + check_err(stat); + } + + /* define attributes from info in atts array */ + for (iatt = 0; iatt < natts; iatt++) { + varid = (atts[iatt].var == -1) ? NC_GLOBAL : atts[iatt].var; + switch(atts[iatt].type) { + case NC_BYTE: + stat = ncmpi_put_att_schar(ncid, varid, atts[iatt].name, + atts[iatt].type, atts[iatt].len, + (signed char *) atts[iatt].val); + break; + case NC_CHAR: + stat = ncmpi_put_att_text(ncid, varid, atts[iatt].name, + atts[iatt].len, + (char *) atts[iatt].val); + break; + case NC_SHORT: + stat = ncmpi_put_att_short(ncid, varid, atts[iatt].name, + atts[iatt].type, atts[iatt].len, + (short *) atts[iatt].val); + break; + case NC_INT: + stat = ncmpi_put_att_int(ncid, varid, atts[iatt].name, + atts[iatt].type, atts[iatt].len, + (int *) atts[iatt].val); + break; + case NC_FLOAT: + stat = ncmpi_put_att_float(ncid, varid, atts[iatt].name, + atts[iatt].type, atts[iatt].len, + (float *) atts[iatt].val); + break; + case NC_DOUBLE: + stat = ncmpi_put_att_double(ncid, varid, atts[iatt].name, + atts[iatt].type, atts[iatt].len, + (double *) atts[iatt].val); + break; + default: + stat = NC_EBADTYPE; + } + check_err(stat); + } + + /* serial netcdf calls nc_set_fill(NC_NOFILL) here, but we do not + * implement that routine (NC_NOFILL is our default and only behavior) */ + + stat = ncmpi_enddef(ncid); + check_err(stat); +} + + +/* + * Given a netcdf type, a pointer to a vector of values of that type, + * and the index of the vector element desired, returns a pointer to a + * malloced string representing the value in C. + */ +static char * +cstring( + ncmpi_type type, /* netCDF type code */ + void *valp, /* pointer to vector of values */ + int num) /* element of vector desired */ +{ + static char *cp, *sp, ch; + signed char *bytep; + short *shortp; + int *intp; + float *floatp; + double *doublep; + + switch (type) { + case NC_CHAR: + sp = cp = (char *) emalloc (7); + *cp++ = '\''; + ch = *((char *)valp + num); + switch (ch) { + case '\b': *cp++ = '\\'; *cp++ = 'b'; break; + case '\f': *cp++ = '\\'; *cp++ = 'f'; break; + case '\n': *cp++ = '\\'; *cp++ = 'n'; break; + case '\r': *cp++ = '\\'; *cp++ = 'r'; break; + case '\t': *cp++ = '\\'; *cp++ = 't'; break; + case '\v': *cp++ = '\\'; *cp++ = 'v'; break; + case '\\': *cp++ = '\\'; *cp++ = '\\'; break; + case '\'': *cp++ = '\\'; *cp++ = '\''; break; + default: + if (!isprint(ch)) { + static char octs[] = "01234567"; + int rem = ((unsigned char)ch)%64; + *cp++ = '\\'; + *cp++ = octs[((unsigned char)ch)/64]; /* to get, e.g. '\177' */ + *cp++ = octs[rem/8]; + *cp++ = octs[rem%8]; + } else { + *cp++ = ch; + } + break; + } + *cp++ = '\''; + *cp = '\0'; + return sp; + + case NC_BYTE: + cp = (char *) emalloc (7); + bytep = (signed char *)valp; + /* Need to convert '\377' to -1, for example, on all platforms */ + (void) sprintf(cp,"%d", (signed char) *(bytep+num)); + return cp; + + case NC_SHORT: + cp = (char *) emalloc (10); + shortp = (short *)valp; + (void) sprintf(cp,"%d",* (shortp + num)); + return cp; + + case NC_INT: + cp = (char *) emalloc (20); + intp = (int *)valp; + (void) sprintf(cp,"%d",* (intp + num)); + return cp; + + case NC_FLOAT: + cp = (char *) emalloc (20); + floatp = (float *)valp; + (void) sprintf(cp,"%.8g",* (floatp + num)); + return cp; + + case NC_DOUBLE: + cp = (char *) emalloc (20); + doublep = (double *)valp; + (void) sprintf(cp,"%.16g",* (doublep + num)); + return cp; + + default: + derror("cstring: bad type code"); + return 0; + } +} + + +/* + * Generate C code for creating netCDF from in-memory structure. + */ +static void +gen_c( + const char *filename) +{ + int idim, ivar, iatt, jatt, maxdims; + int vector_atts; + char *val_string; + char stmnt[C_MAX_STMNT]; + + /* wrap in main program */ + cline("#include "); + cline("#include "); + cline("#include "); + cline("#include "); + cline(""); + cline("void"); + cline("check_err(const int stat, const int line, const char *file) {"); + cline(" if (stat != NC_NOERR) {"); + cline(" (void) fprintf(stderr, \"line %d of %s: %s\\n\", line, file, ncmpi_strerror(stat));"); + cline(" exit(1);"); + cline(" }"); + cline("}"); + cline(""); + cline("int"); + sprintf(stmnt, "main(int argc, char **argv) {\t\t\t/* create %s */", filename); + cline(stmnt); + + /* create necessary declarations */ + cline(""); + cline(" int stat;\t\t\t/* return status */"); + cline(" int ncid;\t\t\t/* netCDF id */"); + + if (ndims > 0) { + cline(""); + cline(" /* dimension ids */"); + for (idim = 0; idim < ndims; idim++) { + sprintf(stmnt, " int %s_dim;", dims[idim].lname); + cline(stmnt); + } + + cline(""); + cline(" /* dimension lengths */"); + for (idim = 0; idim < ndims; idim++) { + if (dims[idim].size == NC_UNLIMITED) { + sprintf(stmnt, " size_t %s_len = NC_UNLIMITED;", + dims[idim].lname); + } else { + sprintf(stmnt, " size_t %s_len = %lu;", + dims[idim].lname, + (unsigned long) dims[idim].size); + } + cline(stmnt); + } + } + + maxdims = 0; /* most dimensions of any variable */ + for (ivar = 0; ivar < nvars; ivar++) + if (vars[ivar].ndims > maxdims) + maxdims = vars[ivar].ndims; + + if (nvars > 0) { + cline(""); + cline(" /* variable ids */"); + for (ivar = 0; ivar < nvars; ivar++) { + sprintf(stmnt, " int %s_id;", vars[ivar].lname); + cline(stmnt); + } + + cline(""); + cline(" /* rank (number of dimensions) for each variable */"); + for (ivar = 0; ivar < nvars; ivar++) { + sprintf(stmnt, "# define RANK_%s %d", vars[ivar].lname, + vars[ivar].ndims); + cline(stmnt); + } + if (maxdims > 0) { /* we have dimensioned variables */ + cline(""); + cline(" /* variable shapes */"); + for (ivar = 0; ivar < nvars; ivar++) { + if (vars[ivar].ndims > 0) { + sprintf(stmnt, " int %s_dims[RANK_%s];", + vars[ivar].lname, vars[ivar].lname); + cline(stmnt); + } + } + } + } + + /* determine if we need any attribute vectors */ + vector_atts = 0; + for (iatt = 0; iatt < natts; iatt++) { + if (atts[iatt].type != NC_CHAR) { + vector_atts = 1; + break; + } + } + if (vector_atts) { + cline(""); + cline(" /* attribute vectors */"); + for (iatt = 0; iatt < natts; iatt++) { + if (atts[iatt].type != NC_CHAR) { + sprintf(stmnt, + " %s %s_%s[%lu];", + ncatype(atts[iatt].type), + atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, + atts[iatt].lname, + (unsigned long) atts[iatt].len); + cline(stmnt); + } + } + } + + /* create netCDF file, uses NC_CLOBBER mode */ + cline(""); + cline(" int stat=0;"); + cline(" MPI_Init(&argc, &argv);"); + cline(" /* enter define mode */"); + + if (!giantfile_flag) { + sprintf(stmnt, + " stat = ncmpi_create(MPI_COMM_WORLD, \"%s\", NC_CLOBBER, MPI_INFO_NULL, &ncid);", + filename); + } else { + sprintf(stmnt, " stat = ncmpi_create(MPI_COMM_WORLD, \"%s\", NC_CLOBBER|NC_64BIT_OFFSET, &ncid);", + filename); + } + cline(stmnt); + cline(" check_err(stat,__LINE__,__FILE__);"); + + /* define dimensions from info in dims array */ + if (ndims > 0) { + cline(""); + cline(" /* define dimensions */"); + } + for (idim = 0; idim < ndims; idim++) { + sprintf(stmnt, + " stat = ncmpi_def_dim(ncid, \"%s\", %s_len, &%s_dim);", + dims[idim].name, dims[idim].lname, dims[idim].lname); + cline(stmnt); + cline(" check_err(stat,__LINE__,__FILE__);"); + } + + /* define variables from info in vars array */ + if (nvars > 0) { + cline(""); + cline(" /* define variables */"); + for (ivar = 0; ivar < nvars; ivar++) { + cline(""); + for (idim = 0; idim < vars[ivar].ndims; idim++) { + sprintf(stmnt, + " %s_dims[%d] = %s_dim;", + vars[ivar].lname, + idim, + dims[vars[ivar].dims[idim]].lname); + cline(stmnt); + } + if (vars[ivar].ndims > 0) { /* a dimensioned variable */ + sprintf(stmnt, + " stat = ncmpi_def_var(ncid, \"%s\", %s, RANK_%s, %s_dims, &%s_id);", + vars[ivar].name, + nctype(vars[ivar].type), + vars[ivar].lname, + vars[ivar].lname, + vars[ivar].lname); + } else { /* a scalar */ + sprintf(stmnt, + " stat = ncmpi_def_var(ncid, \"%s\", %s, RANK_%s, 0, &%s_id);", + vars[ivar].name, + nctype(vars[ivar].type), + vars[ivar].lname, + vars[ivar].lname); + } + cline(stmnt); + cline(" check_err(stat,__LINE__,__FILE__);"); + } + } + + /* define attributes from info in atts array */ + if (natts > 0) { + cline(""); + cline(" /* assign attributes */"); + for (iatt = 0; iatt < natts; iatt++) { + if (atts[iatt].type == NC_CHAR) { /* string */ + val_string = cstrstr((char *) atts[iatt].val, atts[iatt].len); + sprintf(stmnt, + " stat = ncmpi_put_att_text(ncid, %s%s, \"%s\", %lu, %s);", + atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname, + atts[iatt].var == -1 ? "" : "_id", + atts[iatt].name, + (unsigned long) atts[iatt].len, + val_string); + cline(stmnt); + free (val_string); + } + else { /* vector attribute */ + for (jatt = 0; jatt < atts[iatt].len ; jatt++) { + val_string = cstring(atts[iatt].type,atts[iatt].val,jatt); + sprintf(stmnt, " %s_%s[%d] = %s;", + atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, + atts[iatt].lname, + jatt, + val_string); + cline(stmnt); + free (val_string); + } + + sprintf(stmnt, + " stat = ncmpi_put_att_%s(ncid, %s%s, \"%s\", %s, %lu, %s_%s);", + ncatype(atts[iatt].type), + atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname, + atts[iatt].var == -1 ? "" : "_id", + atts[iatt].name, + nctype(atts[iatt].type), + (unsigned long) atts[iatt].len, + atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname, + atts[iatt].lname); + cline(stmnt); + } + cline(" check_err(stat,__LINE__,__FILE__);"); + } + } + /* here's another place where serial netcdf would insert a call to + * setfill(NOFILL), but that's our only supported behavior, so skip */ + cline(""); + cline(" /* leave define mode */"); + cline(" stat = ncmpi_enddef (ncid);"); + cline(" check_err(stat,__LINE__,__FILE__);"); +} + + +/* return Fortran type name for netCDF type, given type code */ +static const char * +ncftype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + + case NC_BYTE: + return "integer"; + case NC_CHAR: + return "character"; + case NC_SHORT: + return "integer"; + case NC_INT: +#ifdef MSDOS + return "integer*4"; +#else + return "integer"; +#endif + case NC_FLOAT: + return "real"; +#ifdef _CRAY + case NC_DOUBLE: + return "real"; /* we don't support CRAY 128-bit doubles */ +#else + case NC_DOUBLE: + return "double precision"; +#endif + default: + derror("ncftype: bad type code"); + return 0; + + } +} + + +/* return Fortran type suffix for netCDF type, given type code */ +const char * +nfstype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "int1"; + case NC_CHAR: + return "text"; + case NC_SHORT: + return "int2"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "real"; + case NC_DOUBLE: + return "double"; + default: + derror("nfstype: bad type code"); + return 0; + + } +} + + +/* Return Fortran function suffix for netCDF type, given type code. + * This should correspond to the Fortran type name in ncftype(). + */ +const char * +nfftype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "int"; + case NC_CHAR: + return "text"; + case NC_SHORT: + return "int"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "real"; +#ifdef _CRAY + case NC_DOUBLE: + return "real"; /* we don't support CRAY 128-bit doubles */ +#else + case NC_DOUBLE: + return "double"; +#endif + default: + derror("nfstype: bad type code"); + return 0; + + } +} + + +/* return FORTRAN name for netCDF type, given type code */ +static const char * +ftypename( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "NF_INT1"; + case NC_CHAR: + return "NF_CHAR"; + case NC_SHORT: + return "NF_INT2"; + case NC_INT: + return "NF_INT"; + case NC_FLOAT: + return "NF_REAL"; + case NC_DOUBLE: + return "NF_DOUBLE"; + default: + derror("ftypename: bad type code"); + return 0; + } +} + + +/* + * Generate FORTRAN code for creating netCDF from in-memory structure. + */ +static void +gen_fortran( + const char *filename) +{ + int idim, ivar, iatt, jatt, itype, maxdims; + int vector_atts; + char *val_string; + char stmnt[FORT_MAX_STMNT]; + char s2[NC_MAX_NAME + 10]; + char *sp; + /* Need how many netCDF types there are, because we create an array + * for each type of attribute. */ + int ntypes = 6; /* number of netCDF types, NC_BYTE, ... */ + ncmpi_type types[6]; /* at least ntypes */ + size_t max_atts[NC_DOUBLE + 1]; + + types[0] = NC_BYTE; + types[1] = NC_CHAR; + types[2] = NC_SHORT; + types[3] = NC_INT; + types[4] = NC_FLOAT; + types[5] = NC_DOUBLE; + + fline("program fgennc"); + + fline("include 'pnetcdf.inc'"); + + /* create necessary declarations */ + fline("* error status return"); + fline("integer iret"); + fline("* netCDF id"); + fline("integer ncid"); + if (nofill_flag) { + fline(" * to save old fill mode before changing it temporarily"); + fline ("integer oldmode"); + } + + if (ndims > 0) { + fline("* dimension ids"); + for (idim = 0; idim < ndims; idim++) { + sprintf(stmnt, "integer %s_dim", dims[idim].lname); + fline(stmnt); + } + + fline("* dimension lengths"); + for (idim = 0; idim < ndims; idim++) { + sprintf(stmnt, "integer %s_len", dims[idim].lname); + fline(stmnt); + } + for (idim = 0; idim < ndims; idim++) { + if (dims[idim].size == NC_UNLIMITED) { + sprintf(stmnt, "parameter (%s_len = NFMPI_UNLIMITED)", + dims[idim].lname); + } else { + sprintf(stmnt, "parameter (%s_len = %lu)", + dims[idim].lname, + (unsigned long) dims[idim].size); + } + fline(stmnt); + } + + } + + maxdims = 0; /* most dimensions of any variable */ + for (ivar = 0; ivar < nvars; ivar++) + if (vars[ivar].ndims > maxdims) + maxdims = vars[ivar].ndims; + + if (nvars > 0) { + fline("* variable ids"); + for (ivar = 0; ivar < nvars; ivar++) { + sprintf(stmnt, "integer %s_id", vars[ivar].lname); + fline(stmnt); + } + + fline("* rank (number of dimensions) for each variable"); + for (ivar = 0; ivar < nvars; ivar++) { + sprintf(stmnt, "integer %s_rank", vars[ivar].lname); + fline(stmnt); + } + for (ivar = 0; ivar < nvars; ivar++) { + sprintf(stmnt, "parameter (%s_rank = %d)", vars[ivar].lname, + vars[ivar].ndims); + fline(stmnt); + } + + fline("* variable shapes"); + for (ivar = 0; ivar < nvars; ivar++) { + if (vars[ivar].ndims > 0) { + sprintf(stmnt, "integer %s_dims(%s_rank)", + vars[ivar].lname, vars[ivar].lname); + fline(stmnt); + } + } + } + + /* declarations for variables to be initialized */ + if (nvars > 0) { /* we have variables */ + fline("* data variables"); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + /* Generate declarations here for non-record data variables only. + Record variables are declared in separate subroutine later, + when we know how big they are. */ + if (v->ndims > 0 && v->dims[0] == rec_dim) { + continue; + } + /* Make declarations for non-text variables only; + for text variables, just include string in nfmpi_put_var call */ + if (v->type == NC_CHAR) { + continue; + } + if (v->ndims == 0) { /* scalar */ + sprintf(stmnt, "%s %s", ncftype(v->type), + v->lname); + } else { + sprintf(stmnt, "%s %s(", ncftype(v->type), + v->lname); + /* reverse dimensions for FORTRAN */ + for (idim = v->ndims-1; idim >= 0; idim--) { + sprintf(s2, "%s_len, ", + dims[v->dims[idim]].lname); + strcat(stmnt, s2); + } + sp = strrchr(stmnt, ','); + if(sp != NULL) { + *sp = '\0'; + } + strcat(stmnt, ")"); + } + fline(stmnt); + } + } + + /* determine what attribute vectors needed */ + for (itype = 0; itype < ntypes; itype++) + max_atts[(int)types[itype]] = 0; + + vector_atts = 0; + for (iatt = 0; iatt < natts; iatt++) { + if (atts[iatt].len > max_atts[(int) atts[iatt].type]) { + max_atts[(int)atts[iatt].type] = atts[iatt].len; + vector_atts = 1; + } + } + if (vector_atts) { + fline("* attribute vectors"); + for (itype = 0; itype < ntypes; itype++) { + if (types[itype] != NC_CHAR && max_atts[(int)types[itype]] > 0) { + sprintf(stmnt, "%s %sval(%lu)", ncftype(types[itype]), + nfstype(types[itype]), + (unsigned long) max_atts[(int)types[itype]]); + fline(stmnt); + } + } + } + + /* create netCDF file, uses NC_CLOBBER mode */ + fline("* enter define mode"); + if (!giantfile_flag) { + sprintf(stmnt, "iret = nfmpi_create(\'%s\', NF_CLOBBER, ncid)", filename); + } else { + sprintf(stmnt, "iret = nfmpi_create(\'%s\', OR(NF_CLOBBER|NF_64BIT_OFFSET), ncid)", filename); + } + fline(stmnt); + fline("call check_err(iret)"); + + /* define dimensions from info in dims array */ + if (ndims > 0) + fline("* define dimensions"); + for (idim = 0; idim < ndims; idim++) { + if (dims[idim].size == NC_UNLIMITED) + sprintf(stmnt, "iret = nfmpi_def_dim(ncid, \'%s\', NFMPI_UNLIMITED, %s_dim)", + dims[idim].name, dims[idim].lname); + else + sprintf(stmnt, "iret = nfmpi_def_dim(ncid, \'%s\', %lu, %s_dim)", + dims[idim].name, (unsigned long) dims[idim].size, + dims[idim].lname); + fline(stmnt); + fline("call check_err(iret)"); + } + + /* define variables from info in vars array */ + if (nvars > 0) { + fline("* define variables"); + for (ivar = 0; ivar < nvars; ivar++) { + for (idim = 0; idim < vars[ivar].ndims; idim++) { + sprintf(stmnt, "%s_dims(%d) = %s_dim", + vars[ivar].lname, + vars[ivar].ndims - idim, /* reverse dimensions */ + dims[vars[ivar].dims[idim]].lname); + fline(stmnt); + } + if (vars[ivar].ndims > 0) { /* a dimensioned variable */ + sprintf(stmnt, + "iret = nfmpi_def_var(ncid, \'%s\', %s, %s_rank, %s_dims, %s_id)", + vars[ivar].name, + ftypename(vars[ivar].type), + vars[ivar].lname, + vars[ivar].lname, + vars[ivar].lname); + } else { /* a scalar */ + sprintf(stmnt, + "iret = nfmpi_def_var(ncid, \'%s\', %s, %s_rank, 0, %s_id)", + vars[ivar].name, + ftypename(vars[ivar].type), + vars[ivar].lname, + vars[ivar].lname); + } + fline(stmnt); + fline("call check_err(iret)"); + } + } + + /* define attributes from info in atts array */ + if (natts > 0) { + fline("* assign attributes"); + for (iatt = 0; iatt < natts; iatt++) { + if (atts[iatt].type == NC_CHAR) { /* string */ + val_string = fstrstr((char *) atts[iatt].val, atts[iatt].len); + sprintf(stmnt, + "iret = nfmpi_put_att_text(ncid, %s%s, \'%s\', %lu, %s)", + atts[iatt].var == -1 ? "NF_GLOBAL" : vars[atts[iatt].var].lname, + atts[iatt].var == -1 ? "" : "_id", + atts[iatt].name, + (unsigned long) atts[iatt].len, + val_string); + fline(stmnt); + fline("call check_err(iret)"); + free(val_string); + } else { + for (jatt = 0; jatt < atts[iatt].len ; jatt++) { + val_string = fstring(atts[iatt].type,atts[iatt].val,jatt); + sprintf(stmnt, "%sval(%d) = %s", + nfstype(atts[iatt].type), + jatt+1, + val_string); + fline(stmnt); + free (val_string); + } + + sprintf(stmnt, + "iret = nfmpi_put_att_%s(ncid, %s%s, \'%s\', %s, %lu, %sval)", + nfftype(atts[iatt].type), + atts[iatt].var == -1 ? "NCGLOBAL" : vars[atts[iatt].var].lname, + atts[iatt].var == -1 ? "" : "_id", + atts[iatt].name, + ftypename(atts[iatt].type), + (unsigned long) atts[iatt].len, + nfstype(atts[iatt].type)); + fline(stmnt); + fline("call check_err(iret)"); + } + } + } + /* skip the call to nfmpi_set_fill until we implement it */ + fline("* leave define mode"); + fline("iret = nfmpi_enddef(ncid)"); + fline("call check_err(iret)"); +} + + +/* + * Output a C statement. + */ +void +cline( + const char *stmnt) +{ + FILE *cout = stdout; + + fputs(stmnt, cout); + fputs("\n", cout); +} + +/* + * From a long line FORTRAN statment, generates the necessary FORTRAN + * lines with continuation characters in column 6. If stmnt starts with "*", + * it is treated as a one-line comment. Statement labels are *not* handled, + * but since we don't generate any labels, we don't care. + */ +void +fline( + const char *stmnt) +{ + FILE *fout = stdout; + int len = (int) strlen(stmnt); + int line = 0; + static char cont[] = { /* continuation characters */ + ' ', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + if(stmnt[0] == '*') { + fputs(stmnt, fout); + fputs("\n", fout); + return; + } + + while (len > 0) { + if (line >= FORT_MAX_LINES) + derror("FORTRAN statement too long: %s",stmnt); + (void) fprintf(fout, " %c", cont[line++]); + (void) fprintf(fout, "%.66s\n", stmnt); + len -= 66; + if (len > 0) + stmnt += 66; + } +} + + +/* return C name for netCDF type, given type code */ +const char * +nctype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "NC_BYTE"; + case NC_CHAR: + return "NC_CHAR"; + case NC_SHORT: + return "NC_SHORT"; + case NC_INT: + return "NC_INT"; + case NC_FLOAT: + return "NC_FLOAT"; + case NC_DOUBLE: + return "NC_DOUBLE"; + default: + derror("nctype: bad type code"); + return 0; + } +} + + +/* + * Return C type name for netCDF type, given type code. + */ +const char * +ncctype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "signed char"; + case NC_CHAR: + return "char"; + case NC_SHORT: + return "short"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "float"; + case NC_DOUBLE: + return "double"; + default: + derror("ncctype: bad type code"); + return 0; + } +} + + + +/* + * Return C type name for netCDF type suffix, given type code. + */ +const char * +ncstype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "schar"; + case NC_CHAR: + return "text"; + case NC_SHORT: + return "short"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "float"; + case NC_DOUBLE: + return "double"; + default: + derror("ncstype: bad type code"); + return 0; + } +} + + +/* + * Return C type name for netCDF attribute container type, given type code. + */ +const char * +ncatype( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return "int"; /* avoids choosing between uchar and schar */ + case NC_CHAR: + return "text"; + case NC_SHORT: + return "short"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "float"; + case NC_DOUBLE: + return "double"; + default: + derror("ncatype: bad type code"); + return 0; + } +} + + +/* return internal size for values of specified netCDF type */ +size_t +nctypesize( + ncmpi_type type) /* netCDF type code */ +{ + switch (type) { + case NC_BYTE: + return sizeof(char); + case NC_CHAR: + return sizeof(char); + case NC_SHORT: + return sizeof(short); + case NC_INT: + return sizeof(int); + case NC_FLOAT: + return sizeof(float); + case NC_DOUBLE: + return sizeof(double); + default: + derror("nctypesize: bad type code"); + return 0; + } +} + + +/* + * Given a netcdf numeric type, a pointer to a vector of values of that + * type, and the index of the vector element desired, returns a pointer + * to a malloced string representing the value in FORTRAN. Since this + * may be used in a DATA statement, it must not include non-constant + * expressions, such as "char(26)". + */ +char * +fstring( + ncmpi_type type, /* netCDF type code */ + void *valp, /* pointer to vector of values */ + int num) /* element of vector desired */ +{ + static char *cp; + signed char *schp; + short *shortp; + int *intp; + float *floatp; + double *doublep; + + switch (type) { + case NC_BYTE: + cp = (char *) emalloc (10); + schp = (signed char *)valp; + sprintf(cp,"%d", schp[num]); + return cp; + + case NC_SHORT: + cp = (char *) emalloc (10); + shortp = (short *)valp; + (void) sprintf(cp,"%d",* (shortp + num)); + return cp; + + case NC_INT: + cp = (char *) emalloc (20); + intp = (int *)valp; + (void) sprintf(cp,"%d",* (intp + num)); + return cp; + + case NC_FLOAT: + cp = (char *) emalloc (20); + floatp = (float *)valp; + (void) sprintf(cp,"%.8g",* (floatp + num)); + return cp; + + case NC_DOUBLE: + cp = (char *) emalloc (25); + doublep = (double *)valp; + (void) sprintf(cp,"%.16g",* (doublep + num)); + expe2d(cp); /* change 'e' to 'd' in exponent */ + return cp; + + default: + derror("fstring: bad type code"); + return 0; + } +} + + +/* + * Given a pointer to a counted string, returns a pointer to a malloced string + * representing the string as a C constant. + */ +char * +cstrstr( + const char *valp, /* pointer to vector of characters*/ + size_t len) /* number of characters in valp */ +{ + static char *sp; + char *cp; + char *istr, *istr0; /* for null-terminated copy */ + int ii; + + if(4*len+3 != (unsigned)(4*len+3)) { + derror("too much character data!"); + exit(9); + } + sp = cp = (char *) emalloc(4*len+3); + + if(len == 1 && *valp == 0) { /* empty string */ + strcpy(sp,"\"\""); + return sp; + } + + istr0 = istr = (char *) emalloc(len + 1); + for(ii = 0; ii < len; ii++) { + istr[ii] = valp[ii]; + } + istr[len] = '\0'; + + *cp++ = '"'; + for(ii = 0; ii < len; ii++) { + switch (*istr) { + case '\0': *cp++ = '\\'; *cp++ = '0'; *cp++ = '0'; *cp++ = '0'; break; + case '\b': *cp++ = '\\'; *cp++ = 'b'; break; + case '\f': *cp++ = '\\'; *cp++ = 'f'; break; + case '\n': *cp++ = '\\'; *cp++ = 'n'; break; + case '\r': *cp++ = '\\'; *cp++ = 'r'; break; + case '\t': *cp++ = '\\'; *cp++ = 't'; break; + case '\v': *cp++ = '\\'; *cp++ = 'v'; break; + case '\\': *cp++ = '\\'; *cp++ = '\\'; break; + case '\"': *cp++ = '\\'; *cp++ = '\"'; break; + default: + if (!isprint(*istr)) { + static char octs[] = "01234567"; + int rem = ((unsigned char)*istr)%64; + *cp++ = '\\'; + *cp++ = octs[((unsigned char)*istr)/64]; /* to get, e.g. '\177' */ + *cp++ = octs[rem/8]; + *cp++ = octs[rem%8]; + } else { + *cp++ = *istr; + } + break; + } + istr++; + } + *cp++ = '"'; + *cp = '\0'; + free(istr0); + return sp; +} + + +/* Given a pointer to a counted string (not necessarily + * null-terminated), returns a pointer to a malloced string representing + * the string as a FORTRAN string expression. For example, the string + * "don't" would yield the FORTRAN string "'don''t'", and the string + * "ab\ncd" would yield "'ab'//char(10)//'cd'". The common + * interpretation of "\"-escaped characters is non-standard, so the + * generated Fortran may require adjustment in compilers that don't + * recognize "\" as anything special in a character context. */ +char * +fstrstr( + const char *str, /* pointer to vector of characters */ + size_t ilen) /* number of characters in istr */ +{ + static char *ostr; + char *cp, tstr[12]; + int was_print = 0; /* true if last character was printable */ + char *istr, *istr0; /* for null-terminated copy */ + int ii; + + if(12*ilen != (size_t)(12*ilen)) { + derror("too much character data!"); + exit(9); + } + istr0 = istr = (char *) emalloc(ilen + 1); + for(ii = 0; ii < ilen; ii++) { + istr[ii] = str[ii]; + } + istr[ilen] = '\0'; + + if (*istr == '\0') { /* empty string input, not legal in FORTRAN */ + ostr = (char*) emalloc(strlen("char(0)") + 1); + strcpy(ostr, "char(0)"); + free(istr0); + return ostr; + } + ostr = cp = (char *) emalloc(12*ilen); + *ostr = '\0'; + if (isprint(*istr)) { /* handle first character in input */ + *cp++ = '\''; + switch (*istr) { + case '\'': + *cp++ = '\''; + *cp++ = '\''; + break; + case '\\': + *cp++ = '\\'; + *cp++ = '\\'; + break; + default: + *cp++ = *istr; + break; + } + *cp = '\0'; + was_print = 1; + } else { + sprintf(tstr, "char(%d)", (unsigned char)*istr); + strcat(cp, tstr); + cp += strlen(tstr); + was_print = 0; + } + istr++; + + for(ii = 1; ii < ilen; ii++) { /* handle subsequent characters in input */ + if (isprint(*istr)) { + if (! was_print) { + strcat(cp, "//'"); + cp += 3; + } + switch (*istr) { + case '\'': + *cp++ = '\''; + *cp++ = '\''; + break; + case '\\': + *cp++ = '\\'; + *cp++ = '\\'; + break; + default: + *cp++ = *istr; + break; + } + *cp = '\0'; + was_print = 1; + } else { + if (was_print) { + *cp++ = '\''; + *cp = '\0'; + } + sprintf(tstr, "//char(%d)", (unsigned char)*istr); + strcat(cp, tstr); + cp += strlen(tstr); + was_print = 0; + } + istr++; + } + if (was_print) + *cp++ = '\''; + *cp = '\0'; + free(istr0); + return ostr; +} + + +static void +cl_netcdf(void) +{ + int stat = ncmpi_close(ncid); + check_err(stat); +} + + +static void +cl_c(void) +{ + cline(" stat = ncmpi_close(ncid);"); + cline(" check_err(stat,__LINE__,__FILE__);"); + cline(" MPI_Finalize();"); +#ifndef vms + cline(" return 0;"); +#else + cline(" return 1;"); +#endif + cline("}"); +} + +/* Returns true if dimension used in at least one record variable, + otherwise false. This is an inefficient algorithm, but we don't call + it very often ... */ +static int +used_in_rec_var( + int idim /* id of dimension */ + ) { + int ivar; + + for (ivar = 0; ivar < nvars; ivar++) { + if (vars[ivar].ndims > 0 && vars[ivar].dims[0] == rec_dim) { + int jdim; + for (jdim = 0; jdim < vars[ivar].ndims; jdim++) { + if (vars[ivar].dims[jdim] == idim) + return 1; + } + } + } + return 0; +} + + +/* Return name for Fortran fill constant of specified type */ +static const char * +f_fill_name( + ncmpi_type type + ) +{ + switch(type) { + case NC_BYTE: + return "NF_FILL_BYTE"; + case NC_CHAR: + return "NF_FILL_CHAR"; + case NC_SHORT: + return "NF_FILL_SHORT"; + case NC_INT: + return "NF_FILL_INT"; + case NC_FLOAT: + return "NF_FILL_FLOAT"; + case NC_DOUBLE: + return "NF_FILL_DOUBLE"; + default: + derror("f_fill_name: bad type code"); + } + return 0; +} + + +/* Generate Fortran for cleaning up and closing file */ +static void +cl_fortran(void) +{ + int ivar; + int idim; + char stmnt[FORT_MAX_STMNT]; + char s2[FORT_MAX_STMNT]; + char*sp; + int have_rec_var = 0; + + /* do we have any record variables? */ + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + have_rec_var = 1; + break; + } + } + + if (have_rec_var) { + fline(" "); + fline("* Write record variables"); + sprintf(stmnt, "call writerecs(ncid,"); + /* generate parameter list for subroutine to write record vars */ + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + /* if a record variable, include id in parameter list */ + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(s2, "%s_id,", v->lname); + strcat(stmnt, s2); + } + } + sp = strrchr(stmnt, ','); + if(sp != NULL) { + *sp = '\0'; + } + strcat(stmnt, ")"); + fline(stmnt); + } + + fline(" "); + fline("iret = nfmpi_close(ncid)"); + fline("call check_err(iret)"); + fline("end"); + + fline(" "); + + if (have_rec_var) { + sprintf(stmnt, "subroutine writerecs(ncid,"); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(s2, "%s_id,", v->lname); + strcat(stmnt, s2); + } + } + sp = strrchr(stmnt, ','); + if(sp != NULL) { + *sp = '\0'; + } + strcat(stmnt, ")"); + fline(stmnt); + fline(" "); + fline("* netCDF id"); + fline("integer ncid"); + + fline("* variable ids"); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(stmnt, "integer %s_id", v->lname); + fline(stmnt); + } + } + + fline(" "); + fline("include 'pnetcdf.inc'"); + + /* create necessary declarations */ + fline("* error status return"); + fline("integer iret"); + + /* generate integer/parameter declarations for all dimensions + used in record variables, except record dimension. */ + fline(" "); + fline("* netCDF dimension sizes for dimensions used with record variables"); + for (idim = 0; idim < ndims; idim++) { + /* if used in a record variable and not record dimension */ + if (used_in_rec_var(idim) && dims[idim].size != NC_UNLIMITED) { + sprintf(stmnt, "integer %s_len", dims[idim].lname); + fline(stmnt); + sprintf(stmnt, "parameter (%s_len = %lu)", + dims[idim].lname, (unsigned long) dims[idim].size); + fline(stmnt); + } + } + + fline(" "); + fline("* rank (number of dimensions) for each variable"); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(stmnt, "integer %s_rank", v->lname); + fline(stmnt); + } + } + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(stmnt, "parameter (%s_rank = %d)", v->lname, + v->ndims); + fline(stmnt); + } + } + + fline("* starts and counts for array sections of record variables"); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + sprintf(stmnt, + "integer %s_start(%s_rank), %s_count(%s_rank)", + v->lname, v->lname, v->lname, v->lname); + fline(stmnt); + } + } + + fline(" "); + fline("* data variables"); + + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + if (v->ndims > 0 && v->dims[0] == rec_dim) { + fline(" "); + sprintf(stmnt, "integer %s_nr", v->lname); + fline(stmnt); + if (v->nrecs > 0) { + sprintf(stmnt, "parameter (%s_nr = %lu)", + v->lname, (unsigned long) v->nrecs); + } else { + sprintf(stmnt, "parameter (%s_nr = 1)", + v->lname); + } + fline(stmnt); + if (v->type != NC_CHAR) { + char *sp; + sprintf(stmnt, "%s %s(", ncftype(v->type), + v->lname); + /* reverse dimensions for FORTRAN */ + for (idim = v->ndims-1; idim >= 0; idim--) { + if(v->dims[idim] == rec_dim) { + sprintf(s2, "%s_nr, ", v->lname); + } else { + sprintf(s2, "%s_len, ", + dims[v->dims[idim]].lname); + } + strcat(stmnt, s2); + } + sp = strrchr(stmnt, ','); + if(sp != NULL) { + *sp = '\0'; + } + strcat(stmnt, ")"); + fline(stmnt); + } + } + } + + fline(" "); + + /* Emit DATA statements after declarations, because f2c on Linux can't + handle interspersing them */ + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + + if (v->ndims > 0 && v->dims[0] == rec_dim && v->type != NC_CHAR) { + if (v->has_data) { + fline(v->data_stmnt); + } else { /* generate data statement for FILL record */ + size_t rec_len = 1; + for (idim = 1; idim < v->ndims; idim++) { + rec_len *= dims[v->dims[idim]].size; + } + sprintf(stmnt,"data %s /%lu * %s/", v->lname, + (unsigned long) rec_len, + f_fill_name(v->type)); + fline(stmnt); + } + } + } + fline(" "); + for (ivar = 0; ivar < nvars; ivar++) { + struct vars *v = &vars[ivar]; + /* if a record variable, declare starts and counts */ + if (v->ndims > 0 && v->dims[0] == rec_dim) { + if (!v->has_data) + continue; + sprintf(stmnt, "* store %s", v->name); + fline(stmnt); + + for (idim = 0; idim < v->ndims; idim++) { + sprintf(stmnt, "%s_start(%d) = 1", v->lname, idim+1); + fline(stmnt); + } + for (idim = v->ndims-1; idim > 0; idim--) { + sprintf(stmnt, "%s_count(%d) = %s_len", v->lname, + v->ndims - idim, dims[v->dims[idim]].lname); + fline(stmnt); + } + sprintf(stmnt, "%s_count(%d) = %s_nr", v->lname, + v->ndims, v->lname); + fline(stmnt); + + if (v->type != NC_CHAR) { + sprintf(stmnt, + "iret = nfmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s)", + nfftype(v->type), v->lname, v->lname, v->lname, v->lname); + } else { + sprintf(stmnt, + "iret = nfmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s)", + nfftype(v->type), v->lname, v->lname, v->lname, + v->data_stmnt); + } + + fline(stmnt); + fline("call check_err(iret)"); + } + } + + fline(" "); + + fline("end"); + + fline(" "); + } + + fline("subroutine check_err(iret)"); + fline("integer iret"); + fline("include 'pnetcdf.inc'"); + fline("if (iret .ne. NF_NOERR) then"); + fline("print *, nfmpi_strerror(iret)"); + fline("stop"); + fline("endif"); + fline("end"); +} + + +/* invoke netcdf calls (or generate C or Fortran code) to create netcdf + * from in-memory structure. */ +void +define_netcdf( + char *netcdfname) +{ + char *filename; /* output file name */ + + if (netcdf_name) { /* name given on command line */ + filename = netcdf_name; + } else { /* construct name from CDL name */ + filename = (char *) emalloc(strlen(netcdfname) + 5); + (void) strcpy(filename,netcdfname); + if (netcdf_flag == -1) + (void) strcat(filename,".cdf"); /* old, deprecated extension */ + else + (void) strcat(filename,".nc"); /* new, favored extension */ + } + if (netcdf_flag) + gen_netcdf(filename); /* create netcdf */ + if (c_flag) /* create C code to create netcdf */ + gen_c(filename); + if (fortran_flag) /* create Fortran code to create netcdf */ + gen_fortran(filename); + free(filename); +} + + +void +close_netcdf(void) +{ + if (netcdf_flag) + cl_netcdf(); /* close netcdf */ + if (c_flag) /* create C code to close netcdf */ + cl_c(); + if (fortran_flag) /* create Fortran code to close netcdf */ + cl_fortran(); +} + + +void +check_err(int stat) { + if (stat != NC_NOERR) { + fprintf(stderr, "ncgen: %s\n", ncmpi_strerror(stat)); + derror_count++; + } +} + +/* + * For logging error conditions. + */ +#ifndef NO_STDARG +void +derror(const char *fmt, ...) +#else +/*VARARGS1*/ +void +derror(fmt, va_alist) + const char *fmt ; /* error-message printf-style format */ + va_dcl /* variable number of error args, if any */ +#endif /* !NO_STDARG */ +{ + va_list args ; + + + if (lineno == 1) + (void) fprintf(stderr,"%s: %s: ", progname, cdlname); + else + (void) fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lineno); + +#ifndef NO_STDARG + va_start(args ,fmt) ; +#else + va_start(args) ; +#endif /* !NO_STDARG */ + + (void) vfprintf(stderr,fmt,args) ; + va_end(args) ; + + (void) fputc('\n',stderr) ; + (void) fflush(stderr); /* to ensure log files are current */ + derror_count++; +} + + +void * +emalloc ( /* check return from malloc */ + size_t size) +{ + void *p; + + p = (void *) malloc (size); + if (p == 0) { + derror ("out of memory\n"); + exit(3); + } + return p; +} + +void * +ecalloc ( /* check return from calloc */ + size_t size) +{ + void *p; + + p = (void *) calloc (size, 1); + if (p == 0) { + derror ("out of memory\n"); + exit(3); + } + return p; +} + +void * +erealloc ( /* check return from realloc */ + void *ptr, + size_t size) /* if 0, this is really a free */ +{ + void *p; + + p = (void *) realloc (ptr, size); + + if (p == 0 && size != 0) { + derror ("out of memory"); + exit(3); + } + return p; +} + + +/* + * For generated Fortran, change 'e' to 'd' in exponent of double precision + * constants. + */ +void +expe2d( + char *cp) /* string containing double constant */ +{ + char *expchar = strrchr(cp,'e'); + if (expchar) { + *expchar = 'd'; + } +} + + + +/* Returns non-zero if n is a power of 2, 0 otherwise */ +static +int +pow2( + int n) +{ + int m = n; + int p = 1; + + while (m > 0) { + m /= 2; + p *= 2; + } + return p == 2*n; +} + + +/* + * Grow an integer array as necessary. + * + * Assumption: nar never incremented by more than 1 from last call. + * + * Makes sure an array is within a factor of 2 of the size needed. + * + * Make sure *arpp points to enough space to hold nar integers. If not big + * enough, malloc more space, copy over existing stuff, free old. When + * called for first time, *arpp assumed to be uninitialized. + */ +void +grow_iarray( + int nar, /* array must be at least this big */ + int **arpp) /* address of start of int array */ +{ + if (nar == 0) { + *arpp = (int *) emalloc(1 * sizeof(int)); + return; + } + if (! pow2(nar)) /* return unless nar is a power of two */ + return; + *arpp = (int *) erealloc(*arpp, 2 * nar * sizeof(int)); +} + + +/* + * Grow an array of variables as necessary. + * + * Assumption: nar never incremented by more than 1 from last call. + * + * Makes sure array is within a factor of 2 of the size needed. + * + * Make sure *arpp points to enough space to hold nar variables. If not big + * enough, malloc more space, copy over existing stuff, free old. When + * called for first time, *arpp assumed to be uninitialized. + */ +void +grow_varray( + int nar, /* array must be at least this big */ + struct vars **arpp) /* address of start of var array */ +{ + if (nar == 0) { + *arpp = (struct vars *) emalloc(1 * sizeof(struct vars)); + return; + } + if (! pow2(nar)) /* return unless nar is a power of two */ + return; + *arpp = (struct vars *) erealloc(*arpp, 2 * nar * sizeof(struct vars)); +} + + +/* + * Grow an array of dimensions as necessary. + * + * Assumption: nar never incremented by more than 1 from last call. + * + * Makes sure array is within a factor of 2 of the size needed. + * + * Make sure *arpp points to enough space to hold nar dimensions. If not big + * enough, malloc more space, copy over existing stuff, free old. When + * called for first time, *arpp assumed to be uninitialized. + */ +void +grow_darray( + int nar, /* array must be at least this big */ + struct dims **arpp) /* address of start of var array */ +{ + if (nar == 0) { + *arpp = (struct dims *) emalloc(1 * sizeof(struct dims)); + return; + } + if (! pow2(nar)) /* return unless nar is a power of two */ + return; + *arpp = (struct dims *) erealloc(*arpp, 2 * nar * sizeof(struct dims)); +} + + +/* + * Grow an array of attributes as necessary. + * + * Assumption: nar never incremented by more than 1 from last call. + * + * Makes sure array is within a factor of 2 of the size needed. + * + * Make sure *arpp points to enough space to hold nar attributes. If not big + * enough, malloc more space, copy over existing stuff, free old. When + * called for first time, *arpp assumed to be uninitialized. + */ +void +grow_aarray( + int nar, /* array must be at least this big */ + struct atts **arpp) /* address of start of var array */ +{ + if (nar == 0) { + *arpp = (struct atts *) emalloc(1 * sizeof(struct atts)); + return; + } + if (! pow2(nar)) /* return unless nar is a power of two */ + return; + *arpp = (struct atts *) erealloc(*arpp, 2 * nar * sizeof(struct atts)); +} + + +/* + * Replace dashes and dots in name so it can be used in C and + * Fortran without causing syntax errors. Here we just replace each "-" + * in a name with "_dash_" and each "." with "_dot_", though any + * similar replacement that doesn't clash with existing names would + * work. + */ +extern char* +decodify ( + const char *name) +{ + int count=0; /* number of minus signs in name */ + char *newname; + const char *cp = name; + char *sp; + + while(*cp != '\0') { + switch (*cp) { + case '-': + count += strlen("_dash_") - 1; + break; + case '.': + count += strlen("_dot_") - 1; + break; + case '@': + count += strlen("_at_") - 1; + break; + case '#': + count += strlen("_hash_") - 1; + break; + case '[': + count += strlen("_lbr_") - 1; + break; + case ']': + count += strlen("_rbr_") - 1; + break; + default: + break; + } + cp++; + } + newname = (char *) ecalloc(strlen(name) + count + 1); + cp = name; + sp = newname; + while(*cp != '\0') { + switch (*cp) { + case '-': + strcat(sp, "_dash_"); + sp += strlen("_dash_"); + break; + case '.': + strcat(sp, "_dot_"); + sp += strlen("_dot_"); + break; + case '@': + strcat(sp, "_at_"); + sp += strlen("_at_"); + break; + case '#': + strcat(sp, "_hash_"); + sp += strlen("_hash_"); + break; + case '[': + strcat(sp, "_lbr_"); + sp += strlen("_lbr_"); + break; + case ']': + strcat(sp, "_rbr_"); + sp += strlen("_rbr_"); + break; + default: + *sp++ = *cp; + break; + } + cp++; + } + *sp = '\0'; + return newname; +} Index: /tags/v1-0-3/src/utils/ncgen/ncgen.y =================================================================== --- /tags/v1-0-3/src/utils/ncgen/ncgen.y (revision 583) +++ /tags/v1-0-3/src/utils/ncgen/ncgen.y (revision 583) @@ -0,0 +1,883 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +/* yacc source for "ncgen", a netCDL parser and netCDF generator */ +/* there is a shift-reduce conflict in this definition but does not appear to + * be critical */ +%expect 1 + +%{ +#ifndef lint +static char SccsId[] = "$Id$"; +#endif +#include +#include +#include +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" /* for grow_darray() et al */ + +typedef struct Symbol { /* symbol table entry */ + char *name; + struct Symbol *next; + unsigned is_dim : 1; /* appears as netCDF dimension */ + unsigned is_var : 1; /* appears as netCDF variable */ + unsigned is_att : 1; /* appears as netCDF attribute */ + int dnum; /* handle as a dimension */ + int vnum; /* handle as a variable */ + } *YYSTYPE1; + +/* True if string a equals string b*/ +#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) +#define NC_UNSPECIFIED ((nc_type)0) /* unspecified (as yet) type */ + +#define YYSTYPE YYSTYPE1 +YYSTYPE symlist; /* symbol table: linked list */ + +extern int derror_count; /* counts errors in netcdf definition */ +extern int lineno; /* line number for error messages */ + +static int not_a_string; /* whether last constant read was a string */ +static char termstring[MAXTRST]; /* last terminal string read */ +static double double_val; /* last double value read */ +static float float_val; /* last float value read */ +static int int_val; /* last int value read */ +static short short_val; /* last short value read */ +static char char_val; /* last char value read */ +static signed char byte_val; /* last byte value read */ + +static nc_type type_code; /* holds declared type for variables */ +static nc_type atype_code; /* holds derived type for attributes */ +static char *netcdfname; /* to construct netcdf file name */ +static void *att_space; /* pointer to block for attribute values */ +static nc_type valtype; /* type code for list of attribute values */ + +static char *char_valp; /* pointers used to accumulate data values */ +static signed char *byte_valp; +static short *short_valp; +static int *int_valp; +static float *float_valp; +static double *double_valp; +static void *rec_cur; /* pointer to where next data value goes */ +static void *rec_start; /* start of space for data */ + +/* function prototypes */ +#ifdef vms +void +#else +int +#endif +yyerror( char *s); +int yylex(void); +%} + +/* DECLARATIONS */ + +%token + NC_UNLIMITED_K /* keyword for unbounded record dimension */ + BYTE_K /* keyword for byte datatype */ + CHAR_K /* keyword for char datatype */ + SHORT_K /* keyword for short datatype */ + INT_K /* keyword for int datatype */ + FLOAT_K /* keyword for float datatype */ + DOUBLE_K /* keyword for double datatype */ + IDENT /* name for a dimension, variable, or attribute */ + TERMSTRING /* terminal string */ + BYTE_CONST /* byte constant */ + CHAR_CONST /* char constant */ + SHORT_CONST /* short constant */ + INT_CONST /* int constant */ + FLOAT_CONST /* float constant */ + DOUBLE_CONST /* double constant */ + DIMENSIONS /* keyword starting dimensions section, if any */ + VARIABLES /* keyword starting variables section, if any */ + NETCDF /* keyword declaring netcdf name */ + DATA /* keyword starting data section, if any */ + FILLVALUE /* fill value, from _FillValue attribute or default */ + +%start ncdesc /* start symbol for grammar */ + +%% + +/* RULES */ + +ncdesc: NETCDF + '{' + { init_netcdf(); } + dimsection /* dimension declarations */ + vasection /* variable and attribute declarations */ + { + if (derror_count == 0) + define_netcdf(netcdfname); + if (derror_count > 0) + exit(6); + } + datasection /* data, variables loaded as encountered */ + '}' + { + if (derror_count == 0) + close_netcdf(); + } + ; +dimsection: /* empty */ + | DIMENSIONS dimdecls + ; +dimdecls: dimdecline ';' + | dimdecls dimdecline ';' + ; +dimdecline: dimdecl + | dimdecline ',' dimdecl + ; +dimdecl: dimd '=' INT_CONST + { if (int_val <= 0) + derror("dimension length must be positive"); + dims[ndims].size = int_val; + ndims++; + } + | dimd '=' DOUBLE_CONST + { /* for rare case where 2^31 < dimsize < 2^32 */ + if (double_val <= 0) + derror("dimension length must be positive"); + if (double_val > 4294967295.0) + derror("dimension too large"); + if (double_val - (size_t) double_val > 0) + derror("dimension length must be an integer"); + dims[ndims].size = (size_t) double_val; + ndims++; + } + | dimd '=' NC_UNLIMITED_K + { if (rec_dim != -1) + derror("only one NC_UNLIMITED dimension allowed"); + rec_dim = ndims; /* the unlimited (record) dimension */ + dims[ndims].size = NC_UNLIMITED; + ndims++; + } + ; +dimd: dim + { if ($1->is_dim == 1) { + derror( "duplicate dimension declaration for %s", + $1->name); + } + $1->is_dim = 1; + $1->dnum = ndims; + /* make sure dims array will hold dimensions */ + grow_darray(ndims, /* must hold ndims+1 dims */ + &dims); /* grow as needed */ + dims[ndims].name = (char *) emalloc(strlen($1->name)+1); + (void) strcpy(dims[ndims].name, $1->name); + /* name for use in generated Fortran and C variables */ + dims[ndims].lname = decodify($1->name); + } + ; +dim: IDENT + ; +vasection: /* empty */ + | VARIABLES vadecls + | gattdecls + ; +vadecls: vadecl ';' + | vadecls vadecl ';' + ; +vadecl: vardecl | attdecl + ; +gattdecls: gattdecl ';' + | gattdecls gattdecl ';' + ; +gattdecl: attdecl /* causes a shift/reduce conflict */ + ; +vardecl: type varlist + ; +type: BYTE_K { type_code = NC_BYTE; } + | CHAR_K { type_code = NC_CHAR; } + | SHORT_K { type_code = NC_SHORT; } + | INT_K { type_code = NC_INT; } + | FLOAT_K { type_code = NC_FLOAT; } + | DOUBLE_K{ type_code = NC_DOUBLE; } + ; +varlist: varspec + | varlist ',' varspec + ; +varspec: var + { + static struct vars dummyvar; + + dummyvar.name = "dummy"; + dummyvar.type = NC_DOUBLE; + dummyvar.ndims = 0; + dummyvar.dims = 0; + dummyvar.fill_value.doublev = NC_FILL_DOUBLE; + dummyvar.has_data = 0; + + nvdims = 0; + /* make sure variable not re-declared */ + if ($1->is_var == 1) { + derror( "duplicate variable declaration for %s", + $1->name); + } + $1->is_var = 1; + $1->vnum = nvars; + /* make sure vars array will hold variables */ + grow_varray(nvars, /* must hold nvars+1 vars */ + &vars); /* grow as needed */ + vars[nvars] = dummyvar; /* to make Purify happy */ + vars[nvars].name = (char *) emalloc(strlen($1->name)+1); + (void) strcpy(vars[nvars].name, $1->name); + /* name for use in generated Fortran and C variables */ + vars[nvars].lname = decodify($1->name); + vars[nvars].type = type_code; + /* set default fill value. You can override this with + * the variable attribute "_FillValue". */ + nc_getfill(type_code, &vars[nvars].fill_value); + vars[nvars].has_data = 0; /* has no data (yet) */ + } + dimspec + { + vars[nvars].ndims = nvdims; + nvars++; + } + ; +var: IDENT + ; +dimspec: /* empty */ + | '(' dimlist ')' + ; +dimlist: vdim + | dimlist ',' vdim + ; +vdim: dim + { + if (nvdims >= NC_MAX_VAR_DIMS) { + derror("%s has too many dimensions",vars[nvars].name); + } + if ($1->is_dim == 1) + dimnum = $1->dnum; + else { + derror( "%s is not declared as a dimension", + $1->name); + dimnum = ndims; + } + if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) { + derror("unlimited dimension must be first"); + } + grow_iarray(nvdims, /* must hold nvdims+1 ints */ + &vars[nvars].dims); /* grow as needed */ + vars[nvars].dims[nvdims] = dimnum; + nvdims++; + } + ; +attdecl: att + { + valnum = 0; + valtype = NC_UNSPECIFIED; + /* get a large block for attributes, realloc later */ + att_space = emalloc(MAX_NC_ATTSIZE); + /* make all kinds of pointers point to it */ + char_valp = (char *) att_space; + byte_valp = (signed char *) att_space; + short_valp = (short *) att_space; + int_valp = (int *) att_space; + float_valp = (float *) att_space; + double_valp = (double *) att_space; + } + '=' attvallist + { + { /* check if duplicate attribute for this var */ + int i; + for(i=0; iis_var == 1) + varnum = $1->vnum; + else { + derror("%s not declared as a variable, fatal error", + $1->name); + YYABORT; + } + } + ; +attr: IDENT + { + /* make sure atts array will hold attributes */ + grow_aarray(natts, /* must hold natts+1 atts */ + &atts); /* grow as needed */ + atts[natts].name = (char *) emalloc(strlen($1->name)+1); + (void) strcpy(atts[natts].name,$1->name); + /* name for use in generated Fortran and C variables */ + atts[natts].lname = decodify($1->name); + } + ; +attvallist: aconst + | attvallist ',' aconst + ; +aconst: attconst + { + if (valtype == NC_UNSPECIFIED) + valtype = atype_code; + if (valtype != atype_code) + derror("values for attribute must be all of same type"); + } + ; + +attconst: CHAR_CONST + { + atype_code = NC_CHAR; + *char_valp++ = char_val; + valnum++; + } + | TERMSTRING + { + atype_code = NC_CHAR; + { + /* don't null-terminate attribute strings */ + size_t len = strlen(termstring); + if (len == 0) /* need null if that's only value */ + len = 1; + (void)strncpy(char_valp,termstring,len); + valnum += len; + char_valp += len; + } + } + | BYTE_CONST + { + atype_code = NC_BYTE; + *byte_valp++ = byte_val; + valnum++; + } + | SHORT_CONST + { + atype_code = NC_SHORT; + *short_valp++ = short_val; + valnum++; + } + | INT_CONST + { + atype_code = NC_INT; + *int_valp++ = int_val; + valnum++; + } + | FLOAT_CONST + { + atype_code = NC_FLOAT; + *float_valp++ = float_val; + valnum++; + } + | DOUBLE_CONST + { + atype_code = NC_DOUBLE; + *double_valp++ = double_val; + valnum++; + } + ; + +datasection: /* empty */ + | DATA datadecls + | DATA + ; + +datadecls: datadecl ';' + | datadecls datadecl ';' + ; +datadecl: avar + { + valtype = vars[varnum].type; /* variable type */ + valnum = 0; /* values accumulated for variable */ + vars[varnum].has_data = 1; + /* compute dimensions product */ + var_size = nctypesize(valtype); + if (vars[varnum].ndims == 0) { /* scalar */ + var_len = 1; + } else if (vars[varnum].dims[0] == rec_dim) { + var_len = 1; /* one record for unlimited vars */ + } else { + var_len = dims[vars[varnum].dims[0]].size; + } + for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++) + var_len = var_len*dims[vars[varnum].dims[dimnum]].size; + /* allocate memory for variable data */ + if (var_len*var_size != (size_t)(var_len*var_size)) { + derror("variable %s too large for memory", + vars[varnum].name); + exit(9); + } + rec_len = var_len; + rec_start = malloc ((size_t)(rec_len*var_size)); + if (rec_start == 0) { + derror ("out of memory\n"); + exit(3); + } + rec_cur = rec_start; + switch (valtype) { + case NC_CHAR: + char_valp = (char *) rec_start; + break; + case NC_BYTE: + byte_valp = (signed char *) rec_start; + break; + case NC_SHORT: + short_valp = (short *) rec_start; + break; + case NC_INT: + int_valp = (int *) rec_start; + break; + case NC_FLOAT: + float_valp = (float *) rec_start; + break; + case NC_DOUBLE: + double_valp = (double *) rec_start; + break; + default: + derror("Unhandled type %d\n", valtype); + break; + + } + } + '=' constlist + { + if (valnum < var_len) { /* leftovers */ + nc_fill(valtype, + var_len - valnum, + rec_cur, + vars[varnum].fill_value); + } + /* put out var_len values */ + /* vars[varnum].nrecs = valnum / rec_len; */ + vars[varnum].nrecs = var_len / rec_len; + if (derror_count == 0) + put_variable(rec_start); + free ((char *) rec_start); + } + ; +constlist: dconst + | constlist ',' dconst + ; +dconst: + { + if(valnum >= var_len) { + if (vars[varnum].dims[0] != rec_dim) { /* not recvar */ + derror("too many values for this variable, %d >= %d", + valnum, var_len); + exit (4); + } else { /* a record variable, so grow data + container and increment var_len by + multiple of record size */ + ptrdiff_t rec_inc = (char *)rec_cur + - (char *)rec_start; + var_len += rec_len * (1 + valnum )/rec_len; + rec_start = erealloc(rec_start, var_len*var_size); + rec_cur = (char *)rec_start + rec_inc; + char_valp = (char *) rec_cur; + byte_valp = (signed char *) rec_cur; + short_valp = (short *) rec_cur; + int_valp = (int *) rec_cur; + float_valp = (float *) rec_cur; + double_valp = (double *) rec_cur; + } + } + not_a_string = 1; + } + const + { + if (not_a_string) { + switch (valtype) { + case NC_CHAR: + rec_cur = (void *) char_valp; + break; + case NC_BYTE: + rec_cur = (void *) byte_valp; + break; + case NC_SHORT: + rec_cur = (void *) short_valp; + break; + case NC_INT: + rec_cur = (void *) int_valp; + break; + case NC_FLOAT: + rec_cur = (void *) float_valp; + break; + case NC_DOUBLE: + rec_cur = (void *) double_valp; + break; + default: + derror("Unhandled type %d\n", valtype); + break; + } + } + } +; + +const: CHAR_CONST + { + atype_code = NC_CHAR; + switch (valtype) { + case NC_CHAR: + *char_valp++ = char_val; + break; + case NC_BYTE: + *byte_valp++ = char_val; + break; + case NC_SHORT: + *short_valp++ = char_val; + break; + case NC_INT: + *int_valp++ = char_val; + break; + case NC_FLOAT: + *float_valp++ = char_val; + break; + case NC_DOUBLE: + *double_valp++ = char_val; + break; + default: + derror("Unhandled type %d\n", valtype); + break; + } + valnum++; + } + | TERMSTRING + { + not_a_string = 0; + atype_code = NC_CHAR; + { + size_t len = strlen(termstring); + + if(valnum + len > var_len) { + if (vars[varnum].dims[0] != rec_dim) { + derror("too many values for this variable, %d>%d", + valnum+len, var_len); + exit (5); + } else {/* a record variable so grow it */ + ptrdiff_t rec_inc = (char *)rec_cur + - (char *)rec_start; + var_len += rec_len * (len + valnum - var_len)/rec_len; + rec_start = erealloc(rec_start, var_len*var_size); + rec_cur = (char *)rec_start + rec_inc; + char_valp = (char *) rec_cur; + } + } + switch (valtype) { + case NC_CHAR: + { + int ld; + size_t i, sl; + (void)strncpy(char_valp,termstring,len); + + ld = vars[varnum].ndims-1; + if (ld > 0) {/* null-fill to size of last dim */ + sl = dims[vars[varnum].dims[ld]].size; + for (i =len;i next) + if (STREQ(sp -> name, sname)) { + return sp; + } + return 0; /* 0 ==> not found */ +} + +YYSTYPE install( /* install sname in symbol table */ + const char *sname) +{ + YYSTYPE sp; + + sp = (YYSTYPE) emalloc (sizeof (struct Symbol)); + sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */ + (void) strcpy (sp -> name, sname); + sp -> next = symlist; /* put at front of list */ + sp -> is_dim = 0; + sp -> is_var = 0; + sp -> is_att = 0; + symlist = sp; + return sp; +} + +void +clearout(void) /* reset symbol table to empty */ +{ + YYSTYPE sp, tp; + for (sp = symlist; sp != (YYSTYPE) 0;) { + tp = sp -> next; + free (sp -> name); + free ((char *) sp); + sp = tp; + } + symlist = 0; +} + +/* get lexical input routine generated by lex */ +#include "ncgenyy.c" Index: /tags/v1-0-3/src/utils/ncgen/Makefile.in =================================================================== --- /tags/v1-0-3/src/utils/ncgen/Makefile.in (revision 418) +++ /tags/v1-0-3/src/utils/ncgen/Makefile.in (revision 418) @@ -0,0 +1,156 @@ +# Makefile for ncmpigen(1). +# +# $Id$ + +srcdir = @srcdir@ +VPATH = @srcdir@ +INSTALL = @INSTALL@ + +include ../../../macros.make + +NCDUMP = ../ncdump/ncmpidump +PROGRAM = ncmpigen +INCLUDES = -I$(srcdir)/../../../src/lib -I$(srcdir) -I. +MANUAL = ncmpigen.1 +GARBAGE = $(PROGRAM) \ + pnetcdf.inc \ + c0.nc c1.cdl c1.nc c2.cdl \ + f0.nc \ + ctest.c ctest ctest0.nc ctest1.cdl \ + ftest.f ftest ftest0.nc ftest1.cdl + +lib_netcdf = ../../../src/lib/libpnetcdf.a +ld_netcdf = -L../../../src/lib -lpnetcdf + +PACKING_LIST = Makefile.in depend escapes.c generic.h \ + ncgentab.c ncgentab.h \ + genlib.c genlib.h getfill.c init.c load.c \ + main.c ncmpigen.1 ncgen.h ncgen.l ncgen.y c0.cdl + +OBJS = main.o load.o ncgentab.o escapes.o \ + getfill.o init.o genlib.o + +lex = @LEX@ +yacc = @YACC@ + +program_srcs = main.c load.c ncgentab.c escapes.c \ + getfill.c init.c genlib.c + +all: $(PROGRAM) + +# generating the fortran does not work yet +#test: $(PROGRAM) b-test c-test f-test FORCE +test: $(PROGRAM) b-test c-test FORCE + +install: + $(INSTALL) -d -m 755 $(MANDIR)/man1 + $(INSTALL) -m 644 $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL) + + $(INSTALL) -d $(BINDIR) + $(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM) + +uninstall: + -rm -f $(BINDIR)/$(PROGRAM) + -rm -f $(MANDIR)/man1/$(MANUAL) + +$(PROGRAM): $(OBJS) $(lib_netcdf) + $(LINK.c) $(OBJS) $(ld_netcdf) $(LIBS) + +ncgentab.c \ +ncgentab.h: ncgen.y ncgenyy.c ncgen.h + $(yacc) -d $(srcdir)/ncgen.y; \ + mv y.tab.c ncgentab.c; \ + mv y.tab.h ncgentab.h + +ncgenyy.c: ncgen.l + $(lex) $(srcdir)/ncgen.l; \ + mv lex.yy.c ncgenyy.c + +vmstab.h \ +vmstab.c: ncgen.y + @echo 1>&2 "$@ is out-of-date with respect to $?" + @echo 1>&2 "It must be recreated via POSIX yacc(1) on a VMS system" + false +vms_yy.c: ncgenyy.c + @echo 1>&2 "$@ is out-of-date with respect to $?" + @echo 1>&2 "It must be recreated via POSIX lex(1) on a VMS system" + false + +# +# test "-b" option of ncgen +# +b-test: $(PROGRAM) c1.cdl + @./$(PROGRAM) -b c1.cdl && \ + $(NCDUMP) `pwd`/c1.nc > c2.cdl + @if diff c1.cdl c2.cdl; then \ + echo "*** $(PROGRAM) -b test successful ***"; \ + else \ + echo "*** $(PROGRAM) -b test failed ***"; \ + exit 1; \ + fi + +# +# test "-c" option of ncgen +# +c-test: $(PROGRAM) c1.cdl + ./$(PROGRAM) -c -o ctest0.nc $(srcdir)/c0.cdl > ctest.c && \ + $(CC) -o ctest $(CFLAGS) $(LDFLAGS) $(CPPFLAGS) ctest.c $(ld_netcdf) $(LIBS) && \ + ./ctest && \ + $(NCDUMP) -n c1 `pwd`/ctest0.nc > ctest1.cdl + @if diff c1.cdl ctest1.cdl; then \ + echo "*** $(PROGRAM) -c test successful ***"; \ + else \ + echo "*** $(PROGRAM) -c test failed ***"; \ + exit 1; \ + fi + +c1.cdl: $(PROGRAM) c0.cdl + ./$(PROGRAM) -b -o c0.nc $(srcdir)/c0.cdl + $(NCDUMP) -n c1 `pwd`/c0.nc > $@ + +# +# test "-f" option of ncgen +# +f-test: $(PROGRAM) c0.cdl c1.cdl + @if [ -n "$(FC)" ]; then \ + $(MAKE) $(MFLAGS) ftest1.cdl && \ + if diff c1.cdl ftest1.cdl; then \ + echo "*** $(PROGRAM) -f test successful ***"; \ + else \ + echo "*** $(PROGRAM) -f test failed ***"; \ + exit 1; \ + fi; \ + else \ + echo 1>&2 "\`$@' not made because no FORTRAN compiler"; \ + fi + +ftest1.cdl: $(PROGRAM) c0.cdl pnetcdf.inc + ./$(PROGRAM) -f -o ftest0.nc $(srcdir)/c0.cdl > ftest.f + $(COMPILE.f) ftest.f + $(FC) $(FFLAGS) $(LDFLAGS) -o ftest ftest.o $(ld_netcdf) $(LIBS) + ./ftest + $(NCDUMP) -n c1 ftest0.nc > ftest1.cdl + +pnetcdf.inc: + @if [ -n "$(FC)" ]; then \ + cp $(srcdir)/../../libf/$@ .; \ + else \ + echo 1>&2 "\`$@' not made because no FORTRAN compiler"; \ + fi + +$(PROGRAM)_src : $(program_srcs) + #setopt primary_language C + #load -C $(CPPFLAGS) $(program_srcs) + #load -C $(LIBS) + #load -C /usr/lang/SC2.0.1/libansi.a + #setopt program_name gribtonc + +$(PROGRAM)_obj : $(program_srcs) + #setopt primary_language C + #load -C $(CPPFLAGS) $(OBJS) + #load -C $(LIBS) + #setopt program_name gribtonc + +include $(srcdir)/../../../rules.make + +include $(srcdir)/depend Index: /tags/v1-0-3/src/utils/ncgen/generic.h =================================================================== --- /tags/v1-0-3/src/utils/ncgen/generic.h (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/generic.h (revision 313) @@ -0,0 +1,18 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#ifndef UD_GENERIC_H +#define UD_GENERIC_H + +union generic { /* used to hold any kind of fill_value */ + float floatv; + double doublev; + int intv; + short shortv; + char charv; +}; + +#endif Index: /tags/v1-0-3/src/utils/ncgen/c0.cdl =================================================================== --- /tags/v1-0-3/src/utils/ncgen/c0.cdl (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/c0.cdl (revision 313) @@ -0,0 +1,331 @@ +netcdf c0 { +dimensions: + Dr = UNLIMITED ; // (2 currently) + D1 = 1 ; + D2 = 2 ; + D3 = 3 ; + dim-name-dashes = 4 ; + dim.name.dots = 5 ; +variables: + char c ; + c:att-name-dashes = 4 ; + c:att.name.dots = 5 ; + short s ; + s:b = 0b, 127b, -128b, -1b ; + s:s = -32768s, 0s, 32767s ; + int i ; + i:i = -2147483647, 0, 2147483647 ; + i:f = -1.e+36f, 0.f, 1.e+36f ; + i:d = -1.e+308, 0., 1.e+308 ; + float f ; + f:c = "x" ; + double d ; + d:c = "abcd\tZ$&" ; + char cr(Dr) ; + short sr(Dr) ; + int ir(Dr) ; + float fr(Dr) ; + double dr(Dr) ; + char c1(D1) ; + short s1(D1) ; + int i1(D1) ; + float f1(D1) ; + double d1(D1) ; + char c2(D2) ; + short s2(D2) ; + int i2(D2) ; + float f2(D2) ; + double d2(D2) ; + char c3(D3) ; + short s3(D3) ; + int i3(D3) ; + float f3(D3) ; + double d3(D3) ; + char cr1(Dr, D1) ; + short sr3(Dr, D3) ; + float f11(D1, D1) ; + double d12(D1, D2) ; + char c13(D1, D3) ; + short s21(D2, D1) ; + int i22(D2, D2) ; + float f23(D2, D3) ; + char c31(D3, D1) ; + short s33(D3, D3) ; + short sr11(Dr, D1, D1) ; + int ir12(Dr, D1, D2) ; + float fr13(Dr, D1, D3) ; + char cr21(Dr, D2, D1) ; + short sr23(Dr, D2, D3) ; + float fr31(Dr, D3, D1) ; + double dr32(Dr, D3, D2) ; + char cr33(Dr, D3, D3) ; + char c111(D1, D1, D1) ; + short s113(D1, D1, D3) ; + float f121(D1, D2, D1) ; + double d122(D1, D2, D2) ; + char c123(D1, D2, D3) ; + short s131(D1, D3, D1) ; + int i132(D1, D3, D2) ; + float f133(D1, D3, D3) ; + float f211(D2, D1, D1) ; + double d212(D2, D1, D2) ; + char c213(D2, D1, D3) ; + short s221(D2, D2, D1) ; + int i222(D2, D2, D2) ; + float f223(D2, D2, D3) ; + char c231(D2, D3, D1) ; + short s233(D2, D3, D3) ; + short s311(D3, D1, D1) ; + int i312(D3, D1, D2) ; + float f313(D3, D1, D3) ; + double var-name-dashes ; + double var.name.dots ; + +// global attributes: + :Gc = "" ; + :Gb = -128b, 127b ; + :Gs = -32768s, 0s, 32767s ; + :Gi = -2147483647, 0, 2147483647 ; + :Gf = -1.e+36f, 0.f, 1.e+36f ; + :Gd = -1.e+308, 0., 1.e+308 ; + :Gatt-name-dashes = -1 ; + :Gatt.name.dots = -2 ; +data: + + c = "2" ; + + s = -5 ; + + i = -20 ; + + f = -9 ; + + d = -10 ; + + cr = "ab" ; + + sr = -32768, 32767 ; + + ir = -2147483646, 2147483647 ; + + fr = -1e+36, 1e+36 ; + + dr = -1e+308, 1e+308 ; + + c1 = "" ; + + s1 = -32768 ; + + i1 = -2147483646 ; + + f1 = -1e+36 ; + + d1 = -1e+308 ; + + c2 = "ab" ; + + + s2 = -32768, 32767 ; + + i2 = -2147483646, 2147483647 ; + + f2 = -1e+36, 1e+36 ; + + d2 = -1e+308, 1e+308 ; + + c3 = "\001\300." ; + + s3 = -32768, 0, 32767 ; + + i3 = -2147483646, 0, 2147483647 ; + + f3 = -1e+36, 0, 1e+36 ; + + d3 = -1e+308, 0, 1e+308 ; + + cr1 = + "x", + "y" ; + + sr3 = + -375, -380, -385, + -350, -355, -360 ; + + f11 = + -2187 ; + + d12 = + -3000, -3010 ; + + c13 = + "\tb\177" ; + + s21 = + -375, + -350 ; + + i22 = + -24000, -24020, + -23600, -23620 ; + + f23 = + -2187, -2196, -2205, + -2106, -2115, -2124 ; + + c31 = + "+", + "-", + " " ; + + s33 = + -375, -380, -385, + -350, -355, -360, + -325, -330, -335 ; + + sr11 = + 2500, + 2375 ; + + ir12 = + 640000, 639980, + 632000, 631980 ; + + fr13 = + 26244, 26235, 26226, + 25515, 25506, 25497 ; + + cr21 = + "@", + "D", + "H", + "L" ; + + sr23 = + 2500, 2495, 2490, + 2525, 2520, 2515, + 2375, 2370, 2365, + 2400, 2395, 2390 ; + + fr31 = + 26244, + 26325, + 26406, + 25515, + 25596, + 25677 ; + + dr32 = + 40000, 39990, + 40100, 40090, + 40200, 40190, + 39000, 38990, + 39100, 39090, + 39200, 39190 ; + + cr33 = + "1", + "two", + "3", + "4", + "5", + "six" ; + + c111 = + "@" ; + + s113 = + 2500, 2495, 2490 ; + + f121 = + 26244, + 26325 ; + + d122 = + 40000, 39990, + 40100, 40090 ; + + c123 = + "one", + "2" ; + + s131 = + 2500, + 2525, + 2550 ; + + i132 = + 640000, 639980, + 640400, 640380, + 640800, 640780 ; + + f133 = + 26244, 26235, 26226, + 26325, 26316, 26307, + 26406, 26397, 26388 ; + + f211 = + 26244, + 25515 ; + + d212 = + 40000, 39990, + 39000, 38990 ; + +// The following trips a bug on Cray T3E, but should work on other platforms +// c213 = +// "1", +// "two" ; + + s221 = + 2500, + 2525, + 2375, + 2400 ; + + i222 = + 640000, 639980, + 640400, 640380, + 632000, 631980, + 632400, 632380 ; + + f223 = + 26244, 26235, 26226, + 26325, 26316, 26307, + 25515, 25506, 25497, + 25596, 25587, 25578 ; + + c231 = + "@", + "D", + "H", + "H", + "L", + "P" ; + + s233 = + 2500, 2495, 2490, + 2525, 2520, 2515, + 2550, 2545, 2540, + 2375, 2370, 2365, + 2400, 2395, 2390, + 2425, 2420, 2415 ; + + s311 = + 2500, + 2375, + 2250 ; + + i312 = + 640000, 639980, + 632000, 631980, + 624000, 623980 ; + + f313 = + 26244, 26235, 26226, + 25515, 25506, 25497, + 24786, 24777, 24768 ; + + var-name-dashes = -1 ; + + var.name.dots = -2 ; +} Index: /tags/v1-0-3/src/utils/ncgen/escapes.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/escapes.c (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/escapes.c (revision 313) @@ -0,0 +1,96 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include +#include +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + +/* + * "Expands" valid escape sequences in yystring (read by lex) into the + * apropriate characters in termstring. For example, the two character + * sequence "\t" in yystring would be converted into a single tab character + * in termstring. On return, termstring is properly terminated. + */ + +void +expand_escapes( + char *termstring, /* returned, with escapes expanded */ + char *yytext, + int yyleng) +{ + char *s, *t, *endp; + + yytext[yyleng-1]='\0'; /* don't copy quotes */ + /* expand "\" escapes, e.g. "\t" to tab character */ + s = termstring; + t = yytext+1; + while(*t) { + if (*t == '\\') { + t++; + switch (*t) { + case 'a': + *s++ = '\007'; t++; /* will use '\a' when STDC */ + break; + case 'b': + *s++ = '\b'; t++; + break; + case 'f': + *s++ = '\f'; t++; + break; + case 'n': + *s++ = '\n'; t++; + break; + case 'r': + *s++ = '\r'; t++; + break; + case 't': + *s++ = '\t'; t++; + break; + case 'v': + *s++ = '\v'; t++; + break; + case '\\': + *s++ = '\\'; t++; + break; + case '?': + *s++ = '\177'; t++; + break; + case '\'': + *s++ = '\''; t++; + break; + case '\"': + *s++ = '\"'; t++; + break; + case 'x': + t++; /* now t points to one or more hex digits */ + *s++ = (char) strtol(t, &endp, 16); + t = endp; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + /* t now points to octal digits */ + *s++ = (char) strtol(t, &endp, 8); + t = endp; + break; + default: + *s++ = *t++; + break; + } + } else { + *s++ = *t++; + } + } + *s = '\0'; + return; +} Index: /tags/v1-0-3/src/utils/ncgen/init.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/init.c (revision 313) +++ /tags/v1-0-3/src/utils/ncgen/init.c (revision 313) @@ -0,0 +1,43 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include +#include +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + +extern int netcdf_flag; +extern int c_flag; +extern int fortran_flag; + +struct dims *dims; /* table of netcdf dimensions */ + +int ncid; /* handle for netCDF */ +int ndims; /* number of dimensions declared for netcdf */ +int nvars; /* number of variables declared for netcdf */ +int natts; /* number of attributes */ +int nvdims; /* number of dimensions for variables */ +int dimnum; /* dimension number index for variables */ +int varnum; /* variable number index for attributes */ +int valnum; /* value number index for attributes */ +int rec_dim; /* number of the unlimited dimension, if any */ +size_t var_len; /* variable length (product of dimensions) */ +size_t rec_len; /* number of elements for a record of data */ +size_t var_size; /* size of each element of variable */ + +struct vars *vars; /* a malloc'ed list */ + +struct atts *atts; /* table of variable and global attributes */ + +void +init_netcdf(void) { /* initialize global counts, flags */ + + clearout(); /* reset symbol table to empty */ + ndims = 0; + nvars = 0; + rec_dim = -1; /* means no unlimited dimension (yet) */ +} Index: /tags/v1-0-3/src/utils/ncgen/ncgen.l =================================================================== --- /tags/v1-0-3/src/utils/ncgen/ncgen.l (revision 418) +++ /tags/v1-0-3/src/utils/ncgen/ncgen.l (revision 418) @@ -0,0 +1,208 @@ +%{ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Id$ + *********************************************************************/ + +/* lex specification for tokens for ncgen */ + +/* Fill value used by ncdump from version 2.4 and later. Should match + definition of FILL_STRING in ../ncdump/vardata.h */ +#define FILL_STRING "_" +#define XDR_INT_MIN (-2147483647-1) +#define XDR_INT_MAX 2147483647 + +char errstr[100]; /* for short error messages */ + +#include +#include +#include "genlib.h" +#include "ncgentab.h" + +#define YY_BREAK /* defining as nothing eliminates unreachable + statement warnings from flex output, + but make sure every action ends with + "return" or "break"! */ + +%} + +%p 6000 + +escaped \\. +nonquotes ([^"\\]|{escaped})* +exp ([eE][+-]?[0-9]+) +%% +\/\/.* { /* comment */ + break; + } + +\"{nonquotes}\" { + if(yyleng > MAXTRST) { + yyerror("string too long, truncated\n"); + yytext[MAXTRST-1] = '\0'; + } + expand_escapes(termstring,(char *)yytext,yyleng); + return (TERMSTRING); + } + +float|FLOAT|real|REAL {return (FLOAT_K);} +char|CHAR {return (CHAR_K);} +byte|BYTE {return (BYTE_K);} +short|SHORT {return (SHORT_K);} +long|LONG|int|INT|integer|INTEGER {return (INT_K);} +double|DOUBLE {return (DOUBLE_K);} +unlimited|UNLIMITED {int_val = -1; + return (NC_UNLIMITED_K);} + +dimensions:|DIMENSIONS: {return (DIMENSIONS);} +variables:|VARIABLES: {return (VARIABLES);} +data:|DATA: {return (DATA);} +(netcdf|NETCDF|netCDF)[ \t]+[^\{]+ { + char *s = (char*)yytext+strlen("netcdf"); + char *t = (char*)yytext+yyleng-1; + while (isspace(*s)) + s++; + while (isspace(*t)) + t--; + t++; + if (t-s+1 < 1) { + yyerror("netCDF name required"); + return (DATA); /* generate syntax error */ + } + netcdfname = (char *) emalloc(t-s+1); + (void) strncpy(netcdfname, s, t-s); + netcdfname[t-s] = '\0'; + return (NETCDF); + } +DoubleInf|NaN|-?Infinity { /* missing value (pre-2.4 backward compatibility) */ + if (yytext[0] == '-') { + double_val = -NC_FILL_DOUBLE; + } else { + double_val = NC_FILL_DOUBLE; + } + return (DOUBLE_CONST); + } +FloatInf|-?Inff { /* missing value (pre-2.4 backward compatibility) */ + if (yytext[0] == '-') { + float_val = -NC_FILL_FLOAT; + } else { + float_val = NC_FILL_FLOAT; + } + return (FLOAT_CONST); + } +[A-Za-z_][A-Z.@#\[\]a-z_0-9+-]* { + if (STREQ((char *)yytext, FILL_STRING)) + return (FILLVALUE); + if ((yylval = lookup((char *)yytext)) == NULL) { + yylval = install((char *)yytext); + } + return (IDENT); + } + +\n { + lineno++ ; + break; + } + +[+-]?[0-9]*[0-9][Bb] { + int ii; + if (sscanf((char*)yytext, "%d", &ii) != 1) { + sprintf(errstr,"bad byte constant: %s",(char*)yytext); + yyerror(errstr); + } + byte_val = ii; + if (ii != (int)byte_val) { + sprintf(errstr,"byte constant out of range (-128,127): %s",(char*)yytext); + yyerror(errstr); + } + return (BYTE_CONST); + } + +[+-]?[0-9]*\.[0-9]*{exp}?[LlDd]?|[+-]?[0-9]*{exp}[LlDd]? { + if (sscanf((char*)yytext, "%le", &double_val) != 1) { + sprintf(errstr,"bad long or double constant: %s",(char*)yytext); + yyerror(errstr); + } + return (DOUBLE_CONST); + } +[+-]?[0-9]*\.[0-9]*{exp}?[Ff]|[+-]?[0-9]*{exp}[Ff] { + if (sscanf((char*)yytext, "%e", &float_val) != 1) { + sprintf(errstr,"bad float constant: %s",(char*)yytext); + yyerror(errstr); + } + return (FLOAT_CONST); + } +[+-]?[0-9]+[sS]|0[xX][0-9a-fA-F]+[sS] { + if (sscanf((char*)yytext, "%hd", &short_val) != 1) { + sprintf(errstr,"bad short constant: %s",(char*)yytext); + yyerror(errstr); + } + return (SHORT_CONST); + } +[+-]?([1-9][0-9]*|0)[lL]? { + char *ptr; + errno = 0; + double_val = strtod((char*)yytext, &ptr); + if (errno != 0 && double_val == 0.0) { + sprintf(errstr,"bad numerical constant: %s",(char*)yytext); + yyerror(errstr); + } + if (double_val < XDR_INT_MIN ||double_val > XDR_INT_MAX) { + return DOUBLE_CONST; + } else { + int_val = (int) double_val; + return INT_CONST; + } + } +0[xX]?[0-9a-fA-F]+[lL]? { + char *ptr; + long long_val; + errno = 0; + long_val = strtol((char*)yytext, &ptr, 0); + if (errno != 0) { + sprintf(errstr,"bad long constant: %s",(char*)yytext); + yyerror(errstr); + } + if (long_val < XDR_INT_MIN || long_val > XDR_INT_MAX) { + double_val = (double) long_val; + return DOUBLE_CONST; + } else { + int_val = (int) long_val; + return INT_CONST; + } + } +\'[^\\]\' { + (void) sscanf((char*)&yytext[1],"%c",&byte_val); + return (BYTE_CONST); + } +\'\\[0-7][0-7]?[0-7]?\' { + byte_val = (char) strtol((char*)&yytext[2], (char **) 0, 8); + return (BYTE_CONST); + } +\'\\[xX][0-9a-fA-F][0-9a-fA-F]?\' { + byte_val = (char) strtol((char*)&yytext[3], (char **) 0, 16); + return (BYTE_CONST); + } +\'\\.\' { + switch ((char)yytext[2]) { + case 'a': byte_val = '\007'; break; /* not everyone under- + * stands '\a' yet */ + case 'b': byte_val = '\b'; break; + case 'f': byte_val = '\f'; break; + case 'n': byte_val = '\n'; break; + case 'r': byte_val = '\r'; break; + case 't': byte_val = '\t'; break; + case 'v': byte_val = '\v'; break; + case '\\': byte_val = '\\'; break; + case '?': byte_val = '\177'; break; + case '\'': byte_val = '\''; break; + default: byte_val = (char)yytext[2]; + } + return (BYTE_CONST); + } + +[ \t\f]+ { /* whitespace */ + break; + } +. return (yytext[0]) ; Index: /tags/v1-0-3/src/utils/ncgen/main.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/main.c (revision 589) +++ /tags/v1-0-3/src/utils/ncgen/main.c (revision 589) @@ -0,0 +1,215 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include /* has getopt() under VMS */ +#include + +#ifdef __hpux +#include +#endif + +#include + +#include + +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + +extern int yyparse(void); + +const char *progname; /* for error messages */ +const char *cdlname; + +int c_flag; +int fortran_flag; +int netcdf_flag; +int giantfile_flag; +int nofill_flag; +char *netcdf_name = NULL; /* name of output netCDF file to write */ + +extern FILE *yyin; + +static const char* ubasename ( const char* av0 ); +static void usage ( void ); +int main ( int argc, char** argv ); + + +/* strip off leading path */ +static const char * +ubasename( + const char *av0) +{ + const char *logident ; +#ifdef VMS +#define SEP ']' +#endif +#ifdef MSDOS +#define SEP '\\' +#endif +#ifndef SEP +#define SEP '/' +#endif + if ((logident = strrchr(av0, SEP)) == NULL) + logident = av0 ; + else + logident++ ; + return logident ; +} + + +static void usage(void) +{ + derror("Usage: %s [ -b ] [ -c ] [ -f ] [ -v version ] [ -x ] [ -o outfile] [ file ... ]", + progname); + derror("netcdf library version %s", ncmpi_inq_libvers()); +} + + +int +main( + int argc, + char *argv[]) +{ + extern int optind; + extern int opterr; + extern char *optarg; + int c; + int ret; + FILE *fp; + + MPI_Init(&argc, &argv); + +#ifdef __hpux + setlocale(LC_CTYPE,""); +#endif + +#ifdef MDEBUG + malloc_debug(2) ; /* helps find malloc/free errors on Sun */ +#endif /* MDEBUG */ + + opterr = 1; /* print error message if bad option */ + progname = ubasename(argv[0]); + cdlname = "-"; + + c_flag = 0; + fortran_flag = 0; + netcdf_flag = 0; + giantfile_flag = 0; + nofill_flag = 0; + +#if 0 +#if _CRAYMPP && 0 + /* initialize CRAY MPP parallel-I/O library */ + (void) par_io_init(32, 32); +#endif +#endif + + while ((c = getopt(argc, argv, "bcfl:no:v:x")) != EOF) + switch(c) { + case 'c': /* for c output. old version of '-lc' */ + c_flag = 1; + break; + case 'f': /* for fortran output. old version of '-lf' */ + fortran_flag = 1; + break; + case 'b': /* for binary netcdf output, ".nc" extension */ + netcdf_flag = 1; + break; + case 'l': /* specify language, instead of -c or -f */ + { + char *lang_name = (char *) emalloc(strlen(optarg)+1); + if (! lang_name) { + derror ("%s: out of memory", progname); + return(1); + } + (void)strcpy(lang_name, optarg); + if (strcmp(lang_name, "c") == 0 || strcmp(lang_name, "C") == 0) { + c_flag = 1; + } + else if (strcmp(lang_name, "f77") == 0 || + strcmp(lang_name, "fortran77") == 0 || + strcmp(lang_name, "Fortran77") == 0) { + fortran_flag = 1; + } else { /* Fortran90, Java, C++, Perl, Python, Ruby, ... */ + derror("%s: output language %s not implemented", + progname, lang_name); + return(1); + } + } + break; + case 'n': /* old version of -b, uses ".cdf" extension */ + netcdf_flag = -1; + break; + case 'o': /* to explicitly specify output name */ + netcdf_flag = 1; + netcdf_name = (char *) emalloc(strlen(optarg)+1); + if (! netcdf_name) { + derror ("%s: out of memory", progname); + return(1); + } + (void)strcpy(netcdf_name,optarg); + break; + case 'x': /* set nofill mode to speed up creation fo large files */ + nofill_flag = 1; + break; + case 'v': /* for creating 64-bit offet files, specify version 2 */ + { + char *version_name = (char *)emalloc(strlen(optarg)+1); + if (! version_name) { + derror ("%s: out of memory", progname); + return (1); + } + (void)strcpy(version_name, optarg); + /* the default version is version 1, with 32-bit offsets */ + if (strcmp(version_name, "1") == 0 || + strcmp(version_name, "classic") == 0) { + giantfile_flag = 0; + } + /* the 64-bit offset version (2) should only be used if + * actually needed */ + else if (strcmp(version_name, "2") == 0 || + strcmp(version_name, "64-bit-offset") == 0) { + giantfile_flag = 1; + } + } + break; + case '?': + usage(); + return(8); + } + + if (fortran_flag && c_flag) { + derror("Only one of -c or -f may be specified"); + return(8); + } + if (fortran_flag) { + derror("Generating Fortran interface not supported yet"); + return(0); + } + + argc -= optind; + argv += optind; + + if (argc > 1) { + derror ("%s: only one input file argument permitted",progname); + return(6); + } + + fp = stdin; + if (argc > 0 && strcmp(argv[0], "-") != 0) { + if ((fp = fopen(argv[0], "r")) == NULL) { + derror ("can't open file %s for reading: ", argv[0]); + perror(""); + return(7); + } + cdlname = argv[0]; + } + yyin = fp; + ret = yyparse(); + MPI_Finalize(); + return ret; +} Index: /tags/v1-0-3/src/utils/ncgen/genlib.h =================================================================== --- /tags/v1-0-3/src/utils/ncgen/genlib.h (revision 430) +++ /tags/v1-0-3/src/utils/ncgen/genlib.h (revision 430) @@ -0,0 +1,84 @@ +#ifndef NC_GENLIB_H +#define NC_GENLIB_H +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ +#include +#include + +extern const char *progname; /* for error messages */ +extern const char *cdlname; /* for error messages */ + +#define FORT_MAX_LINES 20 /* max lines in FORTRAN statement */ +#define FORT_MAX_STMNT 66*FORT_MAX_LINES /* max chars in FORTRAN statement */ +#define C_MAX_STMNT FORT_MAX_STMNT /* until we fix to break up C lines */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void cline ( const char* stmnt ); +extern void fline ( const char* stmnt ); +extern const char* nctype ( nc_type type ); +extern const char* ncctype ( nc_type type ); +extern const char* ncstype ( nc_type type ); +extern const char* ncatype ( nc_type type ); +extern const char* nfstype ( nc_type type ); +extern const char* nfftype ( nc_type type ); +extern char* fstring ( nc_type type, void* valp, int num ); +extern char* cstrstr ( const char* valp, size_t len ); +extern char* fstrstr ( const char* str, size_t ilen ); +extern size_t nctypesize( nc_type type ); + +extern void derror ( const char *fmt, ... ) +#ifdef _GNUC_ + __attribute__ ((format (printf, 1, 2))) +#endif +; +extern void check_err ( int status ); +extern void *emalloc ( size_t size ); +extern void *ecalloc ( size_t size ); +extern void *erealloc ( void *ptr, size_t size ); +extern void expe2d ( char *ptr ); +extern void grow_iarray ( int narray, int **array ); +extern void grow_varray ( int narray, struct vars **array ); +extern void grow_darray ( int narray, struct dims **array ); +extern void grow_aarray ( int narray, struct atts **array ); +extern char* decodify (const char *name); + +extern int put_variable ( void* rec_start ); + +/* initializes netcdf counts (e.g. nvars), defined in init.c */ +extern void init_netcdf ( void ); + +/* generates all define mode stuff, defined in genlib.c */ +extern void define_netcdf(char *netcdfname); + +/* generates variable puts, defined in load.c */ +extern void load_netcdf ( void* rec_start ); + +/* generates close, defined in close.c */ +extern void close_netcdf ( void ); + +/* defined in escapes.c */ +extern void expand_escapes ( char* termstring, char* yytext, int yyleng ); + +/* to get fill value for various types, defined in getfill.c */ +extern void nc_getfill ( nc_type type, union generic* gval ); + +/* to put fill value for various types, defined in getfill.c */ +extern void nc_putfill ( nc_type type, void* val, union generic* gval ); + +/* fills a generic array with a value, defined in getfill.c */ +extern void nc_fill ( nc_type type, size_t num, void* datp, + union generic fill_val ); + +/* reset symbol table to empty, defined in ncgen.y */ +extern void clearout(void); + +#ifdef __cplusplus +} +#endif +#endif /*!NC_GENLIB_H*/ Index: /tags/v1-0-3/src/utils/ncgen/getfill.c =================================================================== --- /tags/v1-0-3/src/utils/ncgen/getfill.c (revision 401) +++ /tags/v1-0-3/src/utils/ncgen/getfill.c (revision 401) @@ -0,0 +1,136 @@ +/********************************************************************* + * Copyright 1993, UCAR/Unidata + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * $Header$ + *********************************************************************/ + +#include "pnetcdf.h" +#include "generic.h" +#include "ncgen.h" +#include "genlib.h" + + +/* + * Given netCDF type, return a default fill_value appropriate for + * that type. + */ +void +nc_getfill( + nc_type type, + union generic *gval) +{ + switch(type) { + case NC_CHAR: + gval->charv = NC_FILL_CHAR; + return; + case NC_BYTE: + gval->charv = NC_FILL_BYTE; + return; + case NC_SHORT: + gval->shortv = NC_FILL_SHORT; + return; + case NC_INT: + gval->intv = NC_FILL_INT; + return; + case NC_FLOAT: + gval->floatv = NC_FILL_FLOAT; + return; + case NC_DOUBLE: + gval->doublev = NC_FILL_DOUBLE; + return; + default: + derror("nc_getfill: unrecognized type"); + } +} + + +void +nc_fill( + nc_type type, /* netcdf type code */ + size_t num, /* number of values to fill */ + void *datp, /* where to start filling */ + union generic fill_val) /* value to use */ +{ + char *char_valp=NULL; /* pointers used to accumulate data values */ + short *short_valp=NULL; + int *long_valp=NULL; + float *float_valp=NULL; + double *double_valp=NULL; + + switch (type) { + case NC_CHAR: + case NC_BYTE: + char_valp = (char *) datp; + break; + case NC_SHORT: + short_valp = (short *) datp; + break; + case NC_INT: + long_valp = (int *) datp; + break; + case NC_FLOAT: + float_valp = (float *) datp; + break; + case NC_DOUBLE: + double_valp = (double *) datp; + break; + default: + derror("nc_fill: unrecognized type"); + break; + } + while (num--) { + switch (type) { + case NC_CHAR: + case NC_BYTE: + *char_valp++ = fill_val.charv; + break; + case NC_SHORT: + *short_valp++ = fill_val.shortv; + break; + case NC_INT: + *long_valp++ = fill_val.intv; + break; + case NC_FLOAT: + *float_valp++ = fill_val.floatv; + break; + case NC_DOUBLE: + *double_valp++ = fill_val.doublev; + break; + default: + derror("nc_fill: unrecognized type"); + break; + } + } +} + + +/* + * Given netCDF type, put a value of that type into a fill_value + */ +void +nc_putfill( + nc_type type, + void *val, /* value of type to be put */ + union generic *gval) /* where the value is to be put */ +{ + switch(type) { + case NC_CHAR: + case NC_BYTE: + gval->charv = *(char *)val; + return; + case NC_SHORT: + gval->shortv = *(short *)val; + return; + case NC_INT: + gval->intv = *(int *)val; + return; + case NC_FLOAT: + gval->floatv = *(float *)val; + return; + case NC_DOUBLE: + gval->doublev = *(double *)val; + return; + default: + derror("nc_putfill: unrecognized type"); + } +} Index: /tags/v1-0-3/src/Makefile.in =================================================================== --- /tags/v1-0-3/src/Makefile.in (revision 316) +++ /tags/v1-0-3/src/Makefile.in (revision 316) @@ -0,0 +1,15 @@ +all: + cd lib && $(MAKE) + if [ @has_fortran@ = yes ] ; then cd libf && $(MAKE) ; fi + cd utils && $(MAKE) + +distclean: clean +clean: + cd lib && $(MAKE) clean + cd libf && $(MAKE) clean + cd utils && $(MAKE) clean + +install: + cd lib && $(MAKE) install + if [ @has_fortran@ = yes ] ; then cd libf && $(MAKE) install ; fi + cd utils && $(MAKE) install Index: /tags/v1-0-3/src/lib/mpincio.c =================================================================== --- /tags/v1-0-3/src/lib/mpincio.c (revision 575) +++ /tags/v1-0-3/src/lib/mpincio.c (revision 575) @@ -0,0 +1,362 @@ +/************************************************************************** + * + * This file is created by Northwestern University and Argonne National + * Laboratory + * + *************************************************************************/ + +#include "ncconfig.h" + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#ifndef ENOERR +#define ENOERR 0 +#endif +#include +#include +#include +#ifdef _MSC_VER /* Microsoft Compilers */ +#include +#else +#include +#endif + +#include "nc.h" +#include "ncio.h" +#include "fbits.h" +#include "rnd.h" + +/* #define INSTRUMENT 1 */ +#ifdef INSTRUMENT /* debugging */ +#undef NDEBUG +#include +#include "instr.h" +#endif + +#ifndef MIN +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) +#endif + +#if !defined(NDEBUG) && !defined(X_INT_MAX) +#define X_INT_MAX INT_MAX +#endif + +#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */ +#define X_ALIGN 4 +#else +#undef X_ALIGN +#endif + +#define MAX_NC_ID 1024 + +static unsigned char IDalloc[MAX_NC_ID]; + +void +ncmpiio_free(ncio *nciop) { + if (nciop != NULL) + free(nciop); +} + +ncio * +ncmpiio_new(const char *path, int ioflags) +{ + size_t sz_ncio = M_RNDUP(sizeof(ncio)); + size_t sz_path = M_RNDUP(strlen(path) +1); + ncio *nciop; + + nciop = (ncio *) malloc(sz_ncio + sz_path); + if (nciop == NULL) + return NULL; + + nciop->ioflags = ioflags; + + nciop->path = (char *) ((char *)nciop + sz_ncio); + (void) strcpy((char *)nciop->path, path); + + return nciop; +} + +int +ncmpiio_create(MPI_Comm comm, const char *path, int ioflags, MPI_Info info, + ncio **nciopp) { + ncio *nciop; + int i; + int mpiomode = (MPI_MODE_RDWR | MPI_MODE_CREATE); + int mpireturn; + int do_zero_file_size = 0; + + fSet(ioflags, NC_WRITE); + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncmpiio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + + nciop->mpiomode = MPI_MODE_RDWR; + nciop->mpioflags = 0; + nciop->comm = comm; + if (info == MPI_INFO_NULL) + nciop->mpiinfo = MPI_INFO_NULL; + else +#ifdef HAVE_MPI_INFO_DUP + MPI_Info_dup(info, &nciop->mpiinfo); +#else + nciop->mpiinfo = info; +#endif + + if (fIsSet(ioflags, NC_NOCLOBBER)) + fSet(mpiomode, MPI_MODE_EXCL); + else + do_zero_file_size = 1; + + mpireturn = MPI_File_open(comm, (char *)path, mpiomode, info, &nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(comm, &rank); + ncmpiio_free(nciop); + ncmpii_handle_error(rank, mpireturn, "MPI_File_open"); + return NC_EOFILE; + } + if (do_zero_file_size) MPI_File_set_size(nciop->collective_fh, 0); + + for (i = 0; i < MAX_NC_ID && IDalloc[i] != 0; i++); + if (i == MAX_NC_ID) { + ncmpiio_free(nciop); + return NC_ENFILE; + } + *((int *)&nciop->fd) = i; + IDalloc[i] = 1; + + set_NC_collectiveFh(nciop); + + *nciopp = nciop; + return ENOERR; +} + +int +ncmpiio_open(MPI_Comm comm, const char *path, int ioflags, MPI_Info info, + ncio **nciopp) { + ncio *nciop; + int i; + int mpiomode = fIsSet(ioflags, NC_WRITE) ? MPI_MODE_RDWR : MPI_MODE_RDONLY; + int mpireturn; + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncmpiio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + + nciop->mpiomode = mpiomode; + nciop->mpioflags = 0; + nciop->comm = comm; + if (info == MPI_INFO_NULL) + nciop->mpiinfo = MPI_INFO_NULL; + else +#ifdef HAVE_MPI_INFO_DUP + MPI_Info_dup(info, &nciop->mpiinfo); +#else + nciop->mpiinfo = info; +#endif + + mpireturn = MPI_File_open(comm, (char *)path, mpiomode, info, &nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(comm, &rank); + ncmpiio_free(nciop); + ncmpii_handle_error(rank, mpireturn, "MPI_File_open"); + return NC_EOFILE; + } + + for (i = 0; i < MAX_NC_ID && IDalloc[i] != 0; i++); + if (i == MAX_NC_ID) { + ncmpiio_free(nciop); + return NC_ENFILE; + } + *((int *)&nciop->fd) = i; + IDalloc[i] = 1; + + set_NC_collectiveFh(nciop); + + *nciopp = nciop; + return ENOERR; +} + +int +ncmpiio_sync(ncio *nciop) { + int mpireturn; + + if(NC_independentFhOpened(nciop)) { + mpireturn = MPI_File_sync(nciop->independent_fh); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + return NC_EFILE; + } + } + + if(NC_collectiveFhOpened(nciop)) { + mpireturn = MPI_File_sync(nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + return NC_EFILE; + } + } + + + MPI_Barrier(nciop->comm); + + return ENOERR; +} + +int +ncmpiio_close(ncio *nciop, int doUnlink) { + int status = ENOERR; + int mpireturn; + + if (nciop == NULL) + return EINVAL; + + if(NC_independentFhOpened(nciop)) { + mpireturn = MPI_File_close(&(nciop->independent_fh)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_close"); + return NC_EFILE; + } + } + + + if(NC_collectiveFhOpened(nciop)) { + mpireturn = MPI_File_close(&(nciop->collective_fh)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_close"); + return NC_EFILE; + } + } + IDalloc[*((int *)&nciop->fd)] = 0; + + if (doUnlink) { + mpireturn = MPI_File_delete((char *)nciop->path, nciop->mpiinfo); +/* + if (mpireturn != MPI_SUCCESS) { + char errorString[512]; + int errorStringLen; + int rank; + MPI_Comm_rank(nciop->comm, &rank); + MPI_Error_string(mpireturn, errorString, &errorStringLen); + printf("%2d: MPI_File_delete error = %s\n", rank, errorString); + return NC_EFILE; + } +*/ + } + + ncmpiio_free(nciop); + + return status; +} + +int +ncmpiio_move(ncio *const nciop, off_t to, off_t from, size_t nbytes) { + int mpireturn, mpierr = 0, errcheck; + const int bufsize = 4096; + size_t movesize, bufcount; + int rank, grpsize; + void *buf = malloc(bufsize); + MPI_Comm comm; + MPI_Status mpistatus; + + + if (buf == NULL) + return NC_ENOMEM; + + comm = nciop->comm; + MPI_Comm_size(comm, &grpsize); + MPI_Comm_rank(comm, &rank); + + movesize = nbytes; + + while (movesize > 0) { + /* find a proper number of processors to participate I/O */ + while (grpsize > 1 && movesize/grpsize < bufsize) + grpsize--; + if (grpsize > 1) { + bufcount = bufsize; + movesize -= bufsize*grpsize; + } + else if (movesize < bufsize) { + bufcount = movesize; + movesize = 0; + } + else { + bufcount = bufsize; + movesize -= bufsize; + } + + /* reset the file view */ + mpireturn = MPI_File_set_view(nciop->collective_fh, 0, MPI_BYTE, + MPI_BYTE, "native", nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + free(buf); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EREAD; + } + if (rank < grpsize) { + /* read the original data @ from+movesize+rank*bufsize */ + mpireturn = MPI_File_read_at(nciop->collective_fh, + from+movesize+rank*bufsize, + buf, bufcount, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + mpierr = 1; + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_at"); + } + } + MPI_Allreduce(&mpierr, &errcheck, 1, MPI_INT, MPI_LOR, comm); + if (errcheck) { + free(buf); + return NC_EREAD; + } + + MPI_Barrier(comm); /* important, in case new region overlaps old region */ + + /* reset the file view */ + mpireturn = MPI_File_set_view(nciop->collective_fh, 0, MPI_BYTE, + MPI_BYTE, "native", nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + free(buf); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EWRITE; + } + if (rank < grpsize) { + /* write to new location @ to+movesize+rank*bufsize */ + mpireturn = MPI_File_write_at(nciop->collective_fh, + to+movesize+rank*bufsize, + buf, bufcount, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + mpierr = 1; + ncmpii_handle_error(rank, mpireturn, "MPI_File_write_at"); + } + } + MPI_Allreduce(&mpierr, &errcheck, 1, MPI_INT, MPI_LOR, comm); + if (errcheck) { + free(buf); + return NC_EWRITE; + } + } + + free(buf); + return NC_NOERR; +} Index: /tags/v1-0-3/src/lib/nc.c =================================================================== --- /tags/v1-0-3/src/lib/nc.c (revision 646) +++ /tags/v1-0-3/src/lib/nc.c (revision 646) @@ -0,0 +1,1097 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#include "nc.h" +#include "rnd.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include "ncx.h" + +/* list of open netcdf's */ +static NC *NClist = NULL; + +/* This is the default create format for ncmpi_create and nc__create. */ +static int default_create_format = NC_FORMAT_CLASSIC; + +/* These have to do with version numbers. */ +#define MAGIC_NUM_LEN 4 +#define VER_CLASSIC 1 +#define VER_64BIT_OFFSET 2 +#define VER_HDF5 3 + + + + +/* Prototypes for functions used only in this file */ +static int move_data_r(NC *ncp, NC *old); +static int move_recs_r(NC *ncp, NC *old); +static int move_vars_r(NC *ncp, NC *old); +static int write_NC(NC *ncp); +static int NC_begins(NC *ncp, size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align); +static int NC_check_def(MPI_Comm comm, void *buf, size_t nn); + +#if 0 +static int enddef(NC *ncp); +static int nc_sync(int ncid); +static int nc_set_fill(int ncid, int fillmode, int *old_mode_ptr); +#endif + +void +ncmpii_add_to_NCList(NC *ncp) +{ + assert(ncp != NULL); + + ncp->prev = NULL; + if(NClist != NULL) + NClist->prev = ncp; + ncp->next = NClist; + NClist = ncp; +} + +void +ncmpii_del_from_NCList(NC *ncp) +{ + assert(ncp != NULL); + + if(NClist == ncp) + { + assert(ncp->prev == NULL); + NClist = ncp->next; + } + else + { + assert(ncp->prev != NULL); + ncp->prev->next = ncp->next; + } + + if(ncp->next != NULL) + ncp->next->prev = ncp->prev; + + ncp->next = NULL; + ncp->prev = NULL; +} + +/* + * Check the data set definitions across all processes by + * comparing the header buffer streams of all processes. + */ +static int +NC_check_def(MPI_Comm comm, void *buf, size_t nn) { + int rank; + int errcheck, compare = 0; + void *cmpbuf; + int max_size; + + MPI_Comm_rank(comm, &rank); + + if (rank == 0) + max_size = nn; + MPI_Bcast(&max_size, 1, MPI_INT, 0, comm); + + compare = max_size - nn; + MPI_Allreduce(&compare, &errcheck, 1, MPI_INT, MPI_LOR, comm); + if (errcheck) + return NC_EMULTIDEFINE; + + if (rank == 0) + cmpbuf = buf; + else + cmpbuf = (void *)malloc(nn); + + MPI_Bcast(cmpbuf, nn, MPI_BYTE, 0, comm); + + if (rank != 0) { + compare = memcmp(buf, cmpbuf, nn); + free(cmpbuf); + } + + MPI_Allreduce(&compare, &errcheck, 1, MPI_INT, MPI_LOR, comm); + + if (errcheck) + return NC_EMULTIDEFINE; + else + return NC_NOERR; +} + +int +ncmpii_NC_check_id(int ncid, NC **ncpp) +{ + NC *ncp; + + if(ncid >= 0) + { + for(ncp = NClist; ncp != NULL; ncp = ncp->next) + { + if(ncp->nciop->fd == ncid) + { + *ncpp = ncp; + return NC_NOERR; /* normal return */ + } + } + } + + /* else, not found */ + return NC_EBADID; +} + + +/* static */ +void +ncmpii_free_NC(NC *ncp) +{ + if(ncp == NULL) + return; + ncmpii_free_NC_dimarrayV(&ncp->dims); + ncmpii_free_NC_attrarrayV(&ncp->attrs); + ncmpii_free_NC_vararrayV(&ncp->vars); + free(ncp); +} + + +/* static */ +NC * +ncmpii_new_NC(const size_t *chunkp) +{ + NC *ncp; + + ncp = (NC *) malloc(sizeof(NC)); + if(ncp == NULL) + return NULL; + (void) memset(ncp, 0, sizeof(NC)); + + ncp->xsz = MIN_NC_XSZ; + assert(ncp->xsz == ncmpii_hdr_len_NC(ncp, 0)); + + ncp->chunk = chunkp != NULL ? *chunkp : NC_SIZEHINT_DEFAULT; + + return ncp; +} + +/* This function sets a default create flag that will be logically + or'd to whatever flags are passed into nc_create for all future + calls to nc_create. + Valid default create flags are NC_64BIT_OFFSET, NC_CLOBBER, + NC_LOCK, NC_SHARE. */ +int +ncmpi_set_default_format(int format, int *old_formatp) +{ + /* Return existing format if desired. */ + if (old_formatp) + *old_formatp = default_create_format; + + /* Make sure only valid format is set. */ + if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT) + return NC_EINVAL; + default_create_format = format; + return NC_NOERR; +} + +#if 0 +/* returns a value suituable for a create flag. Will return one or more of the + * following values ORed together: + * NC_64BIT_OFFSET, NC_CLOBBER, NC_LOCK, NC_SHARE */ +static int +ncmpii_get_default_format(void) +{ + return default_create_format; +} +#endif + +/* static */ +NC * +ncmpii_dup_NC(const NC *ref) +{ + NC *ncp; + + ncp = (NC *) malloc(sizeof(NC)); + if(ncp == NULL) + return NULL; + (void) memset(ncp, 0, sizeof(NC)); + + if(ncmpii_dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR) + goto err; + if(ncmpii_dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR) + goto err; + if(ncmpii_dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR) + goto err; + + ncp->xsz = ref->xsz; + ncp->begin_var = ref->begin_var; + ncp->begin_rec = ref->begin_rec; + ncp->recsize = ref->recsize; + NC_set_numrecs(ncp, NC_get_numrecs(ref)); + return ncp; +err: + ncmpii_free_NC(ncp); + return NULL; +} + + +/* + * Verify that this is a user nc_type + * Formerly +NCcktype() + * Sense of the return is changed. + */ +int +ncmpii_cktype(nc_type type) +{ + switch((int)type){ + case NC_BYTE: + case NC_CHAR: + case NC_SHORT: + case NC_INT: + case NC_FLOAT: + case NC_DOUBLE: + return(NC_NOERR); + } + return(NC_EBADTYPE); +} + + +/* + * How many objects of 'type' + * will fit into xbufsize? + */ +size_t +ncmpix_howmany(nc_type type, size_t xbufsize) +{ + switch(type){ + case NC_BYTE: + case NC_CHAR: + return xbufsize; + case NC_SHORT: + return xbufsize/X_SIZEOF_SHORT; + case NC_INT: + return xbufsize/X_SIZEOF_INT; + case NC_FLOAT: + return xbufsize/X_SIZEOF_FLOAT; + case NC_DOUBLE: + return xbufsize/X_SIZEOF_DOUBLE; + default: + assert("ncmpix_howmany: Bad type" == 0); + return(0); + } +} + +#define D_RNDUP(x, align) _RNDUP(x, (off_t)(align)) + +/* + * Compute each variable's 'begin' offset, + * update 'begin_rec' as well. + */ +static int +NC_begins(NC *ncp, + size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align) +{ + size_t ii; + size_t sizeof_off_t; + off_t index = 0; + NC_var **vpp; + NC_var *last = NULL; + + if(v_align == NC_ALIGN_CHUNK) + v_align = ncp->chunk; + if(r_align == NC_ALIGN_CHUNK) + r_align = ncp->chunk; + + if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) { + sizeof_off_t = 8; + } else { + sizeof_off_t = 4; + } + + ncp->xsz = ncmpii_hdr_len_NC(ncp, sizeof_off_t); + + if(ncp->vars.nelems == 0) + return NC_NOERR; + + /* only (re)calculate begin_var if there is not sufficient space in header + or start of non-record variables is not aligned as requested by valign */ + if (ncp->begin_var < ncp->xsz + h_minfree || + ncp->begin_var != D_RNDUP(ncp->begin_var, v_align) ) + { + index = (off_t) ncp->xsz; + ncp->begin_var = D_RNDUP(index, v_align); + if(ncp->begin_var < index + h_minfree) + { + ncp->begin_var = D_RNDUP(index + (off_t)h_minfree, v_align); + } + } + index = ncp->begin_var; + + /* loop thru vars, first pass is for the 'non-record' vars */ + vpp = ncp->vars.value; + for(ii = 0; ii < ncp->vars.nelems ; ii++, vpp++) + { + if( IS_RECVAR(*vpp) ) + { + /* skip record variables on this pass */ + continue; + } +#if 0 +fprintf(stderr, " VAR %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index); +#endif + if (sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0)) + { + return NC_EVARSIZE; + } + + (*vpp)->begin = index; + index += (*vpp)->len; + } + + /* only (re)calculate begin_rec if there is not sufficient + space at end of non-record variables or if start of record + variables is not aligned as requested by r_align */ + if (ncp->begin_rec < index + v_minfree || + ncp->begin_rec != D_RNDUP(ncp->begin_rec, r_align) ) + { + ncp->begin_rec = D_RNDUP(index, r_align); + if(ncp->begin_rec < index + v_minfree) + { + ncp->begin_rec = D_RNDUP(index + (off_t)v_minfree, r_align); + } + } + index = ncp->begin_rec; + + ncp->recsize = 0; + + /* loop thru vars, second pass is for the 'record' vars */ + vpp = (NC_var **)ncp->vars.value; + for(ii = 0; ii < ncp->vars.nelems; ii++, vpp++) + { + if( !IS_RECVAR(*vpp) ) + { + /* skip non-record variables on this pass */ + continue; + } + +#if 0 +fprintf(stderr, " REC %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index); +#endif + if (sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0)) + { + return NC_EVARSIZE; + } + (*vpp)->begin = index; + index += (*vpp)->len; + /* check if record size must fit in 32-bits */ +#if SIZEOF_OFF_T == SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4 + if (ncp->recsize > X_UINT_MAX - (*vpp)->len) + { + return NC_EVARSIZE; + } +#endif + ncp->recsize += (*vpp)->len; + last = (*vpp); + } + + /* + * for special case of exactly one record variable, pack value + */ + if(last != NULL && ncp->recsize == last->len) + ncp->recsize = *last->dsizes * last->xsz; + + if(NC_IsNew(ncp)) + NC_set_numrecs(ncp, 0); + + return NC_NOERR; +} + +#define NC_NUMRECS_OFFSET 4 +#define NC_NUMRECS_EXTENT 4 + +/* + * Read just the numrecs member. + * (A relatively expensive way to do things.) + */ + + +int +ncmpii_read_numrecs(NC *ncp) { + int status = NC_NOERR, mpireturn; + size_t nrecs; + void *buf, *pos; + MPI_Status mpistatus; + int rank; + + MPI_Comm_rank(ncp->nciop->comm, &rank); + + assert(!NC_indef(ncp)); + + pos = buf = (void *)malloc(X_SIZEOF_SIZE_T); + + /* reset the file view */ + mpireturn = MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE, + MPI_BYTE, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EREAD; + } + + mpireturn = MPI_File_read_at(ncp->nciop->collective_fh, NC_NUMRECS_OFFSET, + buf, X_SIZEOF_SIZE_T, MPI_BYTE, &mpistatus); + + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_at"); + return NC_EREAD; + } + + status = ncmpix_get_size_t((const void **)&pos, &nrecs); + ncp->numrecs = nrecs; + + free(buf); + + return status; +} + +/* + * Write out just the numrecs member. + * (A relatively expensive way to do things.) + */ + +/* + * Collective operation implicit + */ + +int +ncmpii_write_numrecs(NC *ncp) { + int status = NC_NOERR, mpireturn; + size_t nrecs; + void *buf, *pos; + MPI_Status mpistatus; + MPI_Comm comm; + int rank; + + assert(!NC_readonly(ncp)); + assert(!NC_indef(ncp)); + + comm = ncp->nciop->comm; + MPI_Comm_rank(comm, &rank); + + nrecs = ncp->numrecs; + pos = buf = (void *)malloc(X_SIZEOF_SIZE_T); + status = ncmpix_put_size_t(&pos, &nrecs); + + if(NC_indep(ncp) && NC_independentFhOpened(ncp->nciop)) { + mpireturn = MPI_File_sync(ncp->nciop->independent_fh); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + return NC_EWRITE; + } + MPI_Barrier(comm); + } + + /* reset the file view */ + mpireturn = MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE, + MPI_BYTE, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EWRITE; + } + + if (rank == 0) { + mpireturn = MPI_File_write_at(ncp->nciop->collective_fh, NC_NUMRECS_OFFSET, + buf, X_SIZEOF_SIZE_T, MPI_BYTE, &mpistatus); + } + + MPI_Bcast(&mpireturn, 1, MPI_INT, 0, comm); + + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_write_at"); + status = NC_EWRITE; + } else { + mpireturn = MPI_File_sync(ncp->nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + status = NC_EWRITE; + } + + MPI_Barrier(comm); + fClr(ncp->flags, NC_NDIRTY); + } + + free(buf); + + return status; +} + +/* + * Read in the header + * It is expensive. + */ + +int +ncmpii_read_NC(NC *ncp) { + int status = NC_NOERR; + + ncmpii_free_NC_dimarrayV(&ncp->dims); + ncmpii_free_NC_attrarrayV(&ncp->attrs); + ncmpii_free_NC_vararrayV(&ncp->vars); + + status = ncmpii_hdr_get_NC(ncp); + + if(status == NC_NOERR) + fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY); + + return status; +} + +/* + * Write out the header + */ + +static int +write_NC(NC *ncp) +{ + int status = NC_NOERR, mpireturn; + void *buf; + MPI_Status mpistatus; + int rank; + + assert(!NC_readonly(ncp)); + + MPI_Comm_rank(ncp->nciop->comm, &rank); + + buf = (void *)malloc(ncp->xsz); + status = ncmpii_hdr_put_NC(ncp, buf); + if(status != NC_NOERR) { + free(buf); + return status; + } + status = NC_check_def(ncp->nciop->comm, buf, ncp->xsz); + if (status != NC_NOERR) { + free(buf); + return status; + } + + /* reset the file view */ + mpireturn = MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE, + MPI_BYTE, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EWRITE; + } + + if (rank == 0) { + mpireturn = MPI_File_write_at(ncp->nciop->collective_fh, 0, buf, + ncp->xsz, MPI_BYTE, &mpistatus); + } + + MPI_Bcast(&mpireturn, 1, MPI_INT, 0, ncp->nciop->comm); + + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_write_at"); + return NC_EWRITE; + } + + fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY); + free(buf); + + return status; +} + +/* + * Write the header or the numrecs if necessary. + */ +int +ncmpii_NC_sync(NC *ncp) +{ + int mynumrecs, numrecs; + + assert(!NC_readonly(ncp)); + + /* collect and set the max numrecs due to difference by independent write */ + + mynumrecs = ncp->numrecs; + MPI_Allreduce(&mynumrecs, &numrecs, 1, MPI_INT, MPI_MAX, ncp->nciop->comm); + if (numrecs > ncp->numrecs) { + ncp->numrecs = numrecs; + set_NC_ndirty(ncp); + } + + if(NC_hdirty(ncp)) { + return write_NC(ncp); + } + /* else */ + + if(NC_ndirty(ncp)) { + return ncmpii_write_numrecs(ncp); + } + /* else */ + + return NC_NOERR; +} + + +/* + * Move the records "out". + * Fill as needed. + */ + +static int +move_data_r(NC *ncp, NC *old) { + /* no new variable inserted, move the whole contiguous data part */ + ncp->numrecs = old->numrecs; + return ncmpiio_move(ncp->nciop, ncp->begin_var, old->begin_var, + old->begin_rec - old->begin_var + old->recsize * old->numrecs); +} + +static int +move_recs_r(NC *ncp, NC *old) { + int status; + int recno; + const size_t old_nrecs = old->numrecs; + const size_t ncp_recsize = ncp->recsize; + const size_t old_recsize = old->recsize; + const off_t ncp_off = ncp->begin_rec; + const off_t old_off = old->begin_rec; + + assert(ncp_recsize >= old_recsize); + + if (ncp_recsize == old_recsize) { + + /* No new rec var inserted, move all rec vars as a whole */ + + status = ncmpiio_move(ncp->nciop, ncp_off, old_off, + old_recsize * old_nrecs); + if(status != NC_NOERR) + return status; + } else { + + /* else, new rec var inserted, to be moved one record at a time */ + + for (recno = (int)old_nrecs -1; recno >= 0; recno--) { + status = ncmpiio_move(ncp->nciop, + ncp_off+recno*ncp_recsize, + old_off+recno*old_recsize, + old_recsize); + if(status != NC_NOERR) + return status; + } + } + + ncp->numrecs = old_nrecs; + + return NC_NOERR; +} + + +/* + * Move the "non record" variables "out". + * Fill as needed. + */ + +static int +move_vars_r(NC *ncp, NC *old) { + return ncmpiio_move(ncp->nciop, ncp->begin_var, old->begin_var, + old->begin_rec - old->begin_var); +} + +#if 0 + /* + * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len + * (product of non-rec dim sizes too large), else return NC_NOERR. + */ +static int +ncmpii_NC_check_vlens(NC *ncp) +{ + NC_var **vpp; + /* maximum permitted variable size (or size of one record's worth + of a record variable) in bytes. This is different for format 1 + and format 2. */ + size_t vlen_max; + size_t ii; + size_t large_vars_count; + size_t rec_vars_count; + int last=-1; + + if(ncp->vars.nelems == 0) + return NC_NOERR; + + if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) { + /* CDF2 format and LFS */ + vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */ + } else { + /* CDF1 format */ + vlen_max = X_INT_MAX - 3; + } + /* Loop through vars, first pass is for non-record variables. */ + large_vars_count = 0; + rec_vars_count = 0; + vpp = ncp->vars.value; + for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { + if( !IS_RECVAR(*vpp) ) { + last = 0; + if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) { + large_vars_count++; + last = 1; + } + } else { + rec_vars_count++; + } + } + /* OK if last non-record variable size too large, since not used to + compute an offset */ + if( large_vars_count > 1) { /* only one "too-large" variable allowed */ + return NC_EVARSIZE; + } + /* and it has to be the last one */ + if( large_vars_count == 1 && last == 0) { + return NC_EVARSIZE; + } + if( rec_vars_count > 0 ) { + /* and if it's the last one, there can't be any record variables */ + if( large_vars_count == 1 && last == 1) { + return NC_EVARSIZE; + } + /* Loop through vars, second pass is for record variables. */ + large_vars_count = 0; + vpp = ncp->vars.value; + for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { + if( IS_RECVAR(*vpp) ) { + last = 0; + if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) { + large_vars_count++; + last = 1; + } + } + } + /* OK if last record variable size too large, since not used to + compute an offset */ + if( large_vars_count > 1) { /* only one "too-large" variable allowed */ + return NC_EVARSIZE; + } + /* and it has to be the last one */ + if( large_vars_count == 1 && last == 0) { + return NC_EVARSIZE; + } + } + return NC_NOERR; +} +#endif + +int +ncmpii_NC_enddef(NC *ncp) { + int status = NC_NOERR; + MPI_Comm comm; + int mpireturn; + int rank; + + assert(!NC_readonly(ncp)); + assert(NC_indef(ncp)); + + comm = ncp->nciop->comm; + + MPI_Comm_rank(comm, &rank); + + /* NC_begins: pnetcdf doesn't expose an equivalent to nc__enddef, but we can + * acomplish the same thing with calls to NC_begins */ + NC_begins(ncp, 0, 512, 0, 512); + + /* serial netcdf calls a check on dimension lenghths here */ + + /* To be updated */ + if(ncp->old != NULL) { + /* a plain redef, not a create */ + assert(!NC_IsNew(ncp)); + assert(fIsSet(ncp->flags, NC_INDEF)); + assert(ncp->begin_rec >= ncp->old->begin_rec); + assert(ncp->begin_var >= ncp->old->begin_var); + assert(ncp->vars.nelems >= ncp->old->vars.nelems); + + mpireturn = MPI_File_sync(ncp->nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + return NC_EWRITE; + } + /* + * Barrier needed switching between read and write + * Important, MPI_File_sync doesn't ensure barrier + */ + MPI_Barrier(comm); + + if(ncp->vars.nelems != 0) { + if(ncp->begin_rec > ncp->old->begin_rec) { + if (ncp->vars.nelems == ncp->old->vars.nelems) { + status = move_data_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } else { + status = move_recs_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + if(ncp->begin_var > ncp->old->begin_var) { + status = move_vars_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + } + } else { /* ... ncp->begin_rec > ncp->old->begin_rec */ + /* Even if (ncp->begin_rec == ncp->old->begin_rec) + * and (ncp->begin_var == ncp->old->begin_var) + * might still have added a new record variable + */ + if(ncp->recsize > ncp->old->recsize) { + status = move_recs_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + } + } + } /* ... ncp->old != NULL */ + + status = write_NC(ncp); + if (status != NC_NOERR) + return status; + + if(ncp->old != NULL) { + ncmpii_free_NC(ncp->old); + ncp->old = NULL; + } + + fClr(ncp->flags, NC_CREAT | NC_INDEF); + mpireturn = MPI_File_sync(ncp->nciop->collective_fh); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + return NC_EWRITE; + } + + MPI_Barrier(comm); + + return NC_NOERR; +} + +#if 0 +static int +enddef(NC *ncp) +{ + assert(!NC_readonly(ncp)); + if(!NC_indef(ncp)) + return(NC_ENOTINDEFINE); + + NC_begins(ncp, 0, 1, 0, 1); + + if(ncp->old != NULL) + { + ncmpii_free_NC(ncp->old); + ncp->old = NULL; + } + + fClr(ncp->flags, NC_CREAT | NC_INDEF); + + return NC_NOERR; +} +#endif + + +/* Public */ + +int +ncmpii_NC_close(NC *ncp) { + int status = NC_NOERR; + + if(NC_indef(ncp)) { + status = ncmpii_NC_enddef(ncp); /* TODO: defaults */ + if(status != NC_NOERR ) { + /* To do: Abort new definition, if any */ + if (ncp->old != NULL) { + ncmpii_free_NC(ncp->old); + ncp->old = NULL; + fClr(ncp->flags, NC_INDEF); + } + } + } + else if(!NC_readonly(ncp)) { + status = ncmpii_NC_sync(ncp); + if (status != NC_NOERR) + return status; + } + + (void) ncmpiio_close(ncp->nciop, 0); + ncp->nciop = NULL; + + ncmpii_del_from_NCList(ncp); + + ncmpii_free_NC(ncp); + + return status; +} + +int +ncmpi_inq(int ncid, + int *ndimsp, + int *nvarsp, + int *nattsp, + int *xtendimp) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(ndimsp != NULL) + *ndimsp = (int) ncp->dims.nelems; + if(nvarsp != NULL) + *nvarsp = (int) ncp->vars.nelems; + if(nattsp != NULL) + *nattsp = (int) ncp->attrs.nelems; + if(xtendimp != NULL) + *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL); + + return NC_NOERR; +} + +int +ncmpi_inq_ndims(int ncid, int *ndimsp) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(ndimsp != NULL) + *ndimsp = (int) ncp->dims.nelems; + + return NC_NOERR; +} + +int +ncmpi_inq_nvars(int ncid, int *nvarsp) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(nvarsp != NULL) + *nvarsp = (int) ncp->vars.nelems; + + return NC_NOERR; +} + +int +ncmpi_inq_natts(int ncid, int *nattsp) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(nattsp != NULL) + *nattsp = (int) ncp->attrs.nelems; + + return NC_NOERR; +} + +int +ncmpi_inq_unlimdim(int ncid, int *xtendimp) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(xtendimp != NULL) + *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL); + + return NC_NOERR; +} + +#if 0 +static int +nc_sync(int ncid) +{ + int status; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + if(NC_readonly(ncp)) + { + return ncmpii_read_NC(ncp); + } + /* else, read/write */ + + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + + return ncp->nciop->sync(ncp->nciop); +} + + +static int +nc_set_fill(int ncid, + int fillmode, int *old_mode_ptr) +{ + int status; + NC *ncp; + int oldmode; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL; + + if(fillmode == NC_NOFILL) + { + fSet(ncp->flags, NC_NOFILL); + } + else if(fillmode == NC_FILL) + { + if(fIsSet(ncp->flags, NC_NOFILL)) + { + /* + * We are changing back to fill mode + * so do a sync + */ + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + fClr(ncp->flags, NC_NOFILL); + } + else + { + return NC_EINVAL; /* Invalid fillmode */ + } + + if(old_mode_ptr != NULL) + *old_mode_ptr = oldmode; + + return NC_NOERR; +} +#endif + +/*ARGSUSED*/ + Index: /tags/v1-0-3/src/lib/Makefile.in =================================================================== --- /tags/v1-0-3/src/lib/Makefile.in (revision 512) +++ /tags/v1-0-3/src/lib/Makefile.in (revision 512) @@ -0,0 +1,118 @@ +# $Id$ +# +# Makefile for netcdf libsrc +# + +srcdir = @srcdir@ +VPATH = @srcdir@ +INSTALL = @INSTALL@ + +# generated by configure, so it's in the build dir, not srcdirr +include ../../macros.make + +INCLUDES = -I. + +LIBRARY = libpnetcdf.a +PROGRAM = ncvalid +ld_netcdf = -L. -lpnetcdf + +HEADER = pnetcdf.h + +MANUAL = pnetcdf.3 + +LIB_CSRCS = \ + mpinetcdf.c \ + header.c \ + mpincio.c \ + attr.c \ + dim.c \ + error.c \ + nc.c \ + ncx.c \ + string.c \ + var.c \ + ncmpidtype.c + +PACKING_LIST = \ + $(LIB_CSRCS) \ + depend \ + fbits.h \ + Makefile \ + nc.h \ + ncconfig.in \ + ncio.h \ + ncx.h \ + pnetcdf.3 \ + pnetcdf.h \ + rnd.h \ + ncmpidtype.h + +LIB_OBJS = $(LIB_CSRCS:.c=.o) + +PROG_CSRCS = \ + validator.c \ + header.c \ + mpincio.c \ + attr.c \ + dim.c \ + nc.c \ + ncx.c \ + string.c \ + error.c \ + var.c + +PROG_OBJS = $(PROG_CSRCS:.c=.o) + +GARBAGE = + +DIST_GARBAGE = ncconfig.h + + +all: $(LIBRARY) $(MANUAL) $(PROGRAM) + +install: + $(INSTALL) -d -m 755 $(LIBDIR) + $(INSTALL) -m 644 $(LIBRARY) $(LIBDIR)/$(LIBRARY) + + $(INSTALL) -d -m 755 $(INCDIR) + $(INSTALL) -m 644 $(srcdir)/$(HEADER) $(INCDIR)/$(HEADER) + + $(INSTALL) -d -m 755 $(MANDIR)/man3 + $(INSTALL) -m 644 $(MANUAL) $(MANDIR)/man3/$(MANUAL) + + $(INSTALL) -d $(BINDIR) + $(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM) + +uninstall: + -rm -f $(LIBDIR)/$(LIBRARY) + -rm -f $(INCDIR)/$(HEADER) + -rm -f $(MANDIR)/man3/$(MANUAL) + -rm -f $(BINDIR)/$(PROGRAM) + + + +# The rule for generating the manual page is here for completeness only. +# The manual page is actually part of the distribution so that we don't +# have to depend on the non-POSIX utility m4(1). +# +$(MANUAL): $(srcdir)/../../man/netcdf.m4 + $(M4) $(M4FLAGS) -DAPI=C $? >$@ || rm $@ + +$(PROGRAM): $(PROG_OBJS) + $(LINK.c) $(PROG_OBJS) $(LIBS) + +include $(srcdir)/../../rules.make + +.SUFFIXES: .ln +LINT = lint +LINT.c = $(LINT) $(LINTFLAGS) $(CPPFLAGS) +.c.ln: + $(LINT.c) -c $< + +llib-lpnetcdf.ln: $(LIB_CSRCS) + $(LINT.c) $(LIB_CSRCS) -y -o pnetcdf + +lint: llib-lpnetcdf.ln + $(LINT.c) t_nc.c llib-lpnetcdf.ln + +include $(srcdir)/depend Index: /tags/v1-0-3/src/lib/nc.h =================================================================== --- /tags/v1-0-3/src/lib/nc.h (revision 610) +++ /tags/v1-0-3/src/lib/nc.h (revision 610) @@ -0,0 +1,630 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ +#ifndef _NC_H_ +#define _NC_H_ + +/* + * netcdf library 'private' data structures, objects and interfaces + */ + +#include "ncconfig.h" + +#include /* size_t */ +#include /* off_t */ +#include "pnetcdf.h" +#include "ncio.h" /* ncio */ +#include "fbits.h" + + +#ifndef NC_ARRAY_GROWBY +/* XXX: this seems really low. do we end up spending a ton of time mallocing? + * could we reduce that by increasing this to something 21st century? */ +#define NC_ARRAY_GROWBY 4 +#endif + +/* + * The extern size of an empty + * netcdf version 1 file. + * The initial value of ncp->xsz. + */ +#define MIN_NC_XSZ 32 + +typedef struct NC NC; /* forward reference */ + +/* + * The internal data types + */ +typedef enum { + NC_UNSPECIFIED = 0, +/* future NC_BITFIELD = 7, */ +/* NC_STRING = 8, */ + NC_DIMENSION = 10, + NC_VARIABLE = 11, + NC_ATTRIBUTE = 12 +} NCtype; + + +/* + * Counted string for names and such + */ +typedef struct { + /* all xdr'd */ + size_t nchars; + char *cp; +} NC_string; + +extern NC * +ncmpii_new_NC(const size_t *chunkp); + +extern NC * +ncmpii_dup_NC(const NC *ref); + +/* Begin defined in string.c */ +extern void +ncmpii_free_NC_string(NC_string *ncstrp); + +extern int +ncmpii_NC_check_name(const char *name); + +extern NC_string * +ncmpii_new_NC_string(size_t slen, const char *str); + +extern int +ncmpii_set_NC_string(NC_string *ncstrp, const char *str); + +/* End defined in string.c */ + +/* + * NC dimension stucture + */ +typedef struct { + /* all xdr'd */ + NC_string *name; + size_t size; +} NC_dim; + +typedef struct NC_dimarray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_DIMENSION */ + size_t nelems; /* length of the array */ + NC_dim **value; +} NC_dimarray; + +/* Begin defined in dim.c */ + +extern void +ncmpii_free_NC_dim(NC_dim *dimp); + +extern NC_dim * +ncmpii_new_x_NC_dim(NC_string *name); + +extern int +ncmpii_find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp); + +/* dimarray */ + +extern void +ncmpii_free_NC_dimarrayV0(NC_dimarray *ncap); + +extern void +ncmpii_free_NC_dimarrayV(NC_dimarray *ncap); + +extern int +ncmpii_dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref); + +extern NC_dim * +ncmpii_elem_NC_dimarray(const NC_dimarray *ncap, size_t elem); + +extern int +ncmpi_def_dim(int ncid, const char *name, MPI_Offset size, int *dimidp); + +extern int +ncmpi_rename_dim( int ncid, int dimid, const char *newname); + +extern int +ncmpi_inq_dimid(int ncid, const char *name, int *dimid_ptr); + +extern int +ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *sizep); + +extern int +ncmpi_inq_dimname(int ncid, int dimid, char *name); + +extern int +ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp); +/* End defined in dim.c */ + +/* + * NC attribute + */ +typedef struct { + size_t xsz; /* amount of space at xvalue */ + /* below gets xdr'd */ + NC_string *name; + nc_type type; /* the discriminant */ + size_t nelems; /* length of the array */ + void *xvalue; /* the actual data, in external representation */ +} NC_attr; + +typedef struct NC_attrarray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_ATTRIBUTE */ + size_t nelems; /* length of the array */ + NC_attr **value; +} NC_attrarray; + +/* Begin defined in attr.c */ + +extern void +ncmpii_free_NC_attr(NC_attr *attrp); + +extern NC_attr * +ncmpii_new_x_NC_attr( + NC_string *strp, + nc_type type, + size_t nelems); + +extern NC_attr ** +ncmpii_NC_findattr(const NC_attrarray *ncap, const char *name); + +/* attrarray */ + +extern void +ncmpii_free_NC_attrarrayV0(NC_attrarray *ncap); + +extern void +ncmpii_free_NC_attrarrayV(NC_attrarray *ncap); + +extern int +ncmpii_dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref); + +extern NC_attr * +ncmpii_elem_NC_attrarray(const NC_attrarray *ncap, size_t elem); + +extern int +ncmpi_put_att_text(int ncid, int varid, const char *name, + MPI_Offset nelems, const char *value); + +extern int +ncmpi_get_att_text(int ncid, int varid, const char *name, char *str); + +extern int +ncmpi_put_att_schar(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const signed char *value); + +extern int +ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *tp); + +extern int +ncmpi_put_att_uchar(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const unsigned char *value); + +extern int +ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp); + +extern int +ncmpi_put_att_short(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const short *value); + +extern int +ncmpi_get_att_short(int ncid, int varid, const char *name, short *tp); + +extern int +ncmpi_put_att_int(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const int *value); + +extern int +ncmpi_get_att_int(int ncid, int varid, const char *name, int *tp); + +extern int +ncmpi_put_att_long(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const long *value); + +extern int +ncmpi_get_att_long(int ncid, int varid, const char *name, long *tp); + +extern int +ncmpi_put_att_float(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const float *value); +extern int +ncmpi_get_att_float(int ncid, int varid, const char *name, float *tp); +extern int +ncmpi_put_att_double(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const double *value); +extern int +ncmpi_get_att_double(int ncid, int varid, const char *name, double *tp); + +extern int +ncmpi_inq_attid(int ncid, int varid, const char *name, int *attnump); + +extern int +ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep); + +extern int +ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp); + +extern int +ncmpi_inq_att(int ncid, int varid, const char *name, + nc_type *datatypep, MPI_Offset *lenp); + +extern int +ncmpi_copy_att(int ncid_in, int varid_in, const char *name, + int ncid_out, int ovarid); + +extern int +ncmpi_rename_att( int ncid, int varid, const char *name, const char *newname); + +extern int +ncmpi_del_att(int ncid, int varid, const char *name); + +extern int +ncmpi_inq_attname(int ncid, int varid, int attnum, char *name); +/* End defined in attr.c */ +/* + * NC variable: description and data + */ +typedef struct { + size_t xsz; /* xszof 1 element */ + size_t *shape; /* compiled info: dim->size of each dim */ + size_t *dsizes; /* compiled info: the right to left product of shape */ + /* below gets xdr'd */ + NC_string *name; + /* next two: formerly NC_iarray *assoc */ /* user definition */ + size_t ndims; /* assoc->count */ + int *dimids; /* assoc->value */ + NC_attrarray attrs; + nc_type type; /* the discriminant */ + size_t len; /* the total length originally allocated */ + MPI_Offset begin; +} NC_var; + +typedef struct NC_vararray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_VARIABLE */ + size_t nelems; /* length of the array */ + NC_var **value; +} NC_vararray; + +/* Begin defined in var.c */ + +extern void +ncmpii_free_NC_var(NC_var *varp); + +extern NC_var * +ncmpii_new_x_NC_var( + NC_string *strp, + size_t ndims); + +/* vararray */ + +extern void +ncmpii_free_NC_vararrayV0(NC_vararray *ncap); + +extern void +ncmpii_free_NC_vararrayV(NC_vararray *ncap); + +extern int +ncmpii_dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref); + +extern int +ncmpii_NC_var_shape(NC_var *varp, const NC_dimarray *dims); + +extern int +ncmpii_NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp); + +extern int +ncmpii_NC_check_vlen(NC_var *varp, size_t vlen_max); + +extern NC_var * +ncmpii_NC_lookupvar(NC *ncp, int varid); + +extern int +ncmpi_def_var( int ncid, const char *name, nc_type type, + int ndims, const int *dimids, int *varidp); + +extern int +ncmpi_rename_var(int ncid, int varid, const char *newname); + +extern int +ncmpi_inq_var(int ncid, int varid, char *name, nc_type *typep, + int *ndimsp, int *dimids, int *nattsp); + +extern int +ncmpi_inq_varid(int ncid, const char *name, int *varid_ptr); + +extern int +ncmpi_inq_varname(int ncid, int varid, char *name); + +extern int +ncmpi_inq_vartype(int ncid, int varid, nc_type *typep); + +extern int +ncmpi_inq_varndims(int ncid, int varid, int *ndimsp); + +extern int +ncmpi_inq_vardimid(int ncid, int varid, int *dimids); + +extern int +ncmpi_inq_varnatts(int ncid, int varid, int *nattsp); + +extern int +ncmpi_rename_var(int ncid, int varid, const char *newname); +/* End defined in var.c */ + +#define IS_RECVAR(vp) \ + ((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 ) + +struct NC { + /* links to make list of open netcdf's */ + struct NC *next; + struct NC *prev; + /* contains the previous NC during redef. */ + struct NC *old; + /* flags */ +#define NC_INDEP 1 /* in independent data mode, cleared by endindep */ +#define NC_CREAT 2 /* in create phase, cleared by ncenddef */ +#define NC_INDEF 8 /* in define mode, cleared by ncenddef */ +#define NC_NSYNC 0x10 /* synchronise numrecs on change */ +#define NC_HSYNC 0x20 /* synchronise whole header on change */ +#define NC_NDIRTY 0x40 /* numrecs has changed */ +#define NC_HDIRTY 0x80 /* header info has changed */ +/* NC_NOFILL in netcdf.h, historical interface */ + int flags; + ncio *nciop; + size_t chunk; /* largest extent this layer will request from ncio->get() */ + MPI_Offset xsz; /* external size of this header, <= var[0].begin */ + MPI_Offset begin_var; /* position of the first (non-record) var */ + MPI_Offset begin_rec; /* position of the first 'record' */ + /* don't constrain maximu sinze of record unnecessarily */ + MPI_Offset recsize; /* length of 'record' */ + /* below gets xdr'd */ + size_t numrecs; /* number of 'records' allocated */ + NC_dimarray dims; + NC_attrarray attrs; + NC_vararray vars; +}; + +#define NC_readonly(ncp) \ + (!fIsSet(ncp->nciop->ioflags, NC_WRITE)) + +#define NC_IsNew(ncp) \ + fIsSet((ncp)->flags, NC_CREAT) + +#define NC_indep(ncp) \ + fIsSet((ncp)->flags, NC_INDEP) + +#define NC_indef(ncp) \ + (NC_IsNew(ncp) || fIsSet((ncp)->flags, NC_INDEF)) + +#define set_NC_ndirty(ncp) \ + fSet((ncp)->flags, NC_NDIRTY) + +#define NC_ndirty(ncp) \ + fIsSet((ncp)->flags, NC_NDIRTY) + +#define set_NC_hdirty(ncp) \ + fSet((ncp)->flags, NC_HDIRTY) + +#define NC_hdirty(ncp) \ + fIsSet((ncp)->flags, NC_HDIRTY) + +#define NC_dofill(ncp) \ + (!fIsSet((ncp)->flags, NC_NOFILL)) + +#define NC_doHsync(ncp) \ + fIsSet((ncp)->flags, NC_HSYNC) + +#define NC_doNsync(ncp) \ + fIsSet((ncp)->flags, NC_NSYNC) + +#define NC_get_numrecs(ncp) \ + ((ncp)->numrecs) + +#define NC_set_numrecs(ncp, nrecs) \ + {((ncp)->numrecs = (nrecs));} + +#define NC_increase_numrecs(ncp, nrecs) \ + {if((nrecs) > (ncp)->numrecs) ((ncp)->numrecs = (nrecs));} +/* Begin defined in nc.c */ + +extern int +ncmpii_NC_check_id(int ncid, NC **ncpp); + +extern int +ncmpii_cktype(nc_type datatype); + +extern size_t +ncmpix_howmany(nc_type type, size_t xbufsize); + +extern int +ncmpii_read_numrecs(NC *ncp); + +extern int +ncmpii_write_numrecs(NC *ncp); + +extern int +ncmpii_NC_sync(NC *ncp); + +extern void +ncmpii_free_NC(NC *ncp); + +extern void +ncmpii_add_to_NCList(NC *ncp); + +extern void +ncmpii_del_from_NCList(NC *ncp); + +extern int +ncmpii_read_NC(NC *ncp); + +extern int +ncmpii_NC_enddef(NC *ncp); + +extern int +ncmpii_NC_close(NC *ncp); + +extern int +ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *xtendimp); + +extern int +ncmpi_inq_ndims(int ncid, int *ndimsp); + +extern int +ncmpi_inq_nvars(int ncid, int *nvarsp); + +extern int +ncmpi_inq_natts(int ncid, int *nattsp); + +extern int +ncmpi_inq_unlimdim(int ncid, int *xtendimp); + +extern int +ncmpi_get_default_format(void); + +/* End defined in nc.c */ +/* Begin defined in v1hpg.c */ + +extern size_t +ncx_len_NC(const NC *ncp, size_t sizeof_off_t); + +extern int +ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent); + +extern int +nc_get_NC( NC *ncp); + +/* End defined in v1hpg.c */ + +#if 0 +/* Begin defined in putget.c */ + +extern int +ncmpii_fill_NC_var(NC *ncp, const NC_var *varp, size_t recno); + +extern int +ncmpii_inq_rec(int ncid, size_t *nrecvars, int *recvarids, size_t *recsizes); + +extern int +ncmpii_get_rec(int ncid, size_t recnum, void **datap); + +extern int +ncmpii_put_rec(int ncid, size_t recnum, void *const *datap); +#endif + +/* End defined in putget.c */ + +/* Begin defined in header.c */ +typedef struct bufferinfo { + ncio *nciop; + MPI_Offset offset; /* current read/write offset in the file */ + int version; /* either 1 for normal netcdf or + 2 for 8-byte offset version */ + void *base; /* beginning of read/write buffer */ + void *pos; /* current position in buffer */ + size_t size; /* size of the buffer */ + size_t index; /* index of current position in buffer */ +} bufferinfo; + +extern size_t +ncmpix_len_nctype(nc_type type); + +#if 0 +extern int +hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap); +#endif + +extern size_t +ncmpii_hdr_len_NC(const NC *ncp, size_t sizeof_off_t); + +extern int +ncmpii_hdr_get_NC(NC *ncp); + +extern int +ncmpii_hdr_put_NC(NC *ncp, void *buf); + +extern int +ncmpii_NC_computeshapes(NC *ncp); + +/* end defined in header.c */ + +/* begin defined in mpincio.c */ +extern int +ncmpiio_create(MPI_Comm comm, const char *path, int ioflags, MPI_Info info, + ncio **nciopp); + +extern int +ncmpiio_open(MPI_Comm comm, const char *path, int ioflags, MPI_Info info, + ncio **nciopp); +extern int +ncmpiio_sync(ncio *nciop); + +extern int +ncmpiio_move(ncio *const nciop, off_t to, off_t from, size_t nbytes); + +extern int +NC_computeshapes(NC *ncp); + +/* end defined in mpincio.h */ + +/* begin defined in error.c */ +const char * nc_strerror(int err); + +void ncmpii_handle_error(int rank, int mpi_status, char *msg); +/* end defined in error.c */ +/* + * These functions are used to support + * interface version 2 backward compatiblity. + * N.B. these are tested in ../nc_test even though they are + * not public. So, be careful to change the declarations in + * ../nc_test/tests.h if you change these. + */ + +extern int +ncmpii_put_att(int ncid, int varid, const char *name, nc_type datatype, + size_t len, const void *value); + +extern int +ncmpii_get_att(int ncid, int varid, const char *name, void *value); + +extern int +ncmpii_put_var1(int ncid, int varid, const MPI_Offset *index, const void *value); + +extern int +ncmpii_get_var1(int ncid, int varid, const MPI_Offset *index, void *value); + +extern int +ncmpii_put_vara(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, const void *value); + +extern int +ncmpii_get_vara(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, void *value); + +extern int +ncmpii_put_vars(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, const ptrdiff_t *stride, + const void * value); + +extern int +ncmpii_get_vars(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, const ptrdiff_t *stride, + void * value); + +extern int +ncmpii_put_varm(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, const ptrdiff_t *stride, + const ptrdiff_t * map, const void *value); + +extern int +ncmpii_get_varm(int ncid, int varid, + const MPI_Offset *start, const MPI_Offset *count, const ptrdiff_t *stride, + const ptrdiff_t * map, void *value); + + +#endif /* _NC_H_ */ Index: /tags/v1-0-3/src/lib/string.c =================================================================== --- /tags/v1-0-3/src/lib/string.c (revision 465) +++ /tags/v1-0-3/src/lib/string.c (revision 465) @@ -0,0 +1,127 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#include "nc.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include "ncx.h" +#include "rnd.h" + + +/* + * Free string, and, if needed, its values. + * Formerly +NC_free_string() + */ +void +ncmpii_free_NC_string(NC_string *ncstrp) +{ + if(ncstrp==NULL) + return; + free(ncstrp); +} + + +/* + * Verify that a name string is valid + * CDL syntax, eg, all the characters are + * alphanumeric, '-', '_', or '.'. + * Also permit ':', '@', '(', or ')' in names for chemists currently making + * use of these characters, but don't document until ncgen and ncdump can + * also handle these characters in names. + */ +int +ncmpii_NC_check_name(const char *name) +{ + const char *cp = name; + assert(name != NULL); + + if(*name == 0) + return NC_EBADNAME; /* empty names disallowed */ + + for(; *cp != 0; cp++) + { + int ch = *cp; + if(!isalnum(ch)) + { + if(ch != '_' && ch != '-' && ch != '+' && ch != '.' && + ch != ':' && ch != '@' && ch != '(' && + ch != ')') + return NC_EBADNAME; + } + } + if(cp - name > NC_MAX_NAME) + return NC_EMAXNAME; + + return NC_NOERR; +} + + +/* + * Allocate a NC_string structure large enough + * to hold slen characters. + * Formerly +NC_new_string(count, str) + */ +NC_string * +ncmpii_new_NC_string(size_t slen, const char *str) +{ + NC_string *ncstrp; + size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1; + +#if 0 + sz = _RNDUP(sz, X_ALIGN); +#endif + + ncstrp = (NC_string *)malloc(sz); + if( ncstrp == NULL ) + return NULL; + (void) memset(ncstrp, 0, sz); + + ncstrp->nchars = sz - M_RNDUP(sizeof(NC_string)) - 1; + assert(ncstrp->nchars + 1 > slen); + ncstrp->cp = (char *)ncstrp + M_RNDUP(sizeof(NC_string)); + + if(str != NULL && *str != 0) + { + (void) strncpy(ncstrp->cp, str, ncstrp->nchars +1); + ncstrp->cp[ncstrp->nchars] = 0; + } + + return(ncstrp); +} + + +/* + * If possible, change the value of an NC_string to 'str'. + * + * Formerly +NC_re_string() + */ +int +ncmpii_set_NC_string(NC_string *ncstrp, const char *str) +{ + size_t slen; + size_t diff; + + assert(str != NULL && *str != 0); + + slen = strlen(str); + + if(ncstrp->nchars < slen) + return NC_ENOTINDEFINE; + + (void) memcpy(ncstrp->cp, str, slen); + diff = ncstrp->nchars - slen; + if(diff != 0) + (void) memset(ncstrp->cp + slen, 0, diff); + + return NC_NOERR; +} Index: /tags/v1-0-3/src/lib/mpinetcdf.c =================================================================== --- /tags/v1-0-3/src/lib/mpinetcdf.c (revision 643) +++ /tags/v1-0-3/src/lib/mpinetcdf.c (revision 643) @@ -0,0 +1,11975 @@ +/********************************************************************************* + * + * This file is created by Northwestern University and Argonne National + * Laboratory + * + ********************************************************************************/ + +#include "nc.h" +#include "ncx.h" +#include +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include "ncmpidtype.h" + +/* Local prototypes */ +static int length_of_mpitype(MPI_Datatype); + +const char * +ncmpi_inq_libvers(void) { + return "version = 1.0.3 of 8 Dec 2008"; +} + +/* Prototypes for functions used only in this file */ +static int echar(nc_type nctype,MPI_Datatype mpitype); +static int need_convert(nc_type nctype,MPI_Datatype mpitype); +static int need_swap(nc_type nctype,MPI_Datatype mpitype); +static int x_putn_schar(void *xbuf, const void *buf, int nelems, + MPI_Datatype datatype); +static int x_putn_short(void *xbuf, const void *buf, int nelems, + MPI_Datatype datatype); +static int x_putn_int(void *xbuf, const void *buf, int nelems, + MPI_Datatype datatype); +static int x_putn_float(void *xbuf, const void *buf, int nelems, + MPI_Datatype datatype); +static int x_putn_double(void *xbuf, const void *buf, int nelems, + MPI_Datatype datatype); +static int x_getn_schar(const void *xbuf, void *buf, int nelems, + MPI_Datatype datatype); +static int x_getn_short(const void *xbuf, void *buf, int nelems, + MPI_Datatype datatype); +static int x_getn_int(const void *xbuf, void *buf, int nelems, + MPI_Datatype datatype); +static int x_getn_float(const void *xbuf, void *buf, int nelems, + MPI_Datatype datatype); +static int x_getn_double(const void *xbuf, void *buf, int nelems, + MPI_Datatype datatype); +static int set_var1_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, + const MPI_Offset index[]); +static int set_var_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp); +static int set_vara_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, + const MPI_Offset start[], const MPI_Offset count[], + int getnotput); +static int set_vars_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, + const MPI_Offset start[], const MPI_Offset count[], + const MPI_Offset stride[], int getnotput); +static int check_mpifh(NC* ncp, MPI_File *mpifh, MPI_Comm comm, + int collective); + +/* Begin Of Dataset Functions */ + +int +ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp) { + int status = NC_NOERR; + size_t sizeof_off_t = 0; + size_t chunksize=4098; /* might be a good thing to hint later */ + NC *ncp; + + ncp = ncmpii_new_NC(&chunksize); + if(ncp == NULL) + return NC_ENOMEM; + + assert(ncp->flags == 0); + + if (fIsSet(cmode, NC_64BIT_OFFSET)) { + /* unlike serial netcdf, we will not bother to support + * NC_64BIT_OFFSET on systems with off_t smaller than 8 bytes. + * serial netcdf has proven it's possible if datasets are small, but + * that's a hassle we don't want to worry about */ + if (sizeof(off_t) != 8) + return NC_ESMALL; + fSet(ncp->flags, NC_64BIT_OFFSET); + sizeof_off_t = 8; + } else { + sizeof_off_t = 4; + } + assert(ncp->xsz = ncmpii_hdr_len_NC(ncp, sizeof_off_t)); + + fSet(ncp->flags, NC_NOFILL); + fSet(ncp->flags, NC_HSYNC); + + status = ncmpiio_create(comm, path, cmode, info, &ncp->nciop); + if(status != NC_NOERR) { + ncmpii_free_NC(ncp); + return status; + } + + fSet(ncp->flags, NC_CREAT); + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) { + /* + * NC_SHARE implies sync up the number of records as well. + * (File format version one.) + * Note that other header changes are not shared + * automatically. Some sort of IPC (external to this package) + * would be used to trigger a call to ncmpi_sync(). + */ + fSet(ncp->flags, NC_NSYNC); + } + + ncmpii_add_to_NCList(ncp); + *ncidp = ncp->nciop->fd; + + return status; +} + +int +ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp) { + int status = NC_NOERR; + NC *ncp; + size_t chunksize=4098; /* might be a good thing to hint later */ + + ncp = ncmpii_new_NC(&chunksize); + if(ncp == NULL) + return NC_ENOMEM; + + status = ncmpiio_open(comm, path, omode, info, &ncp->nciop); + if(status != NC_NOERR) { + ncmpii_free_NC(ncp); + return status; + } + + assert(ncp->flags == 0); + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) { + /* + * NC_SHARE implies sync up the number of records as well. + * (File format version one.) + * Note that other header changes are not shared + * automatically. Some sort of IPC (external to this package) + * would be used to trigger a call to ncmpi_sync(). + */ + fSet(ncp->flags, NC_NSYNC); + } + + status = ncmpii_hdr_get_NC(ncp); + if (status != NC_NOERR) { + ncmpiio_close(ncp->nciop, 0); + ncmpii_free_NC(ncp); + return status; + } + + ncmpii_add_to_NCList(ncp); + + *ncidp = ncp->nciop->fd; + + return status; +} + +int +ncmpi_get_file_info(int ncid, MPI_Info *info_used) { + int status = NC_NOERR; + int mpireturn; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if (status != NC_NOERR) + return status; + + mpireturn = MPI_File_get_info(ncp->nciop->collective_fh, info_used); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_get_info"); + return NC_EFILE; + } + return status; +} + +int +ncmpi_redef(int ncid) { + int status; + NC *ncp; + int mynumrecs, numrecs; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* ensure exiting define mode always entering collective data mode */ + if(NC_indep(ncp)) + ncmpi_end_indep_data(ncid); + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) { + /* read in from disk */ + status = ncmpii_read_NC(ncp); + if(status != NC_NOERR) + return status; + } else { + + /* collect and set the max numrecs */ + + mynumrecs = ncp->numrecs; + MPI_Allreduce(&mynumrecs, &numrecs, 1, MPI_INT, MPI_MAX, ncp->nciop->comm); + if (numrecs > ncp->numrecs) { + ncp->numrecs = numrecs; + set_NC_ndirty(ncp); + } + } + + ncp->old = ncmpii_dup_NC(ncp); + if(ncp->old == NULL) + return NC_ENOMEM; + + fSet(ncp->flags, NC_INDEF); + + return NC_NOERR; +} + +int +ncmpi_begin_indep_data(int ncid) { + int status = NC_NOERR; + int mpireturn; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indep(ncp)) + return NC_EINDEP; + + if(!NC_readonly(ncp) && NC_collectiveFhOpened(ncp->nciop)) { + mpireturn = MPI_File_sync(ncp->nciop->collective_fh); /* collective */ + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + MPI_Finalize(); + return NC_EFILE; + } + } + + fSet(ncp->flags, NC_INDEP); + + MPI_Barrier(ncp->nciop->comm); + + return status; +} + +int +ncmpi_end_indep_data(int ncid) { + int status = NC_NOERR; + int mpireturn; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (!NC_indep(ncp)) + return NC_ENOTINDEP; + + if(!NC_readonly(ncp) && NC_independentFhOpened(ncp->nciop)) { + mpireturn = MPI_File_sync(ncp->nciop->independent_fh); /* independent */ + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_sync"); + MPI_Finalize(); + return NC_EFILE; + } + } + + fClr(ncp->flags, NC_INDEP); + + MPI_Barrier(ncp->nciop->comm); + + return status; +} + +int +ncmpi_enddef(int ncid) { + int status = NC_NOERR; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return(NC_ENOTINDEFINE); + + return ncmpii_NC_enddef(ncp); +} + +int +ncmpi_sync(int ncid) { + int status = NC_NOERR; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + if(NC_readonly(ncp)) + return ncmpii_read_NC(ncp); + + /* else, read/write */ + + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + + return ncmpiio_sync(ncp->nciop); +} + +int +ncmpi_abort(int ncid) { + /* + * In data mode, same as ncmpiio_close. + * In define mode, descard new definition. + * In create, remove the file. + */ + int status; + NC *ncp; + int doUnlink = 0; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + doUnlink = NC_IsNew(ncp); + + if (ncp->old != NULL) { + /* a plain redef, not a create */ + assert(!NC_IsNew(ncp)); + assert(fIsSet(ncp->flags, NC_INDEF)); + ncmpii_free_NC(ncp->old); + ncp->old = NULL; + fClr(ncp->flags, NC_INDEF); + } + else if (!NC_readonly(ncp) && !NC_indef(ncp)) { + /* data mode, write */ + status = ncmpii_NC_sync(ncp); + if (status != NC_NOERR) + return status; + } + + (void) ncmpiio_close(ncp->nciop, doUnlink); + ncp->nciop = NULL; + + ncmpii_del_from_NCList(ncp); + + ncmpii_free_NC(ncp); + + return NC_NOERR; +} + +int +ncmpi_close(int ncid) { + int status = NC_NOERR; + NC *ncp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + /* release NC object, close the file and write Dirty numrecs if necessary */ + + return ncmpii_NC_close(ncp); +} + +/* ncmpi_delete: + * doesn't do anything to release resources, so call ncmpi_close before calling + * this function. + * + * filename: the name of the + * file we will remove. info: mpi info, in case underlying file system needs + * hints. + */ +int +ncmpi_delete(char *filename, MPI_Info info) +{ + int status = NC_NOERR; + status = MPI_File_delete(filename, MPI_INFO_NULL); + if (status != MPI_SUCCESS) + return NC_EFILE; + return NC_NOERR; +} + +/* ncmpi_set_fill: + * not actually implemented. Anything other than NC_NOFILL is not supported. + * Many codes use NC_NOFILL anyway, so this just gets us more source-portable + * with existings serial netcdf codes. Also provides a placeholder if someday + * someone wants to implement all of set_fill + */ +int +ncmpi_set_fill(int ncid, int fillmode, int *old_mode_ptr) +{ + int status = NC_NOERR; + if (fillmode != NC_NOFILL) + status = NC_EINVAL; + return status; + +} + + +/* End Of Dataset Functions */ + +/* + * MAPPING: MPI DATATYPE <---> NETCDF DATATYPE DESCRIPTION + * MPI_UNSIGNED_CHAR NC_BYTE uchar integer + * MPI_BYTE NC_BYTE schar integer + * MPI_CHAR NC_CHAR char(text) + * MPI_SHORT NC_SHORT short + * MPI_INT NC_INT int + * MPI_FLOAT NC_FLOAT float + * MPI_DOUBLE NC_DOUBLE double + * + * + * Assume: MPI_Datatype and nc_type are both enumerable types + */ + +static int +length_of_mpitype(MPI_Datatype datatype) { + if ( datatype == MPI_UNSIGNED_CHAR || + datatype == MPI_BYTE || + datatype == MPI_CHAR) + return (int) sizeof(char); + else if (datatype == MPI_SHORT) return (int) sizeof(short); + else if (datatype == MPI_INT) return (int) sizeof(int); + else if (datatype == MPI_LONG) return (int) sizeof(long); + else if (datatype == MPI_FLOAT) return (int) sizeof(float); + else if (datatype == MPI_DOUBLE) return (int) sizeof(double); + else + fprintf(stderr, "FIXME: unknown type passed to length_of_mpitype\n"); + + return -1; +} + +static int +echar(nc_type nctype,MPI_Datatype mpitype) { + return ((nctype == NC_CHAR) == (mpitype != MPI_CHAR)); +} + +static int +need_convert(nc_type nctype,MPI_Datatype mpitype) { + return !( (nctype == NC_CHAR && mpitype == MPI_CHAR) || + (nctype == NC_BYTE && mpitype == MPI_BYTE) || + (nctype == NC_BYTE && mpitype == MPI_UNSIGNED_CHAR) || + (nctype == NC_SHORT && mpitype == MPI_SHORT) || + (nctype == NC_INT && mpitype == MPI_INT) || + (nctype == NC_INT && mpitype == MPI_LONG && X_SIZEOF_INT == SIZEOF_LONG) || + (nctype == NC_FLOAT && mpitype == MPI_FLOAT) || + (nctype == NC_DOUBLE && mpitype == MPI_DOUBLE) ); +} + +static int +need_swap(nc_type nctype,MPI_Datatype mpitype) { +#ifdef WORDS_BIGENDIAN + return 0; +#else + return ( (nctype == NC_SHORT && mpitype == MPI_SHORT) || + (nctype == NC_INT && mpitype == MPI_INT) || + (nctype == NC_INT && mpitype == MPI_LONG && X_SIZEOF_INT == SIZEOF_LONG) || + (nctype == NC_FLOAT && mpitype == MPI_FLOAT) || + (nctype == NC_DOUBLE && mpitype == MPI_DOUBLE) ); +#endif +} + +static void +swapn(void *dst, const void *src, size_t nn, int xsize) +{ + int i; + char *op = dst; + const char *ip = src; + while (nn-- != 0) { + for (i=0; inciop)) + || (!collective && !NC_independentFhOpened(ncp->nciop)) ) { + + int mpireturn; + mpireturn = MPI_File_open(comm, (char *)ncp->nciop->path, ncp->nciop->mpiomode, + ncp->nciop->mpiinfo, mpifh); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(comm, &rank); + ncmpii_handle_error(rank, mpireturn, "check_mpifh(): MPI_File_open"); + return NC_ENFILE; + /* To be determined the return error code ???????????? */ + } + + if (collective) + set_NC_collectiveFh(ncp->nciop); + else + set_NC_independentFh(ncp->nciop); + + } + + return NC_NOERR; +} + +/* + * Check whether 'coord' values (indices) are valid for the variable. + */ +static int +NCcoordck(NC *ncp, const NC_var *varp, const MPI_Offset *coord) +{ + const MPI_Offset *ip; + size_t *up; + + if(varp->ndims == 0) + return NC_NOERR; /* 'scalar' variable */ + + if(IS_RECVAR(varp)) + { + if(*coord > X_INT_MAX) + return NC_EINVALCOORDS; /* sanity check */ + if(NC_readonly(ncp) && *coord >= ncp->numrecs) + { + if(!NC_doNsync(ncp)) + return NC_EINVALCOORDS; + /* else */ + { + /* Update from disk and check again */ + const int status = ncmpii_read_numrecs(ncp); + if(status != NC_NOERR) + return status; + if(*coord >= ncp->numrecs) + return NC_EINVALCOORDS; + } + } + ip = coord + 1; + up = varp->shape + 1; + } + else + { + ip = coord; + up = varp->shape; + } + + for(; ip < coord + varp->ndims; ip++, up++) + { + /* cast needed for braindead systems with signed size_t */ + if( *ip >= (unsigned long)*up ) + return NC_EINVALCOORDS; + } + + return NC_NOERR; } + +/* + * Check whether 'edges' are valid for the variable and 'start' + */ +/*ARGSUSED*/ +static int +NCedgeck(const NC *ncp, const NC_var *varp, + const MPI_Offset *start, const MPI_Offset *edges) +{ + const MPI_Offset *const end = start + varp->ndims; + const size_t *shp = varp->shape; + + if(varp->ndims == 0) + return NC_NOERR; /* 'scalar' variable */ + + if(IS_RECVAR(varp)) + { + start++; + edges++; + shp++; + } + + for(; start < end; start++, edges++, shp++) + { + /* cast needed for braindead systems with signed size_t */ + if( *edges > (unsigned long)*shp || *start + *edges > (unsigned long)*shp) + { + return(NC_EEDGE); + } + } + + return NC_NOERR; +} + +#if 1 +/* enabled by Jianwei, 12/21/2004. why disable this? */ +static int +NCstrideedgeck(const NC *ncp, const NC_var *varp, + const MPI_Offset *start, const MPI_Offset *edges, const MPI_Offset *stride) +{ + const MPI_Offset *const end = start + varp->ndims; + const size_t *shp = varp->shape; /* use size_t for now :( */ + + if(varp->ndims == 0) + return NC_NOERR; /* 'scalar' variable */ + + if(IS_RECVAR(varp)) + { + if ( *stride == 0 || *stride >= X_INT_MAX) + /* cast needed for braindead systems with signed size_t */ + return NC_ESTRIDE; + + start++; + edges++; + shp++; + stride++; + } + + for(; start < end; start++, edges++, shp++, stride++) + { + /* cast needed for braindead systems with signed size_t */ + if( (*edges > (unsigned long)*shp) || + (*edges > 0 && *start+1 + (*edges-1) * *stride > (unsigned long)*shp) || + (*edges == 0 && *start > (unsigned long)*shp) ) + { + return(NC_EEDGE); + } + + if ( *stride == 0 || *stride >= X_INT_MAX) + /* cast needed for braindead systems with signed size_t */ + return NC_ESTRIDE; + } + + return NC_NOERR; +} +#endif + +static int +set_var1_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, const MPI_Offset index[]) { + MPI_Offset offset; + int status; + int dim, ndims; + int mpireturn; + + status = NCcoordck(ncp, varp, index); + if (status != NC_NOERR) + return status; + + offset = varp->begin; + + ndims = varp->ndims; + + if (ndims > 0) { + + if (IS_RECVAR(varp)) + offset += index[0] * ncp->recsize; + else + offset += index[ndims-1] * varp->xsz; + + if (ndims > 1) { + if (IS_RECVAR(varp)) + offset += index[ndims - 1] * varp->xsz; + else + offset += index[0] * varp->dsizes[1] * varp->xsz; + + for (dim = 1; dim < ndims - 1; dim++) + offset += index[dim] * varp->dsizes[dim+1] * varp->xsz; + } + + } + + mpireturn = MPI_File_set_view(*mpifh, offset, MPI_BYTE, MPI_BYTE, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EFILE; + } + + return NC_NOERR; +} + +static int +set_var_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp) { + MPI_Offset offset; + int mpireturn; + + offset = varp->begin; + + if (!IS_RECVAR(varp)) { + /* Contiguous file view */ + mpireturn = MPI_File_set_view(*mpifh, offset, MPI_BYTE, MPI_BYTE, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EFILE; + } + + } else { + /* Record variable, Strided file view */ + int ndims; + MPI_Datatype filetype; + MPI_Aint stride; + int blocklen; + + ndims = varp->ndims; + if (ndims > 1) + blocklen = varp->dsizes[1] * varp->xsz; + else + blocklen = varp->xsz; + + stride = ncp->recsize; + + if (ncp->numrecs == 0) + return(NC_NOERR); + +#if (MPI_VERSION < 2) + MPI_Type_hvector(ncp->numrecs, blocklen, stride, MPI_BYTE, &filetype); +#else + MPI_Type_create_hvector(ncp->numrecs, blocklen, stride, MPI_BYTE, &filetype); +#endif + MPI_Type_commit(&filetype); + + mpireturn = MPI_File_set_view(*mpifh, offset, MPI_BYTE, filetype, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EFILE; + } + + MPI_Type_free(&filetype); + } + + return NC_NOERR; +} + +static int +set_vara_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, const MPI_Offset start[], const MPI_Offset count[], int getnotput) { + + MPI_Offset offset; + int status; + int dim, ndims; + int *shape = NULL, *subcount = NULL, *substart = NULL; /* all in bytes */ + MPI_Datatype rectype; + MPI_Datatype filetype; + int mpireturn; + + offset = varp->begin; + + ndims = varp->ndims; + + /* New coordinate/edge check to fix NC_EINVALCOORDS bug */ + status = NCedgeck(ncp, varp, start, count); + if( (status != NC_NOERR) || + (getnotput && IS_RECVAR(varp) && *start + *count > NC_get_numrecs(ncp)) ) + { + status = NCcoordck(ncp, varp, start); + if (status != NC_NOERR) + return status; + else + return NC_EEDGE; + } + +/* Removed to fix NC_EINVALCOORDS bug + + status = NCcoordck(ncp, varp, start); + if (status != NC_NOERR) + return status; + + status = NCedgeck(ncp, varp, start, count); + if(status != NC_NOERR) + return status; + + if (getnotput && IS_RECVAR(varp) && *start + *count > NC_get_numrecs(ncp)) + return NC_EEDGE; +*/ + + if (ndims == 0) { + + /* scalar variable */ + filetype = MPI_BYTE; + + } else { + + /* if ndims == 0, all below pointers would be null */ + + shape = (int *)malloc(sizeof(int) * ndims); + subcount = (int *)malloc(sizeof(int) * ndims); + substart = (int *)malloc(sizeof(int) * ndims); + + dim = 0; + while (dim < ndims && count[dim] > 0) dim++; + + if (dim < ndims) { + + /* 0 size data */ + filetype = MPI_BYTE; + + } else { + + if (IS_RECVAR(varp)) { + subcount[0] = count[0]; + substart[0] = 0; + shape[0] = subcount[0]; + + if (ncp->recsize <= varp->len) { + + /* the only record variable */ + + if (varp->ndims == 1) { + shape[0] *= varp->xsz; + subcount[0] *= varp->xsz; + } else { + for (dim = 1; dim < ndims-1; dim++) { + shape[dim] = varp->shape[dim]; + subcount[dim] = count[dim]; + substart[dim] = start[dim]; + } + shape[dim] = varp->xsz * varp->shape[dim]; + subcount[dim] = varp->xsz * count[dim]; + substart[dim] = varp->xsz * start[dim]; + } + offset += start[0] * ncp->recsize; + + MPI_Type_create_subarray(ndims, shape, subcount, substart, + MPI_ORDER_C, MPI_BYTE, &filetype); + + MPI_Type_commit(&filetype); + } else { + + /* more than one record variables */ + + /* TODO: would it make sense here to automatically set the + * cb_buffer size to one record? We have all the information + * needed to do so..*/ + + offset += start[0] * ncp->recsize; + if (varp->ndims == 1) { +#if (MPI_VERSION < 2) + MPI_Type_hvector(subcount[0], varp->xsz, ncp->recsize, + MPI_BYTE, &filetype); +#else + MPI_Type_create_hvector(subcount[0], varp->xsz, ncp->recsize, + MPI_BYTE, &filetype); +#endif + MPI_Type_commit(&filetype); + + } else { + for (dim = 1; dim < ndims-1; dim++) { + shape[dim] = varp->shape[dim]; + subcount[dim] = count[dim]; + substart[dim] = start[dim]; + } + shape[dim] = varp->xsz * varp->shape[dim]; + subcount[dim] = varp->xsz * count[dim]; + substart[dim] = varp->xsz * start[dim]; + + MPI_Type_create_subarray(ndims-1, shape+1, subcount+1, substart+1, + MPI_ORDER_C, MPI_BYTE, &rectype); + MPI_Type_commit(&rectype); +#if (MPI_VERSION < 2) + MPI_Type_hvector(subcount[0], 1, ncp->recsize, rectype, &filetype); +#else + MPI_Type_create_hvector(subcount[0], 1, ncp->recsize, rectype, &filetype); +#endif + MPI_Type_commit(&filetype); + MPI_Type_free(&rectype); + } + } + + } else { + + /* non record variable */ + + for (dim = 0; dim < ndims-1; dim++ ) { + shape[dim] = varp->shape[dim]; + subcount[dim] = count[dim]; + substart[dim] = start[dim]; + } + + shape[dim] = varp->xsz * varp->shape[dim]; + subcount[dim] = varp->xsz * count[dim]; + substart[dim] = varp->xsz * start[dim]; + + MPI_Type_create_subarray(ndims, shape, subcount, substart, + MPI_ORDER_C, MPI_BYTE, &filetype); + + MPI_Type_commit(&filetype); + } + } + } + + mpireturn = MPI_File_set_view(*mpifh, offset, MPI_BYTE, + filetype, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EFILE; + } + + if (ndims > 0) { + if (filetype != MPI_BYTE) + MPI_Type_free(&filetype); + + free(shape); + free(subcount); + free(substart); + } + + return NC_NOERR; +} + +static int +set_vars_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, + const MPI_Offset start[], const MPI_Offset count[], + const MPI_Offset stride[], int getnotput) { + MPI_Offset offset; + int status; + int mpireturn; + int dim, ndims; + MPI_Datatype *subtypes, *filetype; + MPI_Offset *blocklens = NULL, *blockstride = NULL, *blockcount = NULL; + + ndims = varp->ndims; + + for (dim=0; dim NC_get_numrecs(ncp)) ) + { + status = NCcoordck(ncp, varp, start); + if (status != NC_NOERR) + return status; + else + return NC_EEDGE; + } + + status = NCstrideedgeck(ncp, varp, start, count, stride); + if(status != NC_NOERR) + return status; + + if( getnotput && IS_RECVAR(varp) && + ( (*count > 0 && *start+1 + (*count-1) * *stride > NC_get_numrecs(ncp)) || + (*count == 0 && *start > NC_get_numrecs(ncp)) ) ) + return NC_EEDGE; + +/* Removed to fix NC_EINVALCOORDS bug + + status = NCcoordck(ncp, varp, start); + if (status != NC_NOERR) + return status; +*/ + +/* Moved into NCstrideedgeck + + for (dim = 0; dim < ndims; dim++) + { + if ( (stride != NULL && stride[dim] == 0) || + stride[dim] >= X_INT_MAX) + { + return NC_ESTRIDE; + } + } +*/ + +/* Removed to fix NC_EINVALCOORDS bug + + status = NCedgeck(ncp, varp, start, count); + if(status != NC_NOERR) + return status; + + if(getnotput && IS_RECVAR(varp) && + (unsigned long)*start + (unsigned long)*count > NC_get_numrecs(ncp)) + return NC_EEDGE; +*/ + + offset = varp->begin; + + if (ndims == 0) { + + /* scalar variable */ + + filetype = subtypes = (MPI_Datatype *)malloc(sizeof(MPI_Datatype)); + *filetype = MPI_BYTE; + + } else { + + blocklens = (MPI_Offset *) malloc(ndims * sizeof(MPI_Offset)); + blockstride = (MPI_Offset *) malloc(ndims * sizeof(MPI_Offset)); + blockcount = (MPI_Offset *) malloc(ndims * sizeof(MPI_Offset)); + + dim = 0; + while (dim < ndims && count[dim] > 0) dim++; + + if (dim < ndims) { + + /* 0 size data */ + filetype = subtypes = (MPI_Datatype *)malloc(sizeof(MPI_Datatype)); + *filetype = MPI_BYTE; + + } else { + + subtypes = (MPI_Datatype *)malloc((ndims+1) * sizeof(MPI_Datatype)); + filetype = subtypes; + subtypes[ndims] = MPI_BYTE; + + blocklens[ndims - 1] = varp->xsz; + blockcount[ndims - 1] = count[ndims - 1]; + if (ndims == 1 && IS_RECVAR(varp)) { + blockstride[ndims - 1] = stride[ndims - 1] * ncp->recsize; + offset += start[ndims - 1] * ncp->recsize; + } else { + blockstride[ndims - 1] = stride[ndims - 1] * varp->xsz; + offset += start[ndims - 1] * varp->xsz; + } + + for (dim = ndims - 1; dim >= 0; dim--) { +#if (MPI_VERSION < 2) + MPI_Type_hvector(blockcount[dim], blocklens[dim], blockstride[dim], + subtypes[dim + 1], subtypes + dim); +#else + MPI_Type_create_hvector(blockcount[dim], blocklens[dim], blockstride[dim], + subtypes[dim + 1], subtypes + dim); +#endif + MPI_Type_commit(subtypes + dim); + + if (dim - 1 >= 0) { + blocklens[dim - 1] = 1; + blockcount[dim - 1] = count[dim - 1]; + if (dim - 1 == 0 && IS_RECVAR(varp)) { + blockstride[dim - 1] = stride[dim - 1] * ncp->recsize; + offset += start[dim-1] * ncp->recsize; + } else { + blockstride[dim - 1] = stride[dim - 1] * varp->dsizes[dim] * varp->xsz; + offset += start[dim-1] * varp->dsizes[dim] * varp->xsz; + } + } + } + + } + + } + + mpireturn = MPI_File_set_view(*mpifh, offset, MPI_BYTE, + *filetype, "native", ncp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + return NC_EFILE; + } + + if (ndims > 0) { + if (*filetype != MPI_BYTE) + for (dim=0; dim < ndims; dim++) + MPI_Type_free(subtypes + dim); + + free(blocklens); + free(blockstride); + free(blockcount); + } + + free(subtypes); + + return NC_NOERR; +} + +/* BEGIN put/get functions */ +/* buffer layers: + + User Level buf (user defined buffer of MPI_Datatype) + MPI Datatype Level cbuf (contiguous buffer of ptype) + NetCDF XDR Level xbuf (XDR I/O buffer) +*/ + +int +ncmpi_put_var1(int ncid, int varid, + const MPI_Offset index[], + const void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems*varp->xsz; /* account for file bytes */ + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, 1, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, 1, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, 1, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, 1, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, 1, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, 1, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, + MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + status = NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if ( status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = index[0] + 1; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_var1(int ncid, int varid, + const MPI_Offset index[], + void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems*varp->xsz; /* account for file bytes */ + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, 1, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, 1, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, 1, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, 1, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, 1, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, 1, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_var_all(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + if (varp->ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (varp->ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems * varp->xsz; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var_fileview(ncp, &(ncp->nciop->collective_fh), varp); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_all"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_var(int ncid, int varid, const void *buf, int bufcount, MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + if (varp->ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (varp->ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems * varp->xsz; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + status = NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + if (varp->ndims > 1) + newnumrecs = nelems / varp->dsizes[1]; + else + newnumrecs = nelems; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_var(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + if (varp->ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (varp->ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems * varp->xsz; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_vara_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype) { + + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + MPI_Comm comm; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + comm = ncp->nciop->comm; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->collective_fh), comm, 1); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->collective_fh), varp, start, count, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write_all"); + status = NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if (status == NC_NOERR && IS_RECVAR(varp)) { + + /* update the number of records in NC + and write it back to file header, if necessary + */ + int newnumrecs, max_numrecs; + newnumrecs = start[0] + count[0]; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + if (NC_doNsync(ncp)) { + MPI_Allreduce( &newnumrecs, &max_numrecs, 1, MPI_INT, MPI_MAX, comm ); + + if (ncp->numrecs < max_numrecs) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncp->numrecs = max_numrecs; + if (rank == 0) { + status = ncmpii_write_numrecs(ncp); /* call subroutine from nc.c */ + if(status != NC_NOERR) + return status; + } + } + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + + +int +ncmpi_get_vara_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype) { + + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->collective_fh), varp, start, count, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_all"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + return NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = start[0] + count[0]; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_vars_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + MPI_Comm comm; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + MPI_Offset *stride_was_null=NULL, *stride_ptr; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + comm = ncp->nciop->comm; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->collective_fh), comm, 1); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* NULL stride is legal and means (1,1,1,..1) */ + stride_ptr = (MPI_Offset *)stride; + if (stride == NULL) { + stride_was_null=(MPI_Offset*)malloc(varp->ndims*sizeof(MPI_Offset)); + for (dim=0; dim < varp->ndims; dim++) { + stride_was_null[dim] = 1; + } + stride_ptr = stride_was_null; + } + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->collective_fh), + varp, start, count, stride_ptr, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write_all"); + status = NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if (status == NC_NOERR && IS_RECVAR(varp)) { + + /* update the number of records in NC + and write it back to file header, if necessary + */ + int newnumrecs, max_numrecs; + newnumrecs = start[0] + (count[0] - 1) * stride_ptr[0] + 1; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + if (NC_doNsync(ncp)) { + MPI_Allreduce( &newnumrecs, &max_numrecs, 1, MPI_INT, MPI_MAX, comm ); + + if (ncp->numrecs < max_numrecs) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncp->numrecs = max_numrecs; + if (rank == 0) { + status = ncmpii_write_numrecs(ncp); /* call subroutine from nc.c */ + if(status != NC_NOERR) + return status; + } + } + } + } + if (stride_was_null != NULL) free(stride_was_null); + + return ((warning != NC_NOERR) ? warning : status); +} + + +int +ncmpi_get_vars_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype) { + + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->collective_fh), + varp, start, count, stride, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_all"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->independent_fh), + varp, start, count, stride, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, datatype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + status = NC_EWRITE; + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = start[0] + (count[0] - 1) * stride[0] + 1; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype) { + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + MPI_Status mpistatus; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->independent_fh), + varp, start, count, stride, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + mpireturn = MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + if ( need_convert(varp->type, ptype) ) { + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(varp->type)); + + } + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: unpack from the contiguous buffer */ + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +/* varm: there maybe two layer of memory layout (remapping): + one is specified by MPI derived datatype, + the other is specified by imap[], + it's encouraged to use only one option of them, + though using both of them are supported. + + user buffer: |--------------------------| + + mpi derived datatype view: |------| |------| |------| + + logic (contig) memory datastream: |------|------|------| + + imap view: |--| |--| |--| |--| + + contig I/O datastream (internal represent): |--|--|--|--| + + These two layers of memory layout will both be represented in MPI + derived datatype, and if double layers of memory layout is used, + we need to elimilate the upper one passed in MPI_Datatype parameter + from the user, by repacking it to logic contig memory datastream view. +*/ + +int +ncmpi_put_varm_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen*count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + /* layout lbuf to cbuf based on imap */ + status = ncmpii_data_repack(lbuf, 1, imaptype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + + MPI_Type_free(&imaptype); + + status = ncmpi_put_vars_all(ncid, varid, start, count, stride, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + +fn_exit: + if (!iscontig_of_ptypes && lbuf != NULL) + free(lbuf); + if (cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_varm_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen * count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, (MPI_Aint)imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + status = ncmpi_get_vars_all(ncid, varid, start, count, stride, + cbuf, cnelems, ptype); + if (status != NC_NOERR) { + if (status == NC_ERANGE && warning == NC_NOERR) + warning = status; /* to satisfy the nc_test logic */ + else + goto fn_exit; + } + + /* layout cbuf to lbuf based on imap */ + status = ncmpii_data_repack(cbuf, cnelems, ptype, + lbuf, 1, imaptype); + if (status != NC_NOERR) + goto fn_exit; + + MPI_Type_free(&imaptype); + + if (!iscontig_of_ptypes) { + + /* repack it back, like a read-modify-write operation */ + + status = ncmpii_data_repack(lbuf, lnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + goto fn_exit; + + } + +fn_exit: + if (!iscontig_of_ptypes && lbuf != NULL) + free(lbuf); + if (cbuf != NULL) + free(cbuf); + if (imaptype != MPI_DATATYPE_NULL) + MPI_Type_free(&imaptype); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_put_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_put_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_put_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen*count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) { + status = NC_ENEGATIVECNT; + goto fn_exit; + } + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + /* layout lbuf to cbuf based on imap */ + status = ncmpii_data_repack(lbuf, 1, imaptype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + + MPI_Type_free(&imaptype); + + status = ncmpi_put_vars(ncid, varid, start, count, stride, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + goto fn_exit; + +fn_exit: + if (!iscontig_of_ptypes && lbuf != NULL) + free(lbuf); + if (cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_get_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_get_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_get_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_get_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen * count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, (MPI_Aint)imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + status = ncmpi_get_vars(ncid, varid, start, count, stride, + cbuf, cnelems, ptype); + if (status != NC_NOERR) { + if (status == NC_ERANGE && warning == NC_NOERR) + warning = status; /* to satisfy the nc_test logic */ + else + return status; + } + + /* layout cbuf to lbuf based on imap */ + status = ncmpii_data_repack(cbuf, cnelems, ptype, + lbuf, 1, imaptype); + if (status != NC_NOERR) + return status; + + MPI_Type_free(&imaptype); + + if (!iscontig_of_ptypes) { + + /* repack it back, like a read-modify-write operation */ + + status = ncmpii_data_repack(lbuf, lnelems, ptype, + (void *)buf, bufcount, datatype); + if (status != NC_NOERR) + return status; + + if (lbuf != NULL) + free(lbuf); + + } + + if (cbuf != NULL) + free(cbuf); + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_put_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_var1_schar(int ncid, int varid, + const MPI_Offset index[], + const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_BYTE); +} + +int +ncmpi_put_var1_text(int ncid, int varid, + const MPI_Offset index[], + const char *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_CHAR); +} + + +int +ncmpi_put_var1_short(int ncid, int varid, + const MPI_Offset index[], + const short *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_SHORT); +} + +int +ncmpi_put_var1_int(int ncid, int varid, + const MPI_Offset index[], + const int *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_INT); +} + +int +ncmpi_put_var1_long(int ncid, int varid, + const MPI_Offset index[], + const long *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_LONG); +} + +int +ncmpi_put_var1_float(int ncid, int varid, + const MPI_Offset index[], + const float *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_FLOAT); +} + +int +ncmpi_put_var1_double(int ncid, int varid, + const MPI_Offset index[], + const double *op) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_put_var1(ncid, varid, index, + (const void *)op, 1, MPI_DOUBLE); +} + +int +ncmpi_get_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + unsigned char *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_var1_schar(int ncid, int varid, + const MPI_Offset index[], + signed char *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_BYTE); +} + +int +ncmpi_get_var1_text(int ncid, int varid, + const MPI_Offset index[], + char *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_CHAR); +} + +int +ncmpi_get_var1_short(int ncid, int varid, + const MPI_Offset index[], + short *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_SHORT); +} + +int +ncmpi_get_var1_int(int ncid, int varid, + const MPI_Offset index[], + int *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_INT); +} + +int +ncmpi_get_var1_long(int ncid, int varid, + const MPI_Offset index[], + long *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_LONG); +} + +int +ncmpi_get_var1_float(int ncid, int varid, + const MPI_Offset index[], + float *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_FLOAT); +} + +int +ncmpi_get_var1_double(int ncid, int varid, + const MPI_Offset index[], + double *ip) { + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_get_var1(ncid, varid, index, + (void *)ip, 1, MPI_DOUBLE); +} + +int +ncmpi_put_var_uchar(int ncid, int varid, const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_var_schar(int ncid, int varid, const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_BYTE); +} + + +int +ncmpi_put_var_text(int ncid, int varid, const char *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_var_short(int ncid, int varid, const short *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_var_int(int ncid, int varid, const int *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_var_long(int ncid, int varid, const long *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_var_float(int ncid, int varid, const float *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_var_double(int ncid, int varid, const double *op) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_put_var(ncid, varid, (const void *)op, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_var_uchar(int ncid, int varid, unsigned char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_var_schar(int ncid, int varid, signed char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_var_text(int ncid, int varid, char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_var_short(int ncid, int varid, short *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_var_int(int ncid, int varid, int *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_var_long(int ncid, int varid, long *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_var_float(int ncid, int varid, float *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_var_double(int ncid, int varid, double *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var(ncid, varid, (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_var_uchar_all(int ncid, int varid, unsigned char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_var_schar_all(int ncid, int varid, signed char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_var_text_all(int ncid, int varid, char *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_var_short_all(int ncid, int varid, short *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_var_int_all(int ncid, int varid, int *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_var_long_all(int ncid, int varid, long *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_var_float_all(int ncid, int varid, float *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_var_double_all(int ncid, int varid, double *ip) { + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_get_var_all(ncid, varid, (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_put_vara_uchar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_vara_schar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_vara_text_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_vara_short_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_vara_int_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_vara_long_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_vara_float_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_vara_double_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara_all(ncid, varid, start, count, + (const void *)op, nelems, MPI_DOUBLE); +} + +int +ncmpi_put_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_vara_uchar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_vara_schar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_vara_text_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_vara_short_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_vara_int_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_vara_long_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_vara_float_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_vara_double_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara_all(ncid, varid, start, count, + (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_put_vars_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_vars_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_vars_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_vars_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_vars_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_vars_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_vars_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_vars_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars_all(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_DOUBLE); + +} + +int +ncmpi_put_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_DOUBLE); + +} + +int +ncmpi_get_vars_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_vars_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_vars_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_vars_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_vars_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_vars_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_vars_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip) { + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_vars_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars_all(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip) { + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_put_varm_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_put_varm_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_BYTE); +} + +int +ncmpi_put_varm_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_CHAR); +} + +int +ncmpi_put_varm_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_SHORT); +} + +int +ncmpi_put_varm_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_INT); +} + +int +ncmpi_put_varm_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_LONG); +} + +int +ncmpi_put_varm_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_FLOAT); +} + +int +ncmpi_put_varm_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_DOUBLE); +} + +int +ncmpi_put_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_put_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_varm_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_UNSIGNED_CHAR); +} + +int +ncmpi_get_varm_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_BYTE); +} + +int +ncmpi_get_varm_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_CHAR); +} + +int +ncmpi_get_varm_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_SHORT); +} + +int +ncmpi_get_varm_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_INT); +} + +int +ncmpi_get_varm_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_LONG); +} + +int +ncmpi_get_varm_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_FLOAT); +} + +int +ncmpi_get_varm_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_DOUBLE); +} + +int +ncmpi_get_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_get_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_DOUBLE); +} + +/* End {put,get}_var */ + +#ifdef ENABLE_NONBLOCKING +/* #################################################################### */ +/* Begin non-blocking data access functions */ + +static void ncmpii_postwrite(void *xbuf, void *cbuf, void *buf) { + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); +} + +static int ncmpii_postread(nc_type vartype, + void *xbuf, + void *cbuf, + int nelems, + int cnelems, + int iscontig_of_ptypes, + void *buf, + int bufcount, + MPI_Datatype datatype, + MPI_Datatype ptype) +{ + + int status = NC_NOERR; + + if ( need_convert(vartype, ptype) ) { + switch( vartype ) { + case NC_BYTE: + status = x_getn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_getn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_getn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_getn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_getn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + } else if ( need_swap(vartype, ptype) ) { + swapn(cbuf, xbuf, nelems, ncmpix_len_nctype(vartype)); + } + + if (!iscontig_of_ptypes) { + status = ncmpii_data_repack(cbuf, cnelems, ptype, + (void *)buf, bufcount, datatype); + } + + if (xbuf != cbuf && xbuf != NULL) + free(xbuf); + if (cbuf != buf && cbuf != NULL) + free(cbuf); + + return status; +} + +static void ncmpii_postmwrite(void *cbuf, void *lbuf, int iscontig_of_ptypes) { + if (!iscontig_of_ptypes && lbuf != NULL) + free(lbuf); + if (cbuf != NULL) + free(cbuf); +} + +static int ncmpii_postmread(void *cbuf, + void *lbuf, + int cnelems, + int lnelems, + int iscontig_of_ptypes, + void *buf, + int bufcount, + MPI_Datatype datatype, + MPI_Datatype ptype, + MPI_Datatype imaptype) +{ + int status; + + status = ncmpii_data_repack(cbuf, cnelems, ptype, + lbuf, 1, imaptype); + if (status != NC_NOERR) + return status; + + MPI_Type_free(&imaptype); + + if (!iscontig_of_ptypes) { + status = ncmpii_data_repack(lbuf, lnelems, ptype, + (void *)buf, bufcount, datatype); + if (lbuf != NULL) + free(lbuf); + } + + if (cbuf != NULL) + free(cbuf); + + return status; +} + +static int +ncmpii_postprocess(NCMPI_Request *request) { + int status = NC_NOERR; + + switch ((*request)->reqtype) { + case NCMPI_REQTYPE_READ: + status = ncmpii_postread((*request)->vartype, + (*request)->xbuf, + (*request)->cbuf, + (*request)->nelems, + (*request)->cnelems, + (*request)->iscontig_of_ptypes, + (*request)->buf, + (*request)->bufcount, + (*request)->datatype, + (*request)->ptype); + MPI_Type_free(&((*request)->datatype)); + break; + case NCMPI_REQTYPE_WRITE: + ncmpii_postwrite((*request)->xbuf, (*request)->cbuf, (*request)->buf); + break; + case NCMPI_REQTYPE_MREAD: + ncmpii_postmread((*request)->cbuf, + (*request)->lbuf, + (*request)->cnelems, + (*request)->lnelems, + (*request)->iscontig_of_ptypes, + (*request)->buf, + (*request)->bufcount, + (*request)->datatype, + (*request)->ptype, + (*request)->imaptype); + MPI_Type_free(&((*request)->datatype)); + break; + case NCMPI_REQTYPE_MWRITE: + ncmpii_postmwrite((*request)->cbuf, + (*request)->lbuf, + (*request)->iscontig_of_ptypes); + break; + default: + break; + } + if (status != NC_NOERR) + return status; + + if ( (*request)->next_req != NCMPI_REQUEST_NULL ) { + status = ncmpii_postprocess( &((*request)->next_req) ); + if (status != NC_NOERR) + return status; + } + + free(*request); + *request = NCMPI_REQUEST_NULL; + + return status; +} + + +int +ncmpi_wait(NCMPI_Request *request) { + int mpireturn = MPI_SUCCESS; + + if (*request != NCMPI_REQUEST_NULL) { + mpireturn = MPI_Wait(&((*request)->mpi_req), MPI_STATUS_IGNORE); + ncmpii_postprocess(request); + } + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_waitall(int count, NCMPI_Request array_of_requests[]) { + int i; + int mpireturn = MPI_SUCCESS; + MPI_Request *array_of_mpireqs; + + array_of_mpireqs = (MPI_Request *)malloc(count * sizeof(int)); + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Waitall(count, array_of_mpireqs, MPI_STATUSES_IGNORE); + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Waitany(count, array_of_mpireqs, index, MPI_STATUS_IGNORE); + if (array_of_requests[*index] != NCMPI_REQUEST_NULL) + ncmpii_postprocess(array_of_requests + *index); + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_waitsome(int count, NCMPI_Request array_of_requests[], + int *outcount, int array_of_indices[]) +{ + int i; + int mpireturn = MPI_SUCCESS; + MPI_Request *array_of_mpireqs; + + array_of_mpireqs = (MPI_Request *)malloc(count * sizeof(int)); + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Waitsome(count, array_of_mpireqs, + outcount, array_of_indices, MPI_STATUSES_IGNORE); + for (i=0; i<*outcount; i++) { + if (array_of_requests[array_of_indices[i]] != NCMPI_REQUEST_NULL) + ncmpii_postprocess(array_of_requests + array_of_indices[i]); + } + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_test(NCMPI_Request *request, int *flag) { + int mpireturn = MPI_SUCCESS; + if (*request != NCMPI_REQUEST_NULL) { + mpireturn = MPI_Test(&((*request)->mpi_req), flag, MPI_STATUS_IGNORE); + if (*flag) + ncmpii_postprocess(request); + } + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_testall(int count, NCMPI_Request array_of_requests[], int *flag) { + int i; + int mpireturn = MPI_SUCCESS; + MPI_Request *array_of_mpireqs; + + array_of_mpireqs = (MPI_Request *)malloc(count * sizeof(int)); + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Testall(count, array_of_mpireqs, flag, MPI_STATUSES_IGNORE); + if (*flag) { + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Testany(count, array_of_mpireqs, + index, flag, MPI_STATUS_IGNORE); + if (*flag && array_of_requests[*index] != NCMPI_REQUEST_NULL) + ncmpii_postprocess(array_of_requests + *index); + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_testsome(int count, NCMPI_Request array_of_requests[], + int *outcount, int array_of_indices[]) +{ + int i; + int mpireturn = MPI_SUCCESS; + MPI_Request *array_of_mpireqs; + + array_of_mpireqs = (MPI_Request *)malloc(count * sizeof(int)); + for (i=0; impi_req; + else + array_of_mpireqs[i] = MPI_REQUEST_NULL; + } + mpireturn = MPI_Testsome(count, array_of_mpireqs, + outcount, array_of_indices, MPI_STATUSES_IGNORE); + for (i=0; i<*outcount; i++) { + if (array_of_requests[array_of_indices[i]] != NCMPI_REQUEST_NULL) + ncmpii_postprocess(array_of_requests + array_of_indices[i]); + } + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_request_get_status(NCMPI_Request request, int *flag) { + int mpireturn = MPI_SUCCESS; + if (request != NCMPI_REQUEST_NULL) + mpireturn = MPI_Request_get_status(request->mpi_req, flag, + MPI_STATUS_IGNORE); + else + *flag = 1; + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_request_free(NCMPI_Request *request) { + int mpireturn = MPI_SUCCESS; + if (*request != NCMPI_REQUEST_NULL) { + mpireturn = MPI_Request_free( &((*request)->mpi_req) ); + ncmpii_postprocess(request); + } + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + +int +ncmpi_cancel(NCMPI_Request *request) { + int mpireturn = MPI_SUCCESS; + if (*request != NCMPI_REQUEST_NULL) + mpireturn = MPI_Cancel(&((*request)->mpi_req)); + + if (mpireturn != MPI_SUCCESS) { + return NC_EFILE; + } else { + return NC_NOERR; + } +} + + +int +ncmpi_iput_var1(int ncid, int varid, + const MPI_Offset index[], + const void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems*varp->xsz; /* account for file bytes */ + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, 1, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, 1, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, 1, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, 1, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, 1, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, 1, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iwrite(ncp->nciop->independent_fh, xbuf, nbytes, + MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + status = NC_EWRITE; + } + + (*request)->reqtype = NCMPI_REQTYPE_WRITE; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->buf = (void *)buf; + (*request)->next_req = NCMPI_REQUEST_NULL; + + if ( status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = index[0] + 1; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iget_var1(int ncid, int varid, + const MPI_Offset index[], + void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems*varp->xsz; /* account for file bytes */ + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iread(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + (*request)->reqtype = NCMPI_REQTYPE_READ; + (*request)->vartype = varp->type; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->nelems = nelems; + (*request)->cnelems = cnelems; + (*request)->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->buf = (void *)buf; + (*request)->bufcount = bufcount; + MPI_Type_dup(datatype, &((*request)->datatype)); + (*request)->ptype = ptype; + (*request)->next_req = NCMPI_REQUEST_NULL; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iput_var(int ncid, int varid, + const void *buf, int bufcount, MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + if (varp->ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (varp->ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems * varp->xsz; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iwrite(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write error"); + status = NC_EWRITE; + } + + (*request)->reqtype = NCMPI_REQTYPE_WRITE; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->buf = (void *)buf; + (*request)->next_req = NCMPI_REQUEST_NULL; + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + if (varp->ndims > 1) + newnumrecs = nelems / varp->dsizes[1]; + else + newnumrecs = nelems; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iget_var(int ncid, int varid, + void *buf, int bufcount, MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + if (varp->ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (varp->ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = nelems * varp->xsz; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iread(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + (*request)->reqtype = NCMPI_REQTYPE_READ; + (*request)->vartype = varp->type; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->nelems = nelems; + (*request)->cnelems = cnelems; + (*request)->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->buf = (void *)buf; + (*request)->bufcount = bufcount; + MPI_Type_dup(datatype, &((*request)->datatype)); + (*request)->ptype = ptype; + (*request)->next_req = NCMPI_REQUEST_NULL; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iput_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iwrite(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + return NC_EWRITE; + } + + (*request)->reqtype = NCMPI_REQTYPE_WRITE; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->buf = (void *)buf; + (*request)->next_req = NCMPI_REQUEST_NULL; + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = start[0] + count[0]; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iget_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iread(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + (*request)->reqtype = NCMPI_REQTYPE_READ; + (*request)->vartype = varp->type; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->nelems = nelems; + (*request)->cnelems = cnelems; + (*request)->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->buf = (void *)buf; + (*request)->bufcount = bufcount; + MPI_Type_dup(datatype, &((*request)->datatype)); + (*request)->ptype = ptype; + (*request)->next_req = NCMPI_REQUEST_NULL; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iput_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->independent_fh), + varp, start, count, stride, 0); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) ) { + + /* allocate new buffer */ + + xbuf = (void *)malloc(nbytes); + + /* automatic numeric datatype conversion */ + + switch( varp->type ) { + case NC_BYTE: + status = x_putn_schar(xbuf, cbuf, cnelems, ptype); + break; + case NC_SHORT: + status = x_putn_short(xbuf, cbuf, cnelems, ptype); + break; + case NC_INT: + status = x_putn_int(xbuf, cbuf, cnelems, ptype); + break; + case NC_FLOAT: + status = x_putn_float(xbuf, cbuf, cnelems, ptype); + break; + case NC_DOUBLE: + status = x_putn_double(xbuf, cbuf, cnelems, ptype); + break; + default: + break; + } + + } else if ( need_swap(varp->type, datatype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + swapn(xbuf, cbuf, nelems, ncmpix_len_nctype(varp->type)); + + } else { + + /* else, just assign contiguous buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iwrite(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_write"); + status = NC_EWRITE; + } + + (*request)->reqtype = NCMPI_REQTYPE_WRITE; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->buf = (void *)buf; + (*request)->next_req = NCMPI_REQUEST_NULL; + + if (status == NC_NOERR && IS_RECVAR(varp)) { + /* update the number of records in NC */ + + int newnumrecs; + newnumrecs = start[0] + (count[0] - 1) * stride[0] + 1; + if (ncp->numrecs < newnumrecs) { + ncp->numrecs = newnumrecs; + set_NC_ndirty(ncp); + } + } + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iget_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + void *xbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int dim; + int nelems, cnelems, el_size, nbytes; + int mpireturn; + MPI_Datatype ptype; + int isderived, iscontig_of_ptypes; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + /* check to see that the desired mpi file handle is opened */ + + status = check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &cnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if ( echar(varp->type, ptype) ) + return NC_ECHAR; + + cnelems *= bufcount; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + nelems *= count[dim]; + } + + if (nelems != cnelems) { + if (warning == NC_NOERR) + warning = NC_EIOMISMATCH; + (nelems>cnelems) ? (nelems=cnelems) : (cnelems=nelems); + } + + nbytes = varp->xsz * nelems; + if (nbytes < 0) + return NC_ENEGATIVECNT; + + /* set the mpi file view */ + + status = set_vars_fileview(ncp, &(ncp->nciop->independent_fh), + varp, start, count, stride, 1); + if(status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* account for derived datatype: allocate the contiguous buffer */ + + cbuf = (void *)malloc( cnelems * el_size ); + + } else { + + cbuf = (void *)buf; + + } + + /* assign or allocate MPI buffer */ + + if ( need_convert(varp->type, ptype) || need_swap(varp->type, ptype) ) { + + /* allocate new buffer */ + xbuf = (void *)malloc(nbytes); + + } else { + + /* else, just assign the contiguous buffer/user buffer */ + xbuf = (void *)cbuf; + + } + + *request = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + + mpireturn = MPI_File_iread(ncp->nciop->independent_fh, xbuf, + nbytes, MPI_BYTE, &((*request)->mpi_req)); + if (mpireturn != MPI_SUCCESS) { + int rank; + MPI_Comm_rank(ncp->nciop->comm, &rank); + ncmpii_handle_error(rank, mpireturn, "MPI_File_read"); + status = NC_EREAD; + } + + (*request)->reqtype = NCMPI_REQTYPE_READ; + (*request)->vartype = varp->type; + (*request)->xbuf = xbuf; + (*request)->cbuf = cbuf; + (*request)->nelems = nelems; + (*request)->cnelems = cnelems; + (*request)->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->buf = (void *)buf; + (*request)->bufcount = bufcount; + MPI_Type_dup(datatype, &((*request)->datatype)); + (*request)->ptype = ptype; + (*request)->next_req = NCMPI_REQUEST_NULL; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iput_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_iput_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_iput_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_iput_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen*count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + /* layout lbuf to cbuf based on imap */ + status = ncmpii_data_repack(lbuf, 1, imaptype, + cbuf, cnelems, ptype); + if (status != NC_NOERR) + return status; + + MPI_Type_free(&imaptype); + + status = ncmpi_iput_vars(ncid, varid, start, count, stride, + cbuf, cnelems, ptype, request); + + (*request)->next_req = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + (*request)->next_req->reqtype = NCMPI_REQTYPE_MWRITE; + (*request)->next_req->cbuf = cbuf; + (*request)->next_req->lbuf = lbuf; + (*request)->next_req->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->next_req->next_req = NCMPI_REQUEST_NULL; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iget_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int ndims, dim; + void *lbuf = NULL, *cbuf = NULL; + int status = NC_NOERR, warning = NC_NOERR; + int lnelems, cnelems, el_size; + MPI_Datatype ptype, tmptype, imaptype; + int isderived, iscontig_of_ptypes; + int imap_contig_blocklen; + + if (imap == NULL) { + /* no mapping, same as vars */ + return ncmpi_iget_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + if (ndims == 0) { + /* reduced to scalar var, only one value at one fixed place */ + return ncmpi_iget_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } + + imap_contig_blocklen = 1; + dim = ndims; + /* test each dim's contiguity until the 1st non-contiguous dim is reached */ + while ( --dim>=0 && imap_contig_blocklen==imap[dim] ) { + if (count[dim] < 0) + return NC_ENEGATIVECNT; + imap_contig_blocklen *= count[dim]; + } + + if (dim == -1) { + /* imap is a contiguous layout */ + return ncmpi_iget_vars(ncid, varid, start, count, stride, + buf, bufcount, datatype, request); + } /* else imap gives non-contiguous layout, and need pack/unpack */ + + status = ncmpii_dtype_decode(datatype, &ptype, &el_size, + &lnelems, &isderived, &iscontig_of_ptypes); + if (status != NC_NOERR) + return status; + + if (!iscontig_of_ptypes) { + + /* handling for derived datatype: pack into a contiguous buffer */ + + lnelems *= bufcount; + lbuf = (void *)malloc( lnelems*el_size ); + status = ncmpii_data_repack((void *)buf, bufcount, datatype, + lbuf, lnelems, ptype); + if (status != NC_NOERR) + return status; + + } else { + + lbuf = (void *)buf; + + } + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + MPI_Type_vector(count[dim], imap_contig_blocklen, imap[dim], + ptype, &imaptype); + MPI_Type_commit(&imaptype); + cnelems = imap_contig_blocklen * count[dim]; + for (dim--; dim>=0; dim--) { + + if (count[dim] < 0) + return NC_ENEGATIVECNT; + +#if (MPI_VERSION < 2) + MPI_Type_hvector(count[dim], 1, imap[dim]*el_size, imaptype, &tmptype); +#else + MPI_Type_create_hvector(count[dim], 1, (MPI_Aint)imap[dim]*el_size, + imaptype, &tmptype); +#endif + MPI_Type_free(&imaptype); + MPI_Type_commit(&tmptype); + imaptype = tmptype; + cnelems *= count[dim]; + + } + + cbuf = (void *)malloc(cnelems*el_size); + + status = ncmpi_iget_vars(ncid, varid, start, count, stride, + cbuf, cnelems, ptype, request); + if (status != NC_NOERR) { + if (status == NC_ERANGE && warning == NC_NOERR) + warning = status; /* to satisfy the nc_test logic */ + else + return status; + } + + (*request)->next_req = (NCMPI_Request)malloc(sizeof(struct NCMPI_Req)); + (*request)->next_req->reqtype = NCMPI_REQTYPE_MREAD; + (*request)->next_req->cbuf = cbuf; + (*request)->next_req->lbuf = lbuf; + (*request)->next_req->cnelems = cnelems; + (*request)->next_req->lnelems = lnelems; + (*request)->next_req->iscontig_of_ptypes = iscontig_of_ptypes; + (*request)->next_req->buf = (void *)buf; + (*request)->next_req->bufcount = bufcount; + MPI_Type_dup(datatype, &((*request)->next_req->datatype)); + (*request)->next_req->ptype = ptype; + (*request)->next_req->imaptype = imaptype; + + return ((warning != NC_NOERR) ? warning : status); +} + +int +ncmpi_iput_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + const unsigned char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iput_var1_schar(int ncid, int varid, + const MPI_Offset index[], + const signed char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_BYTE, request); +} + +int +ncmpi_iput_var1_text(int ncid, int varid, + const MPI_Offset index[], + const char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_CHAR, request); +} + + +int +ncmpi_iput_var1_short(int ncid, int varid, + const MPI_Offset index[], + const short *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_SHORT, request); +} + +int +ncmpi_iput_var1_int(int ncid, int varid, + const MPI_Offset index[], + const int *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_INT, request); +} + +int +ncmpi_iput_var1_long(int ncid, int varid, + const MPI_Offset index[], + const long *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_LONG, request); +} + +int +ncmpi_iput_var1_float(int ncid, int varid, + const MPI_Offset index[], + const float *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_FLOAT, request); +} + +int +ncmpi_iput_var1_double(int ncid, int varid, + const MPI_Offset index[], + const double *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iput_var1(ncid, varid, index, + (const void *)op, 1, MPI_DOUBLE, request); +} + +int +ncmpi_iget_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + unsigned char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iget_var1_schar(int ncid, int varid, + const MPI_Offset index[], + signed char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_BYTE, request); +} + +int +ncmpi_iget_var1_text(int ncid, int varid, + const MPI_Offset index[], + char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_CHAR, request); +} + +int +ncmpi_iget_var1_short(int ncid, int varid, + const MPI_Offset index[], + short *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_SHORT, request); +} + +int +ncmpi_iget_var1_int(int ncid, int varid, + const MPI_Offset index[], + int *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_INT, request); +} + +int +ncmpi_iget_var1_long(int ncid, int varid, + const MPI_Offset index[], + long *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_LONG, request); +} + +int +ncmpi_iget_var1_float(int ncid, int varid, + const MPI_Offset index[], + float *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_FLOAT, request); +} + +int +ncmpi_iget_var1_double(int ncid, int varid, + const MPI_Offset index[], + double *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + return ncmpi_iget_var1(ncid, varid, index, + (void *)ip, 1, MPI_DOUBLE, request); +} + +int +ncmpi_iput_var_uchar(int ncid, int varid, const unsigned char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iput_var_schar(int ncid, int varid, const signed char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_BYTE, request); +} + + +int +ncmpi_iput_var_text(int ncid, int varid, const char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_CHAR, request); +} + +int +ncmpi_iput_var_short(int ncid, int varid, const short *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_SHORT, request); +} + +int +ncmpi_iput_var_int(int ncid, int varid, const int *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_INT, request); +} + +int +ncmpi_iput_var_long(int ncid, int varid, const long *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_LONG, request); +} + +int +ncmpi_iput_var_float(int ncid, int varid, const float *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iput_var_double(int ncid, int varid, const double *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iput_var(ncid, varid, (const void *)op, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iget_var_uchar(int ncid, int varid, unsigned char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iget_var_schar(int ncid, int varid, signed char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_BYTE, request); +} + +int +ncmpi_iget_var_text(int ncid, int varid, char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_CHAR, request); +} + +int +ncmpi_iget_var_short(int ncid, int varid, short *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_SHORT, request); +} + +int +ncmpi_iget_var_int(int ncid, int varid, int *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_INT, request); +} + +int +ncmpi_iget_var_long(int ncid, int varid, long *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_LONG, request); +} + +int +ncmpi_iget_var_float(int ncid, int varid, float *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iget_var_double(int ncid, int varid, double *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int ndims; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + ndims = varp->ndims; + + /* Begin modification 20030311 to fix bug of 0-dimensional variables */ + + if (ndims == 0) + nelems = 1; + else if (!IS_RECVAR(varp)) + nelems = varp->dsizes[0]; + else if (ndims > 1) + nelems = ncp->numrecs * varp->dsizes[1]; + else + nelems = ncp->numrecs; + + /* End modification 20030311 */ + + return ncmpi_iget_var(ncid, varid, (void *)ip, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iput_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iput_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_BYTE, request); +} + +int +ncmpi_iput_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_CHAR, request); +} + +int +ncmpi_iput_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_SHORT, request); +} + +int +ncmpi_iput_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_INT, request); +} + +int +ncmpi_iput_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_LONG, request); +} + +int +ncmpi_iput_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iput_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vara(ncid, varid, start, count, + (const void *)op, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iget_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iget_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_BYTE, request); +} + +int +ncmpi_iget_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_CHAR, request); +} + +int +ncmpi_iget_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_SHORT, request); +} + +int +ncmpi_iget_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_INT, request); +} + +int +ncmpi_iget_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_LONG, request); +} + +int +ncmpi_iget_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iget_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vara(ncid, varid, start, count, + (void *)ip, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iput_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iput_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_BYTE, request); +} + +int +ncmpi_iput_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_CHAR, request); +} + +int +ncmpi_iput_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_SHORT, request); +} + +int +ncmpi_iput_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_INT, request); +} + +int +ncmpi_iput_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_LONG, request); +} + +int +ncmpi_iput_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iput_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_vars(ncid, varid, start, count, stride, + (const void *)op, nelems, MPI_DOUBLE, request); + +} + +int +ncmpi_iget_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iget_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_BYTE, request); +} + +int +ncmpi_iget_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_CHAR, request); +} + +int +ncmpi_iget_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_SHORT, request); +} + +int +ncmpi_iget_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_INT, request); +} + +int +ncmpi_iget_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_LONG, request); +} + +int +ncmpi_iget_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iget_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip, + NCMPI_Request *request) +{ + + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_vars(ncid, varid, start, count, stride, + (void *)ip, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iput_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iput_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_BYTE, request); +} + +int +ncmpi_iput_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_CHAR, request); +} + +int +ncmpi_iput_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_SHORT, request); +} + +int +ncmpi_iput_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_INT, request); +} + +int +ncmpi_iput_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_LONG, request); +} + +int +ncmpi_iput_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iput_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iput_varm(ncid, varid, start, count, stride, imap, + (const void *)op, nelems, MPI_DOUBLE, request); +} + +int +ncmpi_iget_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_UNSIGNED_CHAR, request); +} + +int +ncmpi_iget_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_BYTE, request); +} + +int +ncmpi_iget_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_CHAR, request); +} + +int +ncmpi_iget_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_SHORT, request); +} + +int +ncmpi_iget_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_INT, request); +} + +int +ncmpi_iget_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_LONG, request); +} + +int +ncmpi_iget_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_FLOAT, request); +} + +int +ncmpi_iget_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip, + NCMPI_Request *request) +{ + NC_var *varp; + NC *ncp; + int status; + int dim; + int nelems; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + nelems = 1; + for (dim = 0; dim < varp->ndims; dim++) + nelems *= count[dim]; + + return ncmpi_iget_varm(ncid, varid, start, count, stride, imap, + (void *)ip, nelems, MPI_DOUBLE, request); +} + +/* End non-blocking data access functions */ +/* #################################################################### */ +#endif Index: /tags/v1-0-3/src/lib/dim.c =================================================================== --- /tags/v1-0-3/src/lib/dim.c (revision 560) +++ /tags/v1-0-3/src/lib/dim.c (revision 560) @@ -0,0 +1,531 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#include "nc.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include "ncx.h" +#include "fbits.h" + +/* + * Free dim + * Formerly +NC_free_dim(dim) + */ +void +ncmpii_free_NC_dim(NC_dim *dimp) +{ + if(dimp == NULL) + return; + ncmpii_free_NC_string(dimp->name); + free(dimp); +} + + +NC_dim * +ncmpii_new_x_NC_dim(NC_string *name) +{ + NC_dim *dimp; + + dimp = (NC_dim *) malloc(sizeof(NC_dim)); + if(dimp == NULL) + return NULL; + + dimp->name = name; + dimp->size = 0; + + return(dimp); +} + + +/* + * Formerly +NC_new_dim(const char *name, long size) + */ +static NC_dim * +ncmpii_new_NC_dim(const char *name, MPI_Offset size) +{ + NC_string *strp; + NC_dim *dimp; + + strp = ncmpii_new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + dimp = ncmpii_new_x_NC_dim(strp); + if(dimp == NULL) + { + ncmpii_free_NC_string(strp); + return NULL; + } + + dimp->size = size; + + return(dimp); +} + + +static NC_dim * +dup_NC_dim(const NC_dim *dimp) +{ + return ncmpii_new_NC_dim(dimp->name->cp, (MPI_Offset) dimp->size); +} + +/* + * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension. + * Return dimid or -1 on not found. + * *dimpp is set to the appropriate NC_dim. + * The loop structure is odd. In order to parallelize, + * we moved a clearer 'break' inside the loop body to the loop test. + */ +int +ncmpii_find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + { + int dimid = 0; + NC_dim **loc = ncap->value; + + for(; (size_t) dimid < ncap->nelems + && (*loc)->size != NC_UNLIMITED; dimid++, loc++) + { + /*EMPTY*/ + } + if(dimid >= ncap->nelems) + return(-1); /* not found */ + /* else, normal return */ + if(dimpp != NULL) + *dimpp = *loc; + return dimid; + } +} + + +/* + * Step thru NC_DIMENSION array, seeking match on name. + * Return dimid or -1 on not found. + * *dimpp is set to the appropriate NC_dim. + * The loop structure is odd. In order to parallelize, + * we moved a clearer 'break' inside the loop body to the loop test. + */ +static int +NC_finddim(const NC_dimarray *ncap, const char *name, NC_dim **dimpp) +{ + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + { + size_t slen = strlen(name); + int dimid = 0; + NC_dim **loc = (NC_dim **) ncap->value; + + for(; (size_t) dimid < ncap->nelems + && (strlen((*loc)->name->cp) != slen + || strncmp((*loc)->name->cp, name, slen) != 0); + dimid++, loc++) + { + /*EMPTY*/ + } + if(dimid >= ncap->nelems) + return(-1); /* not found */ + /* else, normal return */ + if(dimpp != NULL) + *dimpp = *loc; + return(dimid); + } +} + + +/* dimarray */ + + +/* + * Free the stuff "in" (referred to by) an NC_dimarray. + * Leaves the array itself allocated. + */ +void +ncmpii_free_NC_dimarrayV0(NC_dimarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_dim **dpp = ncap->value; + NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + ncmpii_free_NC_dim(*dpp); + *dpp = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_dimarray values. + * formerly +NC_free_array() + */ +void +ncmpii_free_NC_dimarrayV(NC_dimarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + ncmpii_free_NC_dimarrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +ncmpii_dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_dim *); + ncap->value = (NC_dim **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_dim **dpp = ncap->value; + const NC_dim **drpp = (const NC_dim **)ref->value; + NC_dim *const *const end = &dpp[ref->nelems]; + for( /*NADA*/; dpp < end; drpp++, dpp++, ncap->nelems++) + { + *dpp = dup_NC_dim(*drpp); + if(*dpp == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + ncmpii_free_NC_dimarrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp) +{ + NC_dim **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_dim **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +NC_dim * +ncmpii_elem_NC_dimarray(const NC_dimarray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + + +/* Public */ + +int +ncmpi_def_dim(int ncid, const char *name, MPI_Offset size, int *dimidp) +{ + int status; + NC *ncp; + int dimid; + NC_dim *dimp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + /* MPI_Offset is usually a signed value, but serial netcdf uses + * size_t -- normally unsigned */ + if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) { + /* CDF2 format and LFS */ + if (size > X_UINT_MAX - 3 || (size < 0)) + /* "-3" handles rounded-up size */ + return NC_EDIMSIZE; + } else { + /* CDF1 format */ + if (size > X_INT_MAX - 3 || (size < 0)) + return NC_EDIMSIZE; + } + + if(size == NC_UNLIMITED) + { + dimid = ncmpii_find_NC_Udim(&ncp->dims, &dimp); + if(dimid != -1) + { + assert(dimid != -1); + return NC_EUNLIMIT; + } + } + + if(ncp->dims.nelems >= NC_MAX_DIMS) + return NC_EMAXDIMS; + + dimid = NC_finddim(&ncp->dims, name, &dimp); + if(dimid != -1) + return NC_ENAMEINUSE; + + dimp = ncmpii_new_NC_dim(name, size); + if(dimp == NULL) + return NC_ENOMEM; + status = incr_NC_dimarray(&ncp->dims, dimp); + if(status != NC_NOERR) + { + ncmpii_free_NC_dim(dimp); + return status; + } + + if(dimidp != NULL) + *dimidp = (int)ncp->dims.nelems -1; + return NC_NOERR; +} + + +int +ncmpi_inq_dimid(int ncid, const char *name, int *dimid_ptr) +{ + int status; + NC *ncp; + int dimid; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimid = NC_finddim(&ncp->dims, name, NULL); + + if(dimid == -1) + return NC_EBADDIM; + + *dimid_ptr = dimid; + return NC_NOERR; +} + + +int +ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *sizep) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = ncmpii_elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(name != NULL) + { + (void)strncpy(name, dimp->name->cp, + dimp->name->nchars); + name[dimp->name->nchars] = 0; + } + if(sizep != 0) + { + if(dimp->size == NC_UNLIMITED) + *sizep = NC_get_numrecs(ncp); + else + *sizep = dimp->size; + } + return NC_NOERR; +} + + +int +ncmpi_inq_dimname(int ncid, int dimid, char *name) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = ncmpii_elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(name != NULL) + { + (void)strncpy(name, dimp->name->cp, + dimp->name->nchars); + name[dimp->name->nchars] = 0; + } + + return NC_NOERR; +} + + +int +ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = ncmpii_elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(lenp != 0) + { + if(dimp->size == NC_UNLIMITED) + *lenp = NC_get_numrecs(ncp); + else + *lenp = dimp->size; + } + return NC_NOERR; +} + + +int +ncmpi_rename_dim( int ncid, int dimid, const char *newname) +{ + int status; + NC *ncp; + int existid; + NC_dim *dimp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + status = ncmpii_NC_check_name(newname); + if(status != NC_NOERR) + return status; + + existid = NC_finddim(&ncp->dims, newname, &dimp); + if(existid != -1) + return NC_ENAMEINUSE; + + dimp = ncmpii_elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(NC_indef(ncp)) + { + NC_string *old = dimp->name; + NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname); + if(newStr == NULL) + return NC_ENOMEM; + dimp->name = newStr; + ncmpii_free_NC_string(old); + return NC_NOERR; + } + + /* else, not in define mode */ + + status = ncmpii_set_NC_string(dimp->name, newname); + if(status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} Index: /tags/v1-0-3/src/lib/ncconfig.in =================================================================== --- /tags/v1-0-3/src/lib/ncconfig.in (revision 584) +++ /tags/v1-0-3/src/lib/ncconfig.in (revision 584) @@ -0,0 +1,278 @@ +/* src/lib/ncconfig.in. Generated from configure.in by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define if able to support nonblocking routines */ +#undef ENABLE_NONBLOCKING + +/* Define if Fortran names are lower case */ +#undef F77_NAME_LOWER + +/* Define if Fortran names are lower case with two trailing underscore2 */ +#undef F77_NAME_LOWER_2USCORE + +/* Define if Fortran names are lower case with one trailing underscore */ +#undef F77_NAME_LOWER_USCORE + +/* Define if Fortran names are uppercase */ +#undef F77_NAME_UPPER + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MPIO_H + +/* available */ +#undef HAVE_MPI_CHARACTER + +/* available */ +#undef HAVE_MPI_COMBINER_DARRAY + +/* available */ +#undef HAVE_MPI_COMBINER_DUP + +/* available */ +#undef HAVE_MPI_COMBINER_F90_COMPLEX + +/* available */ +#undef HAVE_MPI_COMBINER_F90_INTEGER + +/* available */ +#undef HAVE_MPI_COMBINER_F90_REAL + +/* available */ +#undef HAVE_MPI_COMBINER_HINDEXED_INTEGER + +/* available */ +#undef HAVE_MPI_COMBINER_HVECTOR_INTEGER + +/* available */ +#undef HAVE_MPI_COMBINER_INDEXED_BLOCK + +/* available */ +#undef HAVE_MPI_COMBINER_RESIZED + +/* available */ +#undef HAVE_MPI_COMBINER_STRUCT_INTEGER + +/* available */ +#undef HAVE_MPI_COMBINER_SUBARRAY + +/* available */ +#undef HAVE_MPI_COMPLEX16 + +/* available */ +#undef HAVE_MPI_COMPLEX32 + +/* available */ +#undef HAVE_MPI_COMPLEX8 + +/* available */ +#undef HAVE_MPI_DOUBLE_PRECISION + +/* Define to 1 if you have the `MPI_Info_dup' function. */ +#undef HAVE_MPI_INFO_DUP + +/* available */ +#undef HAVE_MPI_INTEGER + +/* available */ +#undef HAVE_MPI_INTEGER1 + +/* available */ +#undef HAVE_MPI_INTEGER16 + +/* available */ +#undef HAVE_MPI_INTEGER2 + +/* available */ +#undef HAVE_MPI_INTEGER4 + +/* available */ +#undef HAVE_MPI_INTEGER8 + +/* available */ +#undef HAVE_MPI_LB + +/* available */ +#undef HAVE_MPI_REAL + +/* available */ +#undef HAVE_MPI_REAL16 + +/* available */ +#undef HAVE_MPI_REAL4 + +/* available */ +#undef HAVE_MPI_REAL8 + +/* Define to 1 if you have the `MPI_Request_get_status' function. */ +#undef HAVE_MPI_REQUEST_GET_STATUS + +/* Define to 1 if you have the `MPI_Type_dup' function. */ +#undef HAVE_MPI_TYPE_DUP + +/* available */ +#undef HAVE_MPI_UB + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#undef HAVE_PTRDIFF_T + +/* Define to 1 if the system has the type `ssize_t'. */ +#undef HAVE_SSIZE_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if `st_blksize' is member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BLKSIZE + +/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use + `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */ +#undef HAVE_ST_BLKSIZE + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if the system has the type `uchar'. */ +#undef HAVE_UCHAR + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Type of NC_BYTE */ +#undef NCBYTE_T + +/* Type of NC_SHORT */ +#undef NCSHORT_T + +/* C type for Fortran dobule */ +#undef NF_DOUBLEPRECISION_IS_C_ + +/* C type for Fortran INT1 */ +#undef NF_INT1_IS_C_ + +/* Type for Fortran INT1 */ +#undef NF_INT1_T + +/* C type for Fortran INT2 */ +#undef NF_INT2_IS_C_ + +/* Type for Fortran INT2 */ +#undef NF_INT2_T + +/* C type for Fortran INT */ +#undef NF_INT_IS_C_ + +/* C type for Fortran REAL */ +#undef NF_REAL_IS_C_ + +/* Does sytem have IEEE FLOAT */ +#undef NO_IEEE_FLOAT + +/* Define if system lacks strerror */ +#undef NO_STRERROR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `double', as computed by sizeof. */ +#undef SIZEOF_DOUBLE + +/* The size of `float', as computed by sizeof. */ +#undef SIZEOF_FLOAT + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The number of bytes in an MPI_Offset */ +#undef SIZEOF_MPI_OFFSET + +/* The size of `off_t', as computed by sizeof. */ +#undef SIZEOF_OFF_T + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +# undef __CHAR_UNSIGNED__ +#endif + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t Index: /tags/v1-0-3/src/lib/attr.c =================================================================== --- /tags/v1-0-3/src/lib/attr.c (revision 560) +++ /tags/v1-0-3/src/lib/attr.c (revision 560) @@ -0,0 +1,2273 @@ +/* Do not edit this file. It is produced from the corresponding .m4 source */ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#include "nc.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include "ncx.h" +#include "fbits.h" +#include "rnd.h" + +/* Prototypes of functions only used in this file */ +static NC_attr *elem_NC_attrarray(const NC_attrarray *ncap, size_t elem); + +/* + * Free attr + * Formerly +NC_free_attr() + */ +void +ncmpii_free_NC_attr(NC_attr *attrp) +{ + + if(attrp == NULL) + return; + ncmpii_free_NC_string(attrp->name); + free(attrp); +} + + +/* + * How much space will 'nelems' of 'type' take in + * external representation (as the values of an attribute)? + */ +static size_t +ncmpix_len_NC_attrV(nc_type type, size_t nelems) +{ + switch(type) { + case NC_BYTE: + case NC_CHAR: + return ncmpix_len_char(nelems); + case NC_SHORT: + return ncmpix_len_short(nelems); + case NC_INT: + return ncmpix_len_int(nelems); + case NC_FLOAT: + return ncmpix_len_float(nelems); + case NC_DOUBLE: + return ncmpix_len_double(nelems); + default: + assert("ncmpix_len_NC_attr bad type" == 0); + } + return 0; +} + + +NC_attr * +ncmpii_new_x_NC_attr( + NC_string *strp, + nc_type type, + size_t nelems) +{ + NC_attr *attrp; + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + size_t sz = M_RNDUP(sizeof(NC_attr)); + + assert(!(xsz == 0 && nelems != 0)); + + sz += xsz; + + attrp = (NC_attr *) malloc(sz); + if(attrp == NULL ) + return NULL; + + attrp->xsz = xsz; + + attrp->name = strp; + attrp->type = type; + attrp->nelems = nelems; + if(xsz != 0) + attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr)); + else + attrp->xvalue = NULL; + + return(attrp); +} + + +/* + * Formerly +NC_new_attr(name,type,count,value) + */ +static NC_attr * +ncmpii_new_NC_attr( + const char *name, + nc_type type, + size_t nelems) +{ + NC_string *strp; + NC_attr *attrp; + + assert(name != NULL && *name != 0); + + strp = ncmpii_new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + attrp = ncmpii_new_x_NC_attr(strp, type, nelems); + if(attrp == NULL) + { + ncmpii_free_NC_string(strp); + return NULL; + } + + return(attrp); +} + + +static NC_attr * +dup_NC_attr(const NC_attr *rattrp) +{ + NC_attr *attrp = ncmpii_new_NC_attr(rattrp->name->cp, + rattrp->type, rattrp->nelems); + if(attrp == NULL) + return NULL; + (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz); + return attrp; +} + +/* attrarray */ + +/* + * Free the stuff "in" (referred to by) an NC_attrarray. + * Leaves the array itself allocated. + */ +void +ncmpii_free_NC_attrarrayV0(NC_attrarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_attr **app = ncap->value; + NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + ncmpii_free_NC_attr(*app); + *app = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_attrarray values. + * formerly +NC_free_array() + */ +void +ncmpii_free_NC_attrarrayV(NC_attrarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + ncmpii_free_NC_attrarrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +ncmpii_dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_attr *); + ncap->value = (NC_attr **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_attr **app = ncap->value; + const NC_attr **drpp = (const NC_attr **)ref->value; + NC_attr *const *const end = &app[ref->nelems]; + for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++) + { + *app = dup_NC_attr(*drpp); + if(*app == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + ncmpii_free_NC_attrarrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp) +{ + NC_attr **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *)); + if(vp == NULL) + return NC_ENOMEM; + + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_attr **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *)); + if(vp == NULL) + return NC_ENOMEM; + + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +static NC_attr * +elem_NC_attrarray(const NC_attrarray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + +/* End attarray per se */ + +/* + * Given ncp and varid, return ptr to array of attributes + * else NULL on error + */ +static NC_attrarray * +NC_attrarray0( NC *ncp, int varid) +{ + NC_attrarray *ap; + + if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */ + { + ap = &ncp->attrs; + } + else if(varid >= 0 && (size_t) varid < ncp->vars.nelems) + { + NC_var **vpp; + vpp = (NC_var **)ncp->vars.value; + vpp += varid; + ap = &(*vpp)->attrs; + } else { + ap = NULL; + } + return(ap); +} + + +/* + * Step thru NC_ATTRIBUTE array, seeking match on name. + * return match or NULL if Not Found. + */ +NC_attr ** +ncmpii_NC_findattr(const NC_attrarray *ncap, const char *name) +{ + NC_attr **attrpp; + size_t attrid; + size_t slen; + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return NULL; + + attrpp = (NC_attr **) ncap->value; + + slen = strlen(name); + + for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++) + { + if(strlen((*attrpp)->name->cp) == slen && + strncmp((*attrpp)->name->cp, name, slen) == 0) + { + return(attrpp); /* Normal return */ + } + } + return(NULL); +} + + +/* + * Look up by ncid, varid and name, return NULL if not found + */ +static int +NC_lookupattr(int ncid, + int varid, + const char *name, /* attribute name */ + NC_attr **attrpp) /* modified on return */ +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **tmp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + tmp = ncmpii_NC_findattr(ncap, name); + if(tmp == NULL) + return NC_ENOTATT; + + if(attrpp != NULL) + *attrpp = *tmp; + + return ENOERR; +} + +/* Public */ + +int +ncmpi_inq_attname(int ncid, int varid, int attnum, char *name) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + attrp = elem_NC_attrarray(ncap, (size_t)attnum); + if(attrp == NULL) + return NC_ENOTATT; + + (void) strncpy(name, attrp->name->cp, attrp->name->nchars); + name[attrp->name->nchars] = 0; + + return NC_NOERR; +} + + +int +ncmpi_inq_attid(int ncid, int varid, const char *name, int *attnump) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp == NULL) + return NC_ENOTATT; + + if(attnump != NULL) + *attnump = (int)(attrpp - ncap->value); + + return NC_NOERR; +} + +int +ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(datatypep != NULL) + *datatypep = attrp->type; + + return NC_NOERR; +} + +int +ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(lenp != NULL) + *lenp = attrp->nelems; + + return NC_NOERR; +} + +int +ncmpi_inq_att(int ncid, + int varid, + const char *name, /* input, attribute name */ + nc_type *datatypep, + MPI_Offset *lenp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(datatypep != NULL) + *datatypep = attrp->type; + if(lenp != NULL) + *lenp = attrp->nelems; + + return NC_NOERR; +} + + +int +ncmpi_rename_att( int ncid, int varid, const char *name, const char *newname) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **tmp; + NC_attr *attrp; + NC_string *newStr, *old; + + /* sortof inline clone of NC_lookupattr() */ + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + +/* bugs found by Jianwei Li + status = ncmpii_NC_check_name(name); +*/ + status = ncmpii_NC_check_name(newname); + if(status != NC_NOERR) + return status; + + tmp = ncmpii_NC_findattr(ncap, name); + if(tmp == NULL) + return NC_ENOTATT; + attrp = *tmp; + /* end inline clone NC_lookupattr() */ + + if(ncmpii_NC_findattr(ncap, newname) != NULL) + { + /* name in use */ + return NC_ENAMEINUSE; + } + + old = attrp->name; + if(NC_indef(ncp)) + { + newStr = ncmpii_new_NC_string(strlen(newname), newname); + if( newStr == NULL) + return NC_ENOMEM; + attrp->name = newStr; + ncmpii_free_NC_string(old); + return NC_NOERR; + } + /* else */ + status = ncmpii_set_NC_string(old, newname); + if( status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} + + +int +ncmpi_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int ovarid) +{ + int status; + NC_attr *iattrp; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_lookupattr(ncid_in, varid_in, name, &iattrp); + if(status != NC_NOERR) + return status; + + status = ncmpii_NC_check_id(ncid_out, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, ovarid); + if(ncap == NULL) + return NC_ENOTVAR; + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + attrp = *attrpp; /* convenience */ + + if(iattrp->xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = iattrp->xsz; + attrp->type = iattrp->type; + attrp->nelems = iattrp->nelems; + + (void) memcpy(attrp->xvalue, iattrp->xvalue, + iattrp->xsz); + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + attrp = ncmpii_new_NC_attr(name, iattrp->type, iattrp->nelems); + if(attrp == NULL) + return NC_ENOMEM; + + (void) memcpy(attrp->xvalue, iattrp->xvalue, + iattrp->xsz); + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + status = incr_NC_attrarray(ncap, attrp); + if(status != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return status; + } + } + + return NC_NOERR; +} + + +int +ncmpi_del_att(int ncid, int varid, const char *name) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + int attrid; + MPI_Offset slen; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + /* sortof inline ncmpii_NC_findattr() */ + slen = strlen(name); + + attrpp = (NC_attr **) ncap->value; + for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++) + { + if( slen == (*attrpp)->name->nchars && + strncmp(name, (*attrpp)->name->cp, slen) == 0) + { + old = *attrpp; + break; + } + } + if( (size_t) attrid == ncap->nelems ) + return NC_ENOTATT; + /* end inline NC_findattr() */ + + /* shuffle down */ + for(attrid++; (size_t) attrid < ncap->nelems; attrid++) + { + *attrpp = *(attrpp + 1); + attrpp++; + } + *attrpp = NULL; + /* decrement count */ + ncap->nelems--; + + ncmpii_free_NC_attr(old); + + return NC_NOERR; +} + + +static int +ncmpix_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_uchar(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_uchar(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_uchar(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_uchar(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_uchar(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Iuchar invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_uchar(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_uchar(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_uchar(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_uchar(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_uchar(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Iuchar invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_schar(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_schar(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_schar(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_schar(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_schar(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Ischar invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_schar(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_schar(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_schar(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_schar(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_schar(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Ischar invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_short(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_short(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_short(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_short(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_short(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Ishort invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_short(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_short(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_short(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_short(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_short(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Ishort invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_int(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_int(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_int(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_int(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_int(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Iint invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_int(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_int(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_int(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_int(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_int(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Iint invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_long(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_long(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_long(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_long(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_long(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Ilong invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_long(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_long(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_long(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_long(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_long(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Ilong invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_float(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_float(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_float(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_float(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_float(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Ifloat invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_float(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_float(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_float(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_float(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_float(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Ifloat invalid type" == 0); + return NC_EBADTYPE; + } +} + + +static int +ncmpix_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_putn_schar_double(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_putn_short_double(xpp, nelems, tp); + case NC_INT: + return ncmpix_putn_int_double(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_putn_float_double(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_putn_double_double(xpp, nelems, tp); + default: + assert("ncmpix_pad_putn_Idouble invalid type" == 0); + return NC_EBADTYPE; + } +} + +static int +ncmpix_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncmpix_pad_getn_schar_double(xpp, nelems, tp); + case NC_SHORT: + return ncmpix_pad_getn_short_double(xpp, nelems, tp); + case NC_INT: + return ncmpix_getn_int_double(xpp, nelems, tp); + case NC_FLOAT: + return ncmpix_getn_float_double(xpp, nelems, tp); + case NC_DOUBLE: + return ncmpix_getn_double_double(xpp, nelems, tp); + default: + assert("ncmpix_pad_getn_Idouble invalid type" == 0); + return NC_EBADTYPE; + } +} + + + +int +ncmpi_put_att_text(int ncid, int varid, const char *name, + MPI_Offset nelems, const char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(NC_CHAR, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = NC_CHAR; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_text(&xp, nelems, value); + if(status != NC_NOERR) + return status; + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + attrp = ncmpii_new_NC_attr(name, NC_CHAR, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_text(&xp, nelems, value); + if(status != NC_NOERR) + return status; + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + status = incr_NC_attrarray(ncap, attrp); + if(status != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return status; + } + } + + return NC_NOERR; +} + + +int +ncmpi_get_att_text(int ncid, int varid, const char *name, char *str) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type != NC_CHAR) + return NC_ECHAR; + + /* else */ + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_text(&xp, attrp->nelems, str); + } +} + + + + +int +ncmpi_put_att_schar(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const signed char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ischar(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ischar + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ischar(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ischar + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Ischar(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_uchar(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const unsigned char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Iuchar(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Iuchar + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Iuchar(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Iuchar + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Iuchar(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_short(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const short *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ishort(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ishort + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ishort(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ishort + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_short(int ncid, int varid, const char *name, short *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Ishort(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_int(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const int *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Iint(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Iint + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Iint(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Iint + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_int(int ncid, int varid, const char *name, int *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Iint(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_long(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const long *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ilong(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ilong + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ilong(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ilong + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_long(int ncid, int varid, const char *name, long *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Ilong(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_float(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const float *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ifloat(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ifloat + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Ifloat(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Ifloat + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_float(int ncid, int varid, const char *name, float *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Ifloat(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +ncmpi_put_att_double(int ncid, int varid, const char *name, + nc_type type, MPI_Offset nelems, const double *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = ncmpii_NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncmpix_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Idouble(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = ncmpii_NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Idouble + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = ncmpii_new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncmpix_pad_putn_Idouble(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + ncmpii_free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncmpix_pad_putn_Idouble + */ + if(lstatus != NC_NOERR) + { + ncmpii_free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +ncmpi_get_att_double(int ncid, int varid, const char *name, double *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncmpix_pad_getn_Idouble(&xp, attrp->nelems, tp, attrp->type); + } +} + + + +/* deprecated, used to support the 2.x interface */ +int +ncmpii_put_att( + int ncid, + int varid, + const char *name, + nc_type type, + size_t nelems, + const void *value) +{ + switch (type) { + case NC_BYTE: + return ncmpi_put_att_schar(ncid, varid, name, type, nelems, + (schar *)value); + case NC_CHAR: + return ncmpi_put_att_text(ncid, varid, name, nelems, + (char *)value); + case NC_SHORT: + return ncmpi_put_att_short(ncid, varid, name, type, nelems, + (short *)value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return ncmpi_put_att_int(ncid, varid, name, type, nelems, + (int *)value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return ncmpi_put_att_long(ncid, varid, name, type, nelems, + (long *)value); +#endif + case NC_FLOAT: + return ncmpi_put_att_float(ncid, varid, name, type, nelems, + (float *)value); + case NC_DOUBLE: + return ncmpi_put_att_double(ncid, varid, name, type, nelems, + (double *)value); + default: + return NC_EBADTYPE; + } +} + + +/* deprecated, used to support the 2.x interface */ +int +ncmpii_get_att(int ncid, int varid, const char *name, void *value) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + switch (attrp->type) { + case NC_BYTE: + return ncmpi_get_att_schar(ncid, varid, name, + (schar *)value); + case NC_CHAR: + return ncmpi_get_att_text(ncid, varid, name, + (char *)value); + case NC_SHORT: + return ncmpi_get_att_short(ncid, varid, name, + (short *)value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return ncmpi_get_att_int(ncid, varid, name, + (int *)value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return ncmpi_get_att_long(ncid, varid, name, + (long *)value); +#endif + case NC_FLOAT: + return ncmpi_get_att_float(ncid, varid, name, + (float *)value); + case NC_DOUBLE: + return ncmpi_get_att_double(ncid, varid, name, + (double *)value); + default: + return NC_EBADTYPE; + } +} Index: /tags/v1-0-3/src/lib/ncmpidtype.c =================================================================== --- /tags/v1-0-3/src/lib/ncmpidtype.c (revision 590) +++ /tags/v1-0-3/src/lib/ncmpidtype.c (revision 590) @@ -0,0 +1,531 @@ +/***************************************************************************** + * + * This file is created by Northwestern University and Argonne National + * Laboratory + * + ****************************************************************************/ + + +#include "nc.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#ifdef HAVE_MPIO_H +#include +#endif + +#include "ncmpidtype.h" + +/*@ + ncmpii_type_filter - Map a basic MPI datatype into one of the eight + that we process natively. + + We unfortunately need to wrap all these types in case they aren't defined. + + Return: + On success, one of MPI_CHAR, MPI_UNSIGNED_CHAR, MPI_BYTE, MPI_SHORT, + MPI_INT, MPI_LONG, MPI_FLOAT, and MPI_DOUBLE. + On failure, MPI_DATATYPE_NULL. +@*/ +static MPI_Datatype ncmpii_type_filter(MPI_Datatype type) +{ + /* char types */ +#ifdef HAVE_MPI_CHARACTER + if (type == MPI_CHARACTER) + return MPI_CHAR; +#endif + if (type == MPI_CHAR) + return MPI_CHAR; + + /* unsigned char types */ + if (type == MPI_UNSIGNED_CHAR) + return MPI_UNSIGNED_CHAR; +#ifdef HAVE_MPI_INTEGER1 + if (type == MPI_INTEGER1) + return MPI_BYTE; +#endif + if (type == MPI_BYTE) + return MPI_BYTE; + + /* 2-byte integer types (only supported if MPI_SHORT is 2-bytes). */ +#if (SIZEOF_SHORT == 2) + #ifdef HAVE_MPI_INTEGER2 + if (type == MPI_INTEGER2) + return MPI_SHORT; + #endif + if (type == MPI_SHORT) + return MPI_SHORT; +#endif + + /* 4-byte integer types */ + { + MPI_Datatype int_4byte; +#if (SIZEOF_INT == 4) + int_4byte = MPI_INT; +#elif (SIZEOF_SHORT == 4) + int_4byte = MPI_SHORT; +#else + int_4byte = MPI_DATATYPE_NULL; /* no 4-byte type? */ +#endif + +#ifdef HAVE_MPI_INTEGER + if (type == MPI_INTEGER) + return int_4byte; +#endif +#ifdef HAVE_MPI_INTEGER4 + if (type == MPI_INTEGER4) + return int_4byte; +#endif +#if (SIZEOF_LONG == 4) + if (type == MPI_LONG) + return int_4byte; +#endif +#if (SIZEOF_INT == 4) + if (type == MPI_INT) + return MPI_INT; +#elif (SIZEOF_SHORT == 4) + if (type == MPI_SHORT) + return MPI_SHORT; +#endif + } + + /* 8-byte integer types (only supported if MPI_INT or MPI_LONG + * is 8-bytes). + */ +#if (SIZEOF_INT == 8) || (SIZEOF_LONG == 8) + #ifdef HAVE_MPI_INTEGER8 + if (type == MPI_INTEGER8) + #if (SIZEOF_INT == 8) + return MPI_INT; + #else + return MPI_LONG; + #endif + #endif + + #if (SIZEOF_INT == 8) + if (type == MPI_INT) + return MPI_INT; + #endif + #if (SIZEOF_LONG == 8) + if (type == MPI_LONG) + #if (SIZEOF_INT == 8) + return MPI_INT; + #else + return MPI_LONG; + #endif + #endif +#endif + + /* 4-byte float types (we assume float is 4-bytes). */ +#ifdef HAVE_MPI_REAL + if (type == MPI_REAL) + return MPI_FLOAT; +#endif +#ifdef HAVE_MPI_REAL4 + if (type == MPI_REAL4) + return MPI_FLOAT; +#endif + if (type == MPI_FLOAT) + return MPI_FLOAT; + + /* 8-byte float types (we assume double is 8-bytes). */ +#ifdef HAVE_MPI_REAL8 + if (type == MPI_REAL8) + return MPI_DOUBLE; +#endif +#ifdef HAVE_MPI_DOUBLE_PRECISION + if (type == MPI_DOUBLE_PRECISION) + return MPI_DOUBLE; +#endif + if (type == MPI_DOUBLE) + return MPI_DOUBLE; + +/* HP-MPI for example needs to handle MPI_LB and MPI_UB */ +#ifdef HAVE_MPI_LB + if (type == MPI_LB) { + if (SIZEOF_SIZE_T == 8) + return MPI_DOUBLE; + if (SIZEOF_SIZE_T == 4) + return MPI_DOUBLE; + } +#endif +#ifdef HAVE_MPI_UB + if (type == MPI_UB) { + if (SIZEOF_SIZE_T == 8) + return MPI_DOUBLE; + if (SIZEOF_SIZE_T == 4) + return MPI_DOUBLE; + } +#endif + +/* default */ + return MPI_DATATYPE_NULL; +} + +/*@ + ncmpi_darray_get_totalblock - Count the total number of blocks assigned + to the calling process by the darray datatype. + + Input: +. rank - rank of calling process +. ndims - number of dimensions for the array and process grid +. array_of_gsizes - Number of elements of type oldtype in each dimension + of global array (array of positive integers) +. array_of_distribs - Distribution of array in each dimension (array of state) +. array_of_dargs - Distribution argument in each dimension + (array of positive integers) +. array_of_psizes - Size of process grid in each dimension + (array of positive integers) + + Return: +. total number of blocks assigned from the distrubted array +@*/ + +static int ncmpii_darray_get_totalblks(int rank, + int ndims, + int array_of_gsizes[], + int array_of_distribs[], + int array_of_dargs[], + int array_of_psizes[]) +{ + int total_blocks = 1; + int subblocks, cycle, remain_cycle; + int i; + int pcoord; + + /* Process Grid ranking is always in C ORDER, + so compute proc coordinates from last dim */ + + for (i=ndims-1; i>=0; i--) { + if ( array_of_distribs[i] == MPI_DISTRIBUTE_NONE ) { + total_blocks *= array_of_gsizes[i]; + } else { + + pcoord = rank % array_of_psizes[i]; + rank /= array_of_psizes[i]; + if ( array_of_dargs[i] == MPI_DISTRIBUTE_DFLT_DARG ) { + subblocks = array_of_gsizes[i]/array_of_psizes[i]; + if ( subblocks*array_of_psizes[i]+pcoord < array_of_gsizes[i] ) + subblocks++; + } else { + cycle = array_of_dargs[i]*array_of_psizes[i]; + remain_cycle = array_of_gsizes[i] % cycle; + + subblocks = remain_cycle - pcoord*array_of_dargs[i]; + if (subblocks > array_of_dargs[i]) + subblocks = array_of_dargs[i]; + else if (subblocks < 0) + subblocks = 0; + + subblocks += array_of_gsizes[i]/cycle * array_of_dargs[i]; + } + + if (subblocks == 0) + return 0; + total_blocks *= subblocks; + + } + } + + return total_blocks; +} + + +/*@ + ncmpii_dtype_decode - Decode the MPI derived datatype to get the bottom + level primitive datatype information. + + Input: +. dtype - The datatype to be decoded (can be predefined type). + + Output: +. ptype - The bottom level primitive datatype (only one allowed) +. el_size - The size of the ptype +. nelems - Number of elements/entries of such ptype +. iscontig_of_ptypes - Whether dtype is a contiguous number of ptype +@*/ + +int ncmpii_dtype_decode(MPI_Datatype dtype, + MPI_Datatype *ptype, + int *el_size, + int *nelems, + int *isderived, + int *iscontig_of_ptypes) +{ + int i; + int tmpnelems, tmpel_size, total_blocks; + MPI_Datatype tmpptype; + int num_ints, num_adds, num_dtypes, combiner; + int *array_of_ints; + MPI_Aint *array_of_adds; + MPI_Datatype *array_of_dtypes; + void *arraybuf; + int memsz; + int count; + int ndims; + int status = NC_NOERR; + + *isderived = 0; + + if (dtype == MPI_DATATYPE_NULL) { + *nelems = 0; + *ptype = dtype; + *el_size = 0; + *iscontig_of_ptypes = 1; + return NC_NOERR; + } + + MPI_Type_get_envelope(dtype, &num_ints, &num_adds, &num_dtypes, &combiner); + + if ( +#ifdef HAVE_MPI_COMBINER_F90_INTEGER + combiner == MPI_COMBINER_F90_INTEGER || +#endif +#ifdef HAVE_MPI_COMBINER_F90_REAL + combiner == MPI_COMBINER_F90_REAL || +#endif +#ifdef HAVE_MPI_COMBINER_F90_COMPLEX + combiner == MPI_COMBINER_F90_COMPLEX || +#endif + 0 ) + { + fprintf(stderr, + "FIXME: F90_INTEGER, F90_REAL or F90_COMPLEX are not supported.\n"); + } + + if ( combiner == MPI_COMBINER_NAMED ) { + /* Predefined datatype */ + *nelems = 1; + if ( (*ptype = ncmpii_type_filter(dtype)) == MPI_DATATYPE_NULL ) + return NC_EUNSPTETYPE; + MPI_Type_size(dtype, el_size); + *iscontig_of_ptypes = 1; + return NC_NOERR; + } + + memsz = num_ints*sizeof(int) + + num_adds*sizeof(MPI_Aint) + + num_dtypes*sizeof(MPI_Datatype); + arraybuf = (void *)malloc(memsz); + array_of_ints = (int *)(arraybuf); + array_of_adds = (MPI_Aint *)(array_of_ints + num_ints); + array_of_dtypes = (MPI_Datatype *)(array_of_adds + num_adds); + + MPI_Type_get_contents(dtype, num_ints, num_adds, num_dtypes, + array_of_ints, array_of_adds, array_of_dtypes); + + switch (combiner) { + + /* single etype */ + + case MPI_COMBINER_CONTIGUOUS: + case MPI_COMBINER_HVECTOR: + case MPI_COMBINER_VECTOR: + case MPI_COMBINER_HINDEXED: + case MPI_COMBINER_INDEXED: +#ifdef HAVE_MPI_COMBINER_DUP + case MPI_COMBINER_DUP: +#endif +#ifdef HAVE_MPI_COMBINER_HVECTOR_INTEGER + case MPI_COMBINER_HVECTOR_INTEGER: +#endif +#ifdef HAVE_MPI_COMBINER_INDEXED_BLOCK + case MPI_COMBINER_INDEXED_BLOCK: +#endif +#ifdef HAVE_MPI_COMBINER_HINDEXED_INTEGER + case MPI_COMBINER_HINDEXED_INTEGER: +#endif +#ifdef HAVE_MPI_COMBINER_SUBARRAY + case MPI_COMBINER_SUBARRAY: +#endif +#ifdef HAVE_MPI_COMBINER_DARRAY + case MPI_COMBINER_DARRAY: +#endif +#ifdef HAVE_MPI_COMBINER_RESIZED + case MPI_COMBINER_RESIZED: +#endif + + status = ncmpii_dtype_decode(array_of_dtypes[0], ptype, el_size, + nelems, isderived, iscontig_of_ptypes); + if (*isderived) + MPI_Type_free(array_of_dtypes); + + break; + + /* multiple etypes */ + + case MPI_COMBINER_STRUCT: +#ifdef HAVE_MPI_COMBINER_STRUCT_INTEGER + case MPI_COMBINER_STRUCT_INTEGER: +#endif + count = array_of_ints[0]; + *el_size = 0; + for (i=0; i 0) + *nelems *= array_of_ints[1+i]; + } + for ( ; i 0) { + if (tmpptype != *ptype) + return NC_EMULTITYPES; + *nelems += tmpnelems*array_of_ints[1+i]; + } + } + + *iscontig_of_ptypes = 0; + + break; + + default: + break; + } + + *isderived = 1; + + switch (combiner) { + + /* single etype */ + + case MPI_COMBINER_CONTIGUOUS: + total_blocks = array_of_ints[0]; + break; + + case MPI_COMBINER_HVECTOR: + case MPI_COMBINER_VECTOR: +#ifdef HAVE_MPI_COMBINER_HVECTOR_INTEGER + case MPI_COMBINER_HVECTOR_INTEGER: +#endif +#ifdef HAVE_MPI_COMBINER_INDEXED_BLOCK + case MPI_COMBINER_INDEXED_BLOCK: +#endif + *iscontig_of_ptypes = 0; + total_blocks = array_of_ints[0]*array_of_ints[1]; + break; + + case MPI_COMBINER_HINDEXED: + case MPI_COMBINER_INDEXED: +#ifdef HAVE_MPI_COMBINER_HINDEXED_INTEGER + case MPI_COMBINER_HINDEXED_INTEGER: +#endif + *iscontig_of_ptypes = 0; + for (i=0, total_blocks=0; i 0) + free(arraybuf); + + return status; +} + +/*@ + ncmpii_data_repack - copy data between two buffers with different datatypes. + + Input: +. inbuf - input buffer where data is copied from +. incount - number of input elements +. intype - datatype of each element in input buffer +. outbuf - output buffer where data is copied to +. outcount - number of output elements +. outtype - datatype of each element in output buffer +@*/ + +int ncmpii_data_repack(void *inbuf, + int incount, + MPI_Datatype intype, + void *outbuf, + int outcount, + MPI_Datatype outtype) +{ + int intypesz, outtypesz; + int packsz; + void *packbuf; + int packpos; + + MPI_Type_size(intype, &intypesz); + MPI_Type_size(outtype, &outtypesz); + + if (incount*intypesz != outcount*outtypesz) { + /* input data amount does not match output data amount */ + /* NOTE: we ignore it for user responsibility or add error handling ? */ + + /* for rescue, guarantee output data amount <= input data amount */ + if (incount*intypesz < outcount*outtypesz) + outcount = incount*intypesz/outtypesz; + } + + if (incount == 0) + return NC_NOERR; + + /* local pack-n-unpack, using MPI_COMM_SELF */ + MPI_Pack_size(incount, intype, MPI_COMM_SELF, &packsz); + packbuf = (void *)malloc(packsz); + packpos = 0; + MPI_Pack(inbuf, incount, intype, packbuf, packsz, &packpos, MPI_COMM_SELF); + packpos = 0; + MPI_Unpack(packbuf, packsz, &packpos, outbuf, outcount, outtype, MPI_COMM_SELF); + free(packbuf); + + return NC_NOERR; +} Index: /tags/v1-0-3/src/lib/fbits.h =================================================================== --- /tags/v1-0-3/src/lib/fbits.h (revision 2) +++ /tags/v1-0-3/src/lib/fbits.h (revision 2) @@ -0,0 +1,26 @@ +/* + * Copyright 1995, University Corporation for Atmospheric Research + * See top level COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#ifndef _FBITS_H_ +#define _FBITS_H_ + +/* + * Macros for dealing with flag bits. + */ +#define fSet(t, f) ((t) |= (f)) +#define fClr(t, f) ((t) &= ~(f)) +#define fIsSet(t, f) ((t) & (f)) +#define fMask(t, f) ((t) & ~(f)) + +/* + * Propositions + */ +/* a implies b */ +#define pIf(a,b) (!(a) || (b)) +/* a if and only if b, use == when it makes sense */ +#define pIff(a,b) (((a) && (b)) || (!(a) && !(b))) + +#endif /*!FBITS_H_*/ Index: /tags/v1-0-3/src/lib/depend =================================================================== --- /tags/v1-0-3/src/lib/depend (revision 101) +++ /tags/v1-0-3/src/lib/depend (revision 101) @@ -0,0 +1,50 @@ +validator: validator.c +header.o: header.c +header.o: nc.h +header.o: ncx.h +mpincio.o: mpincio.c +mpincio.o: ncio.h +mpincio.o: ncconfig.h +mpincio.o: fbits.h +mpincio.o: rnd.h +mpinetcdf.o: mpinetcdf.c +mpinetcdf.o: nc.h +mpinetcdf.o: ncx.h +attr.o: attr.c +attr.o: fbits.h +attr.o: nc.h +attr.o: ncconfig.h +attr.o: ncio.h +attr.o: ncx.h +attr.o: pnetcdf.h +attr.o: rnd.h +dim.o: dim.c +dim.o: fbits.h +dim.o: nc.h +dim.o: ncconfig.h +dim.o: ncio.h +dim.o: ncx.h +dim.o: pnetcdf.h +dim.o: rnd.h +error.o: error.c +error.o: pnetcdf.h +nc.o: fbits.h +nc.o: nc.c +nc.o: nc.h +nc.o: ncconfig.h +nc.o: ncio.h +nc.o: ncx.h +nc.o: pnetcdf.h +nc.o: rnd.h +ncx.o: ncconfig.h +ncx.o: ncx.c +ncx.o: ncx.h +ncx.o: rnd.h +var.o: fbits.h +var.o: nc.h +var.o: ncconfig.h +var.o: ncio.h +var.o: ncx.h +var.o: pnetcdf.h +var.o: rnd.h +var.o: var.c Index: /tags/v1-0-3/src/lib/ncmpidtype.h =================================================================== --- /tags/v1-0-3/src/lib/ncmpidtype.h (revision 478) +++ /tags/v1-0-3/src/lib/ncmpidtype.h (revision 478) @@ -0,0 +1,25 @@ +/***************************************************************************** + * + * This file is created by Northwestern University and Argonne National + * Laboratory + * + ****************************************************************************/ + +#ifndef NCMPI_DTYPE_H +#define NCMPI_DTYPE_H + +int ncmpii_dtype_decode(MPI_Datatype dtype, + MPI_Datatype *ptype, + int *el_size, + int *nelems, + int *isderived, + int *iscontig_of_ptypes); + +int ncmpii_data_repack(void *inbuf, + int incount, + MPI_Datatype intype, + void *outbuf, + int outcount, + MPI_Datatype outtype); + +#endif Index: /tags/v1-0-3/src/lib/TODO =================================================================== --- /tags/v1-0-3/src/lib/TODO (revision 420) +++ /tags/v1-0-3/src/lib/TODO (revision 420) @@ -0,0 +1,98 @@ +# +# Unimplemented functions, approaches we have to revisit, and other unfinished +# tasks +# + +DATA MODE FUNCTIONS: U == unimpplemented I == implemented + +ncmpi_get text uchar schar short int long float double +var1 [0] I I I I I I I I +var I I I I I I I I +var_all I I I I I I I I +vara I I I I I I I I +vara_all I I I I I I I I +vars I I I I I I I I +vars_all I I I I I I I I +varm I I I I I I I I +varm_all I I I I I I I I + +ncmpi_put text uchar schar short int long float double +var1 [0] I I I I I I I I +var I I I I I I I I +var_all [1] +vara I I I I I I I I +vara_all I I I I I I I I +vars I I I I I I I I +vars_all I I I I I I I I +varm I I I I I I I I +varm_all I I I I I I I I + +[0] the var1 functions are all independent operations + +[1] jianwei says "ncmpi_put_var_all does not exist at all, as all such + attempt would result in using ncmpi_put_vara_all, while + ncmpi_get_var_all is designed for a special case of optimization so + that all processes get the whole array but each process only reads a + subarray for example." + +OTHER FUNCTIONS: + +the following functions are just wrappers around netcdf implementations: + +. miscelaneous: + ncmpi_strerror() + +. the Define Mode functions: + ncmpi_def_dim() + ncmpi_def_var() + ncmpi_rename_dim() + ncmpi_rename_var() + +. the inquiry functions + ncmpi_inq() + ncmpi_inq_ndims() + ncmpi_inq_nvars() + ncmpi_inq_natts() + ncmpi_inq_unlimdim() + ncmpi_inq_dimid() + ncmpi_inq_dim() + ncmpi_inq_dimname() + ncmpi_inq_dimlen() + ncmpi_inq_var() + ncmpi_inq_varid() + ncmpi_inq_varname() + ncmpi_inq_vartype() + ncmpi_inq_varndims() + ncmpi_inq_vardimid() + ncmpi_inq_varnatts() + +. the Attribute functions + ncmpi_inq_att() + ncmpi_inq_attid() + ncmpi_inq_atttype() + ncmpi_inq_attlen() + ncmpi_inq_attname() + ncmpi_copy_att() + ncmpi_rename_att() + ncmpi_del_att() + ncmpi_put_att_text() + ncmpi_get_att_text() + ncmpi_put_att_uchar() + ncmpi_get_att_uchar() + ncmpi_put_att_schar() + ncmpi_get_att_schar() + ncmpi_put_att_short() + ncmpi_get_att_short() + ncmpi_put_att_int() + ncmpi_get_att_int() + ncmpi_put_att_long() + ncmpi_get_att_long() + ncmpi_put_att_float() + ncmpi_get_att_float() + ncmpi_put_att_double() + ncmpi_get_att_double() + + +Implemented: +. the flexible data mode and high-level data mode interfaces for many types + using MPI derived datatype to specify memory data layout Index: /tags/v1-0-3/src/lib/validator.c =================================================================== --- /tags/v1-0-3/src/lib/validator.c (revision 465) +++ /tags/v1-0-3/src/lib/validator.c (revision 465) @@ -0,0 +1,739 @@ +/*************************************************************************** + * + * This file is written by Northwestern University and Argonne National + * Laboratory + * + **************************************************************************/ +#include "nc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include "ncx.h" + +#ifndef MAX +#define MAX(mm,nn) (((mm) > (nn)) ? (mm) : (nn)) +#endif +#ifndef MIN +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) +#endif + +/* + * "magic number" at beginning of file: 0x43444601 (big endian) + */ +static const schar ncmagic[] = {'C', 'D', 'F', 0x01}; + +/* Prototypes for functions used only in this file */ +static int val_get_NCtype(bufferinfo *gbp, NCtype *typep); +static int val_get_size_t(bufferinfo *gbp, size_t *sp); +static int val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp); +static int val_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp); +static int val_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap); +static int val_get_nc_type(bufferinfo *gbp, nc_type *typep); +static int val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp); +static int val_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp); +static int val_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap); +static int val_get_NC_var(bufferinfo *gbp, NC_var **varpp); +static int val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap); +static int val_get_NC(NC *ncp); + +static int val_fetch(bufferinfo *gbp, size_t fsize); +static int val_check_buffer(bufferinfo *gbp, size_t nextread); + +/* Begin Of get NC */ + +/* + * Fetch the next header chunk. + */ +static int +val_fetch(bufferinfo *gbp, size_t fsize) { + char *buf; + ssize_t nn = 0, bufsize = 0; + + assert(gbp->base != NULL); + + fsize = _RNDUP(fsize, X_ALIGN); + (void) memset(gbp->base, 0, gbp->size); + buf = gbp->pos = gbp->base; + + lseek(gbp->nciop->fd, gbp->offset, SEEK_SET); + while ( (bufsize < gbp->size) && (nn = read(gbp->nciop->fd, buf, gbp->size-bufsize)) > 0 ) { + buf += nn; + bufsize += nn; + } + gbp->offset += bufsize; + + if (bufsize < fsize) { + printf("Error @ [0x%8.8Lx]: \n\tUnexpected EOF, while ", + (long long unsigned) gbp->offset); + return -1; + } + + gbp->size = bufsize; + + return ENOERR; +} + +/* + * Ensure that 'nextread' bytes are available. + */ +static int +val_check_buffer(bufferinfo *gbp, size_t nextread) { + if ((char *)gbp->pos + nextread <= (char *)gbp->base + gbp->size) + return ENOERR; + return val_fetch(gbp, MIN(gbp->size, nextread)); +} + +static int +val_get_NCtype(bufferinfo *gbp, NCtype *typep) { + int type = 0; + int status = val_check_buffer(gbp, X_SIZEOF_INT); + if (status != ENOERR) { + printf("NC component type is expected for "); + return status; + } + + status = ncmpix_get_int_int(gbp->pos, &type); + gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); + if (status != ENOERR) + return status; + *typep = (NCtype) type; + return ENOERR; +} + +static int +val_get_size_t(bufferinfo *gbp, size_t *sp) { + int status = val_check_buffer(gbp, X_SIZEOF_SIZE_T); + if (status != ENOERR) { + printf("size is expected for "); + return status; + } + return ncmpix_get_size_t((const void **)(&gbp->pos), sp); +} + +static int +val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) { + int status; + size_t nchars = 0, padding, bufremain, strcount; + NC_string *ncstrp; + char *cpos; + char pad[X_ALIGN-1]; + + status = val_get_size_t(gbp, &nchars); + if (status != ENOERR) { + printf("the name string of "); + return status; + } + + ncstrp = ncmpii_new_NC_string(nchars, NULL); + if (ncstrp == NULL) + return NC_ENOMEM; + + padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN) + - X_SIZEOF_CHAR * ncstrp->nchars; + bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base); + cpos = ncstrp->cp; + + while (nchars > 0) { + if (bufremain > 0) { + strcount = MIN(bufremain, X_SIZEOF_CHAR * nchars); + (void) memcpy(cpos, gbp->pos, strcount); + nchars -= strcount/X_SIZEOF_CHAR; + gbp->pos = (void *)((char *)gbp->pos + strcount); + cpos += strcount; + bufremain -= strcount; + } else { + status = val_fetch(gbp, MIN(gbp->size, X_SIZEOF_CHAR * nchars)); + if(status != ENOERR) { + printf("fetching the name string of "); + ncmpii_free_NC_string(ncstrp); + return status; + } + bufremain = gbp->size; + } + } + + memset(pad, 0, X_ALIGN-1); + status = val_check_buffer(gbp, padding); + if(status != ENOERR) { + printf("fetching padding for the name string of "); + ncmpii_free_NC_string(ncstrp); + return status; + } + if (memcmp(gbp->pos, pad, padding) != 0) { + printf("Error @ [0x%8.8Lx]: \n\tPadding should be 0x00 for the name string alignment of ", (long long unsigned) + (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size)); + ncmpii_free_NC_string(ncstrp); + return EINVAL; + } + gbp->pos = (void *)((char *)gbp->pos + padding); + + *ncstrpp = ncstrp; + + return ENOERR; +} + +static int +val_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp) { + int status; + NC_string *ncstrp; + NC_dim *dimp; + + status = val_get_NC_string(gbp, &ncstrp); + if (status != ENOERR) + return status; + + dimp = ncmpii_new_x_NC_dim(ncstrp); + if(dimp == NULL) + return NC_ENOMEM; + + status = val_get_size_t(gbp, &dimp->size); + if(status != ENOERR) { + printf("\"%s\" - ", ncstrp->cp); + ncmpii_free_NC_dim(dimp); /* frees name */ + return status; + } + + *dimpp = dimp; + + return ENOERR; +} + +static int +val_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap) { + int status; + NCtype type = NC_UNSPECIFIED; + NC_dim **dpp, **end; + int dim; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = val_get_NCtype(gbp, &type); + if(status != ENOERR) { + printf("preamble of "); + return status; + } + + status = val_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) { + printf("the length of "); + return status; + } + + if(ncap->nelems == 0) { + if (type != NC_DIMENSION && type != NC_UNSPECIFIED) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_DIMENSION or NC_UNSPECIFIED is expected for "); + return EINVAL; + } + } else { + if(type != NC_DIMENSION) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_DIMENSION is expected since number of dimensions is %d for ", (int)ncap->nelems); + return EINVAL; + } + + ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + dpp = ncap->value; + end = &dpp[ncap->nelems]; + for( /*NADA*/ dim = 0; dpp < end; dpp++, dim++) { + status = val_get_NC_dim(gbp, dpp); + if (status != ENOERR) { + printf("dimension[%d] in ", dim); + ncap->nelems = dpp - ncap->value; + ncmpii_free_NC_dimarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +static int +val_get_nc_type(bufferinfo *gbp, nc_type *typep) { + int type = 0; + int status = val_check_buffer(gbp, X_SIZEOF_INT); + if(status != ENOERR) { + printf("data type is expected for the values of "); + return status; + } + + status = ncmpix_get_int_int(gbp->pos, &type); + if(status != ENOERR) + return status; + gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); + + if ( type != NC_BYTE + && type != NC_CHAR + && type != NC_SHORT + && type != NC_INT + && type != NC_FLOAT + && type != NC_DOUBLE) { + printf("Error @ [0x%8.8Lx]: \n\tUnknown data type for the values of ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - X_SIZEOF_INT)); + return EINVAL; + } + + *typep = (nc_type) type; + + return ENOERR; +} + +/* + * Get the values of an attribute + */ +static int +val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) { + int status; + void *value = attrp->xvalue; + char pad[X_ALIGN-1]; + size_t nvalues = attrp->nelems, esz, padding, bufremain, attcount; + + esz = ncmpix_len_nctype(attrp->type); + padding = attrp->xsz - esz * nvalues; + bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base); + + while (nvalues > 0) { + if (bufremain > 0) { + attcount = MIN(bufremain, esz * nvalues); + (void) memcpy(value, gbp->pos, attcount); + nvalues -= attcount/esz; + gbp->pos = (void *)((char *)gbp->pos + attcount); + value = (void *)((char *)value + attcount); + bufremain -= attcount; + } else { + status = val_fetch(gbp, MIN(gbp->size, esz * nvalues)); + if(status != ENOERR) { + printf("fetching the values of "); + return status; + } + bufremain = gbp->size; + } + } + + memset(pad, 0, X_ALIGN-1); + if (memcmp(gbp->pos, pad, padding) != 0) { + printf("Error @ [0x%8.8Lx]: \n\tPadding should be 0x00 for the values alignment of ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size)); + return EINVAL; + } + gbp->pos = (void *)((char *)gbp->pos + padding); + + return ENOERR; +} + +static int +val_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp) { + NC_string *strp; + int status; + nc_type type; + size_t nelems; + NC_attr *attrp; + + status = val_get_NC_string(gbp, &strp); + if(status != ENOERR) + return status; + + status = val_get_nc_type(gbp, &type); + if(status != ENOERR) { + printf("\"%s\" - ", strp->cp); + ncmpii_free_NC_string(strp); + return status; + } + + status = val_get_size_t(gbp, &nelems); + if(status != ENOERR) { + printf("the values of \"%s\" - ", strp->cp); + ncmpii_free_NC_string(strp); + return status; + } + + attrp = ncmpii_new_x_NC_attr(strp, type, nelems); + if(attrp == NULL) { + ncmpii_free_NC_string(strp); + return status; + } + + status = val_get_NC_attrV(gbp, attrp); + if(status != ENOERR) { + printf("\"%s\" - ", strp->cp); + ncmpii_free_NC_attr(attrp); /* frees strp */ + return status; + } + + *attrpp = attrp; + + return ENOERR; +} + +static int +val_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap){ + int status; + NCtype type = NC_UNSPECIFIED; + NC_attr **app, **end; + int att; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = val_get_NCtype(gbp, &type); + if(status != ENOERR) { + printf("preamble of "); + return status; + } + + status = val_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) { + printf("the length of "); + return status; + } + + if(ncap->nelems == 0) { + if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_ATTRIBUTE or NC_UNSPECIFIED is expected for "); + return EINVAL; + } + } else { + if(type != NC_ATTRIBUTE) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_ATTRIBUTE is expected since number of attributes is %d for ", (int)ncap->nelems); + return EINVAL; + } + + ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + app = ncap->value; + end = &app[ncap->nelems]; + for( /*NADA*/ att = 0; app < end; app++, att++) { + status = val_get_NC_attr(gbp, app); + if (status != ENOERR) { + printf("attribute[%d] of ", att); + ncap->nelems = app - ncap->value; + ncmpii_free_NC_attrarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +static int +val_get_NC_var(bufferinfo *gbp, NC_var **varpp) { + NC_string *strp; + int status; + size_t ndims, dim; + NC_var *varp; + + status = val_get_NC_string(gbp, &strp); + if(status != ENOERR) + return status; + + status = val_get_size_t(gbp, &ndims); + if(status != ENOERR) { + printf("the dimid list of \"%s\" - ", strp->cp); + ncmpii_free_NC_string(strp); + return status; + } + + varp = ncmpii_new_x_NC_var(strp, ndims); + if(varp == NULL) { + ncmpii_free_NC_string(strp); + return NC_ENOMEM; + } + + for (dim = 0; dim < ndims; dim++ ) { + status = val_check_buffer(gbp, X_SIZEOF_INT); + if(status != ENOERR) { + printf("the dimid[%d] is expected for \"%s\" - ", (int)dim, strp->cp); + ncmpii_free_NC_var(varp); + return status; + } + status = ncmpix_getn_int_int((const void **)(&gbp->pos), + 1, varp->dimids + dim); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + } + + status = val_get_NC_attrarray(gbp, &varp->attrs); + if(status != ENOERR) { + printf("ATTRIBUTE list of \"%s\" - ", strp->cp); + ncmpii_free_NC_var(varp); + return status; + } + + status = val_get_nc_type(gbp, &varp->type); + if(status != ENOERR) { + printf("\"%s\" - ", strp->cp); + ncmpii_free_NC_var(varp); + return status; + } + + status = val_get_size_t(gbp, &varp->len); + if(status != ENOERR) { + printf("the data of \"%s\" - ", strp->cp); + ncmpii_free_NC_var(varp); + return status; + } + + status = val_check_buffer(gbp, X_SIZEOF_OFF_T); + if(status != ENOERR) { + printf("offset is expected for the data of \"%s\" - ", strp->cp); + ncmpii_free_NC_var(varp); + return status; + } + status = ncmpix_get_off_t((const void **)&gbp->pos, + &varp->begin, (gbp->version == 1 ? 4 : 8)); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + + *varpp = varp; + return ENOERR; +} + +static int +val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap) { + int status; + NCtype type = NC_UNSPECIFIED; + NC_var **vpp, **end; + int var; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = val_get_NCtype(gbp, &type); + if(status != ENOERR) { + printf("preamble of "); + return status; + } + + status = val_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) { + printf("the length of "); + return status; + } + + if(ncap->nelems == 0) { + if (type != NC_VARIABLE && type != NC_UNSPECIFIED) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_VARIABLE or NC_UNSPECIFIED is expected for "); + return EINVAL; + } + } else { + if(type != NC_VARIABLE) { + printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ", + (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T)); + printf("NC_VARIABLE is expected since number of variables is %d for ", (int)ncap->nelems); + return EINVAL; + } + + ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + vpp = ncap->value; + end = &vpp[ncap->nelems]; + for( /*NADA*/ var = 0; vpp < end; vpp++, var++) { + status = val_get_NC_var(gbp, vpp); + if (status != ENOERR) { + printf("variable[%d] in ", var); + ncap->nelems = vpp - ncap->value; + ncmpii_free_NC_vararrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +static int +val_get_NC(NC *ncp) { + int status; + bufferinfo getbuf; + schar magic[sizeof(ncmagic)]; + size_t nrecs = 0; + + assert(ncp != NULL); + + /* Initialize the get buffer */ + + getbuf.nciop = ncp->nciop; + getbuf.offset = 0; /* read from start of the file */ + getbuf.size = _RNDUP( MAX(MIN_NC_XSZ, ncp->chunk), X_ALIGN ); + if (getbuf.size > 4096) + getbuf.size = 4096; + getbuf.pos = getbuf.base = (void *)malloc(getbuf.size); + + status = val_fetch(&getbuf, sizeof(magic)); + if(status != ENOERR) { + printf("magic number (C D F \\001) is expected!\n"); + return status; + } + + /* Get the header from get buffer */ + + (void) memset(magic, 0, sizeof(magic)); + status = ncmpix_getn_schar_schar( + (const void **)(&getbuf.pos), sizeof(magic), magic); + if(memcmp(magic, ncmagic, sizeof(ncmagic)) != 0) { + printf("Error @ [0x%8.8x]: \n\tUnknow magic number, while (C D F \\001) is expected!\n", (unsigned) 0); + free(getbuf.base); + return NC_ENOTNC; + } + + status = val_check_buffer(&getbuf, X_SIZEOF_SIZE_T); + if(status != ENOERR) { + printf("number of records is expected!\n"); + free(getbuf.base); + return status; + } + status = ncmpix_get_size_t((const void **)(&getbuf.pos), &nrecs); + if(status != ENOERR) { + free(getbuf.base); + return status; + } + ncp->numrecs = nrecs; + + assert((char *)getbuf.pos < (char *)getbuf.base + getbuf.size); + + status = val_get_NC_dimarray(&getbuf, &ncp->dims); + if(status != ENOERR) { + printf("DIMENSION list!\n"); + free(getbuf.base); + return status; + } + + status = val_get_NC_attrarray(&getbuf, &ncp->attrs); + if(status != ENOERR) { + printf("GLOBAL ATTRIBUTE list!\n"); + free(getbuf.base); + return status; + } + + status = val_get_NC_vararray(&getbuf, &ncp->vars); + if(status != ENOERR) { + printf("VARIABLE list!\n"); + free(getbuf.base); + return status; + } + + ncp->xsz = ncmpii_hdr_len_NC(ncp, (getbuf.version == 1 ? 4 : 8)); + status = ncmpii_NC_computeshapes(ncp); + free(getbuf.base); + + return status; +} + +/* End Of get NC */ + +int +main(int argc, char **argv) { + + char *ncfile; + int status; + NC *ncp; + struct stat ncfilestat; + + if (argc < 2) { + printf("Missing ncfile name. Usage:\n\t ncvalid \n"); + exit(1); + } + + if (argc > 2) { + printf("Too many arguments. Usage:\n\t ncvalid \n"); + exit(1); + } + + ncfile = argv[1]; + + /* open the netCDF file */ + + ncp = ncmpii_new_NC(NULL); + if(ncp == NULL) { + printf("Not enough memory!\n"); + return 0; + } + + ncp->nciop = ncmpiio_new(ncfile, NC_NOWRITE); + if(ncp->nciop == NULL) { + ncmpii_free_NC(ncp); + printf("Not enough memory!\n"); + return 0; + } + + if ( (*((int *)&ncp->nciop->fd) = open(ncfile, O_RDONLY)) < 0 ) { + printf("Can not open file: %s\n", ncfile); + ncmpiio_free(ncp->nciop); + ncmpii_free_NC(ncp); + return 0; + } + + /* read to validate the header */ + + status = val_get_NC(ncp); + if (status != 0) { + close(ncp->nciop->fd); + ncmpiio_free(ncp->nciop); + ncmpii_free_NC(ncp); + return 0; + } + + /* check data size */ + + fstat(ncp->nciop->fd, &ncfilestat); + if ( ncp->begin_rec + ncp->recsize * ncp->numrecs < ncfilestat.st_size ) { + printf("Error: \n\tData size is larger than defined!\n"); + close(ncp->nciop->fd); + ncmpiio_free(ncp->nciop); + ncmpii_free_NC(ncp); + return 0; + } else if ( ncp->begin_rec + ncp->recsize * (ncp->numrecs - 1) >= ncfilestat.st_size ) { + printf("Error: \n\tData size is less than expected!\n"); + close(ncp->nciop->fd); + ncmpiio_free(ncp->nciop); + ncmpii_free_NC(ncp); + return 0; + } + + + /* close the file */ + + close(ncp->nciop->fd); + ncmpiio_free(ncp->nciop); + ncmpii_free_NC(ncp); + + printf("The netCDF file is validated!\n"); + + return 0; +} Index: /tags/v1-0-3/src/lib/header.c =================================================================== --- /tags/v1-0-3/src/lib/header.c (revision 568) +++ /tags/v1-0-3/src/lib/header.c (revision 568) @@ -0,0 +1,1186 @@ +/*********************************************************************** + * + * This file is written by Northwestern University and Argonne National + * Laboratory + * + ***********************************************************************/ + +#include "nc.h" + +#include +#ifdef HAVE_MPIO_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include "ncx.h" + +#ifndef MAX +#define MAX(mm,nn) (((mm) > (nn)) ? (mm) : (nn)) +#endif +#ifndef MIN +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) +#endif + +/* Prototypes for functions used only in this file */ +static size_t hdr_len_NC_string(const NC_string *ncstrp); +static size_t hdr_len_NC_dim(const NC_dim *dimp); +static size_t hdr_len_NC_dimarray(const NC_dimarray *ncap); +static size_t hdr_len_NC_attr(const NC_attr *attrp); +static size_t hdr_len_NC_attrarray(const NC_attrarray *ncap); +static size_t hdr_len_NC_var(const NC_var *varp, size_t sizeof_off_t); +static size_t hdr_len_NC_vararray(const NC_vararray *ncap, size_t sizeof_off_t); +static int hdr_put_NCtype(bufferinfo *pbp, NCtype type); +static int hdr_put_nc_type(bufferinfo *pbp, const nc_type *typep); +static int hdr_put_NC_string(bufferinfo *pbp, const NC_string *ncstrp); +static int hdr_put_NC_attrV(bufferinfo *pbp, const NC_attr *attrp); +static int hdr_put_NC_dim(bufferinfo *pbp, const NC_dim *dimp); +static int hdr_put_NC_attr(bufferinfo *pbp, const NC_attr *attrp); +static int hdr_put_NC_var(bufferinfo *pbp, const NC_var *varp); +static int hdr_put_NC_dimarray(bufferinfo *pbp, const NC_dimarray *ncap); +static int hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap); +static int hdr_put_NC_vararray(bufferinfo *pbp, const NC_vararray *ncap); +static int hdr_fetch(bufferinfo *gbp); +static int hdr_check_buffer(bufferinfo *gbp, size_t nextread); +static int hdr_get_NCtype(bufferinfo *gbp, NCtype *typep); +static int hdr_get_size_t(bufferinfo *gbp, size_t *sp); +static int hdr_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp); +static int hdr_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp); +static int hdr_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap); +static int hdr_get_nc_type(bufferinfo *gbp, nc_type *typep); +static int hdr_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp); +static int hdr_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp); +static int hdr_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap); +static int hdr_get_NC_var(bufferinfo *gbp, NC_var **varpp); +static int hdr_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap); + +/* + * "magic number" at beginning of file: 0x43444601 (big endian) + */ +static const schar ncmagic[] = {'C', 'D', 'F', 0x02}; +static const schar ncmagic1[] = {'C', 'D', 'F', 0x01}; + +/* + * Recompute the shapes of all variables + * Sets ncp->begin_var to start of first variable. + * Sets ncp->begin_rec to start of first record variable. + * Returns -1 on error. The only possible error is an reference + * to a non existent dimension, which would occur for a corrupt + * netcdf file. + */ +int +ncmpii_NC_computeshapes(NC *ncp) +{ + NC_var **vpp = (NC_var **)ncp->vars.value; + NC_var *const *const end = &vpp[ncp->vars.nelems]; + NC_var *first_var = NULL; /* first "non-record" var */ + NC_var *first_rec = NULL; /* first "record" var */ + int status; + + ncp->begin_var = (off_t) ncp->xsz; + ncp->begin_rec = (off_t) ncp->xsz; + ncp->recsize = 0; + + if(ncp->vars.nelems == 0) + return(0); + + for( /*NADA*/; vpp < end; vpp++) + { + status = ncmpii_NC_var_shape(*vpp, &ncp->dims); + if(status != ENOERR) + return(status); + + if(IS_RECVAR(*vpp)) + { + if(first_rec == NULL) + first_rec = *vpp; + ncp->recsize += (*vpp)->len; + } + else if(first_var == NULL) + { + first_var = *vpp; + /* + * Overwritten each time thru. + * Usually overwritten in first_rec != NULL clause. + */ + ncp->begin_rec = (*vpp)->begin + (off_t)(*vpp)->len; + } + } + + if(first_rec != NULL) + { + assert(ncp->begin_rec <= first_rec->begin); + ncp->begin_rec = first_rec->begin; + /* + * for special case of exactly one record variable, pack value + */ + if(ncp->recsize == first_rec->len) + ncp->recsize = *first_rec->dsizes * first_rec->xsz; + } + + if(first_var != NULL) + { + ncp->begin_var = first_var->begin; + } + else + { + ncp->begin_var = ncp->begin_rec; + } + + assert(ncp->begin_var > 0); + assert(ncp->xsz <= ncp->begin_var); + assert(ncp->begin_rec > 0); + assert(ncp->begin_var <= ncp->begin_rec); + + return(ENOERR); +} + +/* + * To compute how much space will the xdr'd header take + */ + +#define X_SIZEOF_NC_TYPE X_SIZEOF_INT +#define X_SIZEOF_NCTYPE X_SIZEOF_INT + +static size_t +hdr_len_NC_string(const NC_string *ncstrp) +{ + size_t sz = X_SIZEOF_SIZE_T; /* nchars */ + + assert(ncstrp != NULL); + + if(ncstrp->nchars != 0) + sz += _RNDUP(ncstrp->nchars, X_ALIGN); + + return sz; +} + +static size_t +hdr_len_NC_dim(const NC_dim *dimp) +{ + size_t sz; + + assert(dimp != NULL); + + sz = hdr_len_NC_string(dimp->name); + sz += X_SIZEOF_SIZE_T; + + return(sz); +} + +static size_t +hdr_len_NC_dimarray(const NC_dimarray *ncap) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_dim **dpp = (const NC_dim **)ncap->value; + const NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + xlen += hdr_len_NC_dim(*dpp); + } + } + return xlen; +} + +static size_t +hdr_len_NC_attr(const NC_attr *attrp) +{ + size_t sz; + + assert(attrp != NULL); + + sz = hdr_len_NC_string(attrp->name); + sz += X_SIZEOF_NC_TYPE; /* type */ + sz += X_SIZEOF_SIZE_T; /* nelems */ + sz += attrp->xsz; + + return(sz); +} + +static size_t +hdr_len_NC_attrarray(const NC_attrarray *ncap) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_attr **app = (const NC_attr **)ncap->value; + const NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + xlen += hdr_len_NC_attr(*app); + } + } + return xlen; +} + +static size_t +hdr_len_NC_var(const NC_var *varp, size_t sizeof_off_t) +{ + size_t sz; + + assert(varp != NULL); + assert(sizeof_off_t == 4 || sizeof_off_t == 8); + + sz = hdr_len_NC_string(varp->name); + sz += X_SIZEOF_SIZE_T; /* ndims */ + sz += ncmpix_len_int(varp->ndims); /* dimids */ + sz += hdr_len_NC_attrarray(&varp->attrs); + sz += X_SIZEOF_NC_TYPE; /* type */ + sz += X_SIZEOF_SIZE_T; /* len */ + sz += sizeof_off_t; /* begin */ + + return(sz); +} + +static size_t +hdr_len_NC_vararray(const NC_vararray *ncap, size_t sizeof_off_t) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_var **vpp = (const NC_var **)ncap->value; + const NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + xlen += hdr_len_NC_var(*vpp, sizeof_off_t); + } + } + return xlen; +} + +size_t +ncmpii_hdr_len_NC(const NC *ncp, size_t sizeof_off_t) +{ + size_t xlen = sizeof(ncmagic); + + assert(ncp != NULL); + + xlen += X_SIZEOF_SIZE_T; /* numrecs */ + xlen += hdr_len_NC_dimarray(&ncp->dims); + xlen += hdr_len_NC_attrarray(&ncp->attrs); + xlen += hdr_len_NC_vararray(&ncp->vars, sizeof_off_t); + + return xlen; +} + +/* Begin Of put NC */ + +static int +hdr_put_NCtype(bufferinfo *pbp, NCtype type) { + int status; + const int itype = (int)type; + + status = ncmpix_put_int_int(pbp->pos, &itype); + if (status != ENOERR) + return status; + pbp->pos = (void *)((char *)pbp->pos + X_SIZEOF_INT); + return status; +} + +static int +hdr_put_nc_type(bufferinfo *pbp, const nc_type *typep) { + int status; + const int itype = (int) *typep; + + status = ncmpix_put_int_int(pbp->pos, &itype); + if (status != ENOERR) + return status; + pbp->pos = (void *)((char *)pbp->pos + X_SIZEOF_INT); + + return status; +} + +static int +hdr_put_NC_string(bufferinfo *pbp, const NC_string *ncstrp) { + int status; + + status = ncmpix_put_size_t(&pbp->pos, &ncstrp->nchars); + if (status != ENOERR) + return status; + + status = ncmpix_pad_putn_text(&pbp->pos, ncstrp->nchars, ncstrp->cp); + if (status != ENOERR) + return status; + + return ENOERR; +} + +/* + * Put the values of an attribute + */ +static int +hdr_put_NC_attrV(bufferinfo *pbp, const NC_attr *attrp) { + void *value = attrp->xvalue; + size_t padding, esz; + + esz = ncmpix_len_nctype(attrp->type); + padding = attrp->xsz - esz * attrp->nelems; + + (void) memcpy(pbp->pos, value, esz * attrp->nelems); + pbp->pos = (void *)((char *)pbp->pos + esz * attrp->nelems); + (void) memset(pbp->pos, 0, padding); + pbp->pos = (void *)((char *)pbp->pos + padding); + + return ENOERR; +} + +static int +hdr_put_NC_dim(bufferinfo *pbp, const NC_dim *dimp) { + int status; + + status = hdr_put_NC_string(pbp, dimp->name); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &dimp->size); + if (status != ENOERR) + return status; + + return ENOERR; +} + +static int +hdr_put_NC_attr(bufferinfo *pbp, const NC_attr *attrp) { + int status; + + status = hdr_put_NC_string(pbp, attrp->name); + if (status != ENOERR) + return status; + + status = hdr_put_nc_type(pbp, &attrp->type); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &attrp->nelems); + if (status != ENOERR) + return status; + + status = hdr_put_NC_attrV(pbp, attrp); + if (status != ENOERR) + return status; + + return ENOERR; +} + +static int +hdr_put_NC_var(bufferinfo *pbp, const NC_var *varp) { + int status; + + status = hdr_put_NC_string(pbp, varp->name); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &varp->ndims); + if (status != ENOERR) + return status; + + status = ncmpix_putn_int_int(&pbp->pos, + varp->ndims, varp->dimids); + if (status != ENOERR) + return status; + + status = hdr_put_NC_attrarray(pbp, &varp->attrs); + if (status != ENOERR) + return status; + + status = hdr_put_nc_type(pbp, &varp->type); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &varp->len); + if (status != ENOERR) + return status; + + status = ncmpix_put_off_t(&pbp->pos, &varp->begin, pbp->version == 1 ? 4 : 8); + if (status != ENOERR) + return status; + + return ENOERR; +} + +static int +hdr_put_NC_dimarray(bufferinfo *pbp, const NC_dimarray *ncap) { + int status; + + assert(pbp != NULL); + + if (ncap == NULL || ncap->nelems == 0) { + /* ABSENT */ + const size_t nosz = 0; + status = hdr_put_NCtype(pbp, NC_UNSPECIFIED); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &nosz); + if (status != ENOERR) + return status; + } else { + const NC_dim **dpp = (const NC_dim **)ncap->value; + const NC_dim *const *const end = &dpp[ncap->nelems]; + + status = hdr_put_NCtype(pbp, NC_DIMENSION); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &ncap->nelems); + if (status != ENOERR) + return status; + + for ( /*NADA*/; dpp < end; dpp++) { + status = hdr_put_NC_dim(pbp, *dpp); + if (status != ENOERR) + return status; + } + } + + return ENOERR; +} + +static int +hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap) { + int status; + + assert(pbp != NULL); + + if (ncap == NULL || ncap->nelems == 0) { + /* ABSENT */ + const size_t nosz = 0; + status = hdr_put_NCtype(pbp, NC_UNSPECIFIED); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &nosz); + if (status != ENOERR) + return status; + } else { + const NC_attr **app = (const NC_attr **)ncap->value; + const NC_attr *const *const end = &app[ncap->nelems]; + + status = hdr_put_NCtype(pbp, NC_ATTRIBUTE); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &ncap->nelems); + if (status != ENOERR) + return status; + + for ( /*NADA*/; app < end; app++) { + status = hdr_put_NC_attr(pbp, *app); + if (status != ENOERR) + return status; + } + } + + return ENOERR; +} + +static int +hdr_put_NC_vararray(bufferinfo *pbp, const NC_vararray *ncap){ + int status; + + assert(pbp != NULL); + + if (ncap == NULL || ncap->nelems == 0) { + /* ABSENT */ + const size_t nosz = 0; + status = hdr_put_NCtype(pbp, NC_UNSPECIFIED); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &nosz); + if (status != ENOERR) + return status; + } else { + const NC_var **vpp = (const NC_var **)ncap->value; + const NC_var *const *const end = &vpp[ncap->nelems]; + + status = hdr_put_NCtype(pbp, NC_VARIABLE); + if (status != ENOERR) + return status; + + status = ncmpix_put_size_t(&pbp->pos, &ncap->nelems); + if (status != ENOERR) + return status; + + for( /*NADA*/; vpp < end; vpp++) { + status = hdr_put_NC_var(pbp, *vpp); + if (status != ENOERR) + return status; + } + } + + return ENOERR; +} + +int +ncmpii_hdr_put_NC(NC *ncp, void *buf) { + int status; + bufferinfo putbuf; + size_t nrecs; + + putbuf.nciop = NULL; + putbuf.offset = 0; + putbuf.pos = putbuf.base = buf; + putbuf.size = ncp->xsz; + + if (ncp->flags & NC_64BIT_OFFSET) + putbuf.version = 2; + else + putbuf.version = 1; + + if (putbuf.version == 2) + status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic), ncmagic); + else + status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic1), ncmagic1); + + if (status != ENOERR) + return status; + + nrecs = ncp->numrecs; + status = ncmpix_put_size_t(&putbuf.pos, &nrecs); + if (status != ENOERR) + return status; + + assert((char *)putbuf.pos < (char *)putbuf.base + putbuf.size); + + status = hdr_put_NC_dimarray(&putbuf, &ncp->dims); + if (status != ENOERR) + return status; + + status = hdr_put_NC_attrarray(&putbuf, &ncp->attrs); + if (status != ENOERR) + return status; + + status = hdr_put_NC_vararray(&putbuf, &ncp->vars); + if (status != ENOERR) + return status; + + return status; +} + +/* End Of put NC */ + +/* Begin Of get NC */ + +/* + * Fetch the next header chunk. the chunk is 'gbp->size' bytes big + * Takes care to not overwrite leftover (unused) data in the buffer before + * fetching a new chunk: the current aproach is to re-read the extra data. + * + * NOTE: An alternate approach (which we do not do) would be to save the old + * data, read the next chunk and then copy the old data into the new + * chunk. This alternate aproach might help if it is important for reads + * to be aligned. + */ +static int +hdr_fetch(bufferinfo *gbp) { + int rank; + MPI_Comm comm; + int mpireturn; + size_t slack; /* any leftover data in the buffer */ + + assert(gbp->base != NULL); + + comm = gbp->nciop->comm; + MPI_Comm_rank(comm, &rank); + + /* XXX: this pointer math might not be good on 64 bit platforms */ + slack = gbp->size - ((char *)gbp->pos - (char *)gbp->base); + /* . if gbp->pos and gbp->base are the same, there is no leftover buffer data + * to worry about. + * In the other extreme, where gbp->size == (gbp->pos - gbp->base), then all + * data in the buffer has been consumed */ + + if (slack == gbp->size) slack = 0; + + (void) memset(gbp->base, 0, gbp->size); + gbp->pos = gbp->base; + gbp->index = 0; + mpireturn = MPI_File_set_view(gbp->nciop->collective_fh, 0, MPI_BYTE, MPI_BYTE, + "native", gbp->nciop->mpiinfo); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_set_view"); + MPI_Finalize(); + return NC_EREAD; + } + + if (rank == 0) { + MPI_Status mpistatus; + mpireturn = MPI_File_read_at(gbp->nciop->collective_fh, (gbp->offset)-slack, gbp->base, + gbp->size, MPI_BYTE, &mpistatus); + if (mpireturn != MPI_SUCCESS) { + ncmpii_handle_error(rank, mpireturn, "MPI_File_read_at"); + MPI_Finalize(); + return NC_EREAD; + } + + } + /* we might have had to backtrack */ + gbp->offset += (gbp->size - slack); + + MPI_Bcast(gbp->base, gbp->size, MPI_BYTE, 0, comm); + + return ENOERR; +} + +/* + * Ensure that 'nextread' bytes are available. + */ +static int +hdr_check_buffer(bufferinfo *gbp, size_t nextread) { + if ((char *)gbp->pos + nextread <= (char *)gbp->base + gbp->size) + return ENOERR; + return hdr_fetch(gbp); +} + +static int +hdr_get_NCtype(bufferinfo *gbp, NCtype *typep) { + int type = 0; + int status = hdr_check_buffer(gbp, X_SIZEOF_INT); + if (status != ENOERR) + return status; + + status = ncmpix_get_int_int(gbp->pos, &type); + gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); + gbp->index += X_SIZEOF_INT; + if (status != ENOERR) + return status; + *typep = (NCtype) type; + return ENOERR; +} + +static int +hdr_get_size_t(bufferinfo *gbp, size_t *sp) { + int status = hdr_check_buffer(gbp, X_SIZEOF_SIZE_T); + if (status != ENOERR) + return status; + gbp->index += X_SIZEOF_SIZE_T; + return ncmpix_get_size_t((const void **)(&gbp->pos), sp); +} + +static int +hdr_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) { + int status; + size_t nchars = 0, nbytes, padding, bufremain, strcount; + NC_string *ncstrp; + char *cpos; + char pad[X_ALIGN-1]; + + status = hdr_get_size_t(gbp, &nchars); + if (status != ENOERR) + return status; + + ncstrp = ncmpii_new_NC_string(nchars, NULL); + + if (ncstrp == NULL) + return NC_ENOMEM; + + nbytes = nchars * X_SIZEOF_CHAR; + padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN) + - X_SIZEOF_CHAR * ncstrp->nchars; + bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base); + cpos = ncstrp->cp; + + while (nbytes > 0) { + if (bufremain > 0) { + strcount = MIN(bufremain, nbytes); + (void) memcpy(cpos, gbp->pos, strcount); + nbytes -= strcount; + gbp->pos = (void *)((char *)gbp->pos + strcount); + gbp->index += strcount; + cpos += strcount; + bufremain -= strcount; + } else { + status = hdr_fetch(gbp); + if(status != ENOERR) { + ncmpii_free_NC_string(ncstrp); + return status; + } + bufremain = gbp->size; + } + } + + if (padding > 0) { + (void) memset(pad, 0, X_ALIGN-1); + if (memcmp(gbp->pos, pad, padding) != 0) { + ncmpii_free_NC_string(ncstrp); + return EINVAL; + } + gbp->pos = (void *)((char *)gbp->pos + padding); + gbp->index += padding; + } + + *ncstrpp = ncstrp; + + return ENOERR; +} + +static int +hdr_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp) { + int status; + NC_string *ncstrp; + NC_dim *dimp; + + status = hdr_get_NC_string(gbp, &ncstrp); + if (status != ENOERR) + return status; + + dimp = ncmpii_new_x_NC_dim(ncstrp); + if(dimp == NULL) + return NC_ENOMEM; + + status = hdr_get_size_t(gbp, &dimp->size); + if(status != ENOERR) { + ncmpii_free_NC_dim(dimp); /* frees name */ + return status; + } + + *dimpp = dimp; + + return ENOERR; +} + +static int +hdr_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap) { + int status; + NCtype type = NC_UNSPECIFIED; + NC_dim **dpp, **end; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = hdr_get_NCtype(gbp, &type); + if(status != ENOERR) + return status; + + status = hdr_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) { + if (type != NC_DIMENSION && type != NC_UNSPECIFIED) + return EINVAL; + } else { + if(type != NC_DIMENSION) + return EINVAL; + + ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + dpp = ncap->value; + end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) { + status = hdr_get_NC_dim(gbp, dpp); + if (status != ENOERR) { + ncap->nelems = dpp - ncap->value; + ncmpii_free_NC_dimarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +static int +hdr_get_nc_type(bufferinfo *gbp, nc_type *typep) { + int type = 0; + int status = hdr_check_buffer(gbp, X_SIZEOF_INT); + if(status != ENOERR) + return status; + + status = ncmpix_get_int_int(gbp->pos, &type); + gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); + gbp->index += X_SIZEOF_INT; + if(status != ENOERR) + return status; + + if ( type != NC_BYTE + && type != NC_CHAR + && type != NC_SHORT + && type != NC_INT + && type != NC_FLOAT + && type != NC_DOUBLE) + return EINVAL; + + *typep = (nc_type) type; + + return ENOERR; +} + +size_t +ncmpix_len_nctype(nc_type type) { + switch(type) { + case NC_BYTE: + case NC_CHAR: + return X_SIZEOF_CHAR; + case NC_SHORT: + return X_SIZEOF_SHORT; + case NC_INT: + return X_SIZEOF_INT; + case NC_FLOAT: + return X_SIZEOF_FLOAT; + case NC_DOUBLE: + return X_SIZEOF_DOUBLE; + default: + assert("ncmpix_len_nctype bad type" == 0); + } + return 0; +} + +/* + * Get the values of an attribute + */ +static int +hdr_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) { + int status; + void *value = attrp->xvalue; + char pad[X_ALIGN-1]; + size_t nbytes, esz, padding, bufremain, attcount; + + esz = ncmpix_len_nctype(attrp->type); + padding = attrp->xsz - esz * attrp->nelems; + bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base); + nbytes = esz * attrp->nelems; + + while (nbytes > 0) { + if (bufremain > 0) { + attcount = MIN(bufremain, nbytes); + (void) memcpy(value, gbp->pos, attcount); + nbytes -= attcount; + gbp->pos = (void *)((char *)gbp->pos + attcount); + gbp->index += attcount; + value = (void *)((char *)value + attcount); + bufremain -= attcount; + } else { + status = hdr_fetch(gbp); + if(status != ENOERR) + return status; + bufremain = gbp->size; + } + } + + if (padding > 0) { + (void) memset(pad, 0, X_ALIGN-1); + if (memcmp(gbp->pos, pad, padding) != 0) + return EINVAL; + gbp->pos = (void *)((char *)gbp->pos + padding); + gbp->index += padding; + } + + return ENOERR; +} + +static int +hdr_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp) { + NC_string *strp; + int status; + nc_type type; + size_t nelems; + NC_attr *attrp; + + status = hdr_get_NC_string(gbp, &strp); + if(status != ENOERR) + return status; + + status = hdr_get_nc_type(gbp, &type); + if(status != ENOERR) { + ncmpii_free_NC_string(strp); + return status; + } + + status = hdr_get_size_t(gbp, &nelems); + if(status != ENOERR) { + ncmpii_free_NC_string(strp); + return status; + } + + attrp = ncmpii_new_x_NC_attr(strp, type, nelems); + if(attrp == NULL) { + ncmpii_free_NC_string(strp); + return status; + } + + status = hdr_get_NC_attrV(gbp, attrp); + if(status != ENOERR) { + ncmpii_free_NC_attr(attrp); /* frees strp */ + return status; + } + + *attrpp = attrp; + + return ENOERR; +} + +static int +hdr_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap){ + int status; + NCtype type = NC_UNSPECIFIED; + NC_attr **app, **end; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = hdr_get_NCtype(gbp, &type); + if(status != ENOERR) + return status; + + status = hdr_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) { + if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED) + return EINVAL; + } else { + if(type != NC_ATTRIBUTE) + return EINVAL; + + ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + app = ncap->value; + end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) { + status = hdr_get_NC_attr(gbp, app); + if (status != ENOERR) { + ncap->nelems = app - ncap->value; + ncmpii_free_NC_attrarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +static int +hdr_get_NC_var(bufferinfo *gbp, NC_var **varpp) { + NC_string *strp; + int status; + size_t ndims, dim; + NC_var *varp; + + status = hdr_get_NC_string(gbp, &strp); + if(status != ENOERR) + return status; + + status = hdr_get_size_t(gbp, &ndims); + if(status != ENOERR) { + ncmpii_free_NC_string(strp); + return status; + } + + varp = ncmpii_new_x_NC_var(strp, ndims); + if(varp == NULL) { + ncmpii_free_NC_string(strp); + return NC_ENOMEM; + } + + for (dim = 0; dim < ndims; dim++ ) { + status = hdr_check_buffer(gbp, X_SIZEOF_INT); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + status = ncmpix_getn_int_int((const void **)(&gbp->pos), + 1, varp->dimids + dim); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + } + + status = hdr_get_NC_attrarray(gbp, &varp->attrs); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + + status = hdr_get_nc_type(gbp, &varp->type); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + + status = hdr_get_size_t(gbp, &varp->len); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + + status = hdr_check_buffer(gbp, (gbp->version == 1 ? 4 : 8)); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + status = ncmpix_get_off_t((const void **)&gbp->pos, + &varp->begin, (gbp->version == 1 ? 4 : 8)); + if(status != ENOERR) { + ncmpii_free_NC_var(varp); + return status; + } + + *varpp = varp; + return ENOERR; +} + +static int +hdr_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap) { + int status; + NCtype type = NC_UNSPECIFIED; + NC_var **vpp, **end; + + assert(gbp != NULL && gbp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = hdr_get_NCtype(gbp, &type); + if(status != ENOERR) + return status; + + status = hdr_get_size_t(gbp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) { + if (type != NC_VARIABLE && type != NC_UNSPECIFIED) + return EINVAL; + } else { + if(type != NC_VARIABLE) + return EINVAL; + + ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + vpp = ncap->value; + end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) { + status = hdr_get_NC_var(gbp, vpp); + if (status != ENOERR) { + ncap->nelems = vpp - ncap->value; + ncmpii_free_NC_vararrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +int +ncmpii_hdr_get_NC(NC *ncp) { + int status; + bufferinfo getbuf; + schar magic[sizeof(ncmagic)]; + size_t nrecs = 0; + + assert(ncp != NULL); + + /* Initialize the get buffer */ + + getbuf.nciop = ncp->nciop; + getbuf.offset = 0; /* read from start of the file */ + getbuf.size = _RNDUP( MAX(MIN_NC_XSZ, ncp->chunk), X_ALIGN ); + if (getbuf.size > 4096) + getbuf.size = 4096; + + getbuf.pos = getbuf.base = (void *)malloc(getbuf.size); + getbuf.index = 0; + + status = hdr_fetch(&getbuf); + + /* Get the header from get buffer */ + + (void) memset(magic, 0, sizeof(magic)); + status = ncmpix_getn_schar_schar( + (const void **)(&getbuf.pos), sizeof(magic), magic); + getbuf.index += sizeof(magic); + /* don't need to worry about CDF-1 or CDF-2 + * if the first bits are not 'CDF-' */ + if(memcmp(magic, ncmagic, sizeof(ncmagic)-1) != 0) { + free(getbuf.base); + return NC_ENOTNC; + } + /* check version number in last byte of magic */ + if (magic[sizeof(ncmagic)-1] == 0x1) { + getbuf.version = 1; + } else if (magic[sizeof(ncmagic)-1] == 0x2) { + getbuf.version = 2; + fSet(ncp->flags, NC_64BIT_OFFSET); + if (sizeof(MPI_Offset) != 8) { + /* take the easy way out: if we can't support all CDF-2 + * files, return immediately */ + free(getbuf.base); + return NC_ESMALL; + } + } else { + free(getbuf.base); + return NC_ENOTNC; + } + + status = hdr_check_buffer(&getbuf, (getbuf.version == 1) ? 4 : 8); + if(status != ENOERR) { + free(getbuf.base); + return status; + } + status = ncmpix_get_size_t((const void **)(&getbuf.pos), &nrecs); + getbuf.index += X_SIZEOF_SIZE_T; + if(status != ENOERR) { + free(getbuf.base); + return status; + } + ncp->numrecs = nrecs; + + assert((char *)getbuf.pos < (char *)getbuf.base + getbuf.size); + + status = hdr_get_NC_dimarray(&getbuf, &ncp->dims); + if(status != ENOERR) { + free(getbuf.base); + return status; + } + + status = hdr_get_NC_attrarray(&getbuf, &ncp->attrs); + if(status != ENOERR) { + free(getbuf.base); + return status; + } + + status = hdr_get_NC_vararray(&getbuf, &ncp->vars); + if(status != ENOERR) { + free(getbuf.base); + return status; + } + + ncp->xsz = ncmpii_hdr_len_NC(ncp, (getbuf.version == 1) ? 4 : 8 ); + status = ncmpii_NC_computeshapes(ncp); + free(getbuf.base); + + return status; +} + +/* End Of get NC */ Index: /tags/v1-0-3/src/lib/ncx.c =================================================================== --- /tags/v1-0-3/src/lib/ncx.c (revision 566) +++ /tags/v1-0-3/src/lib/ncx.c (revision 566) @@ -0,0 +1,3814 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * + * This file contains some routines derived from code + * which is copyrighted by Sun Microsystems, Inc. + * The "#ifdef vax" versions of + * ncmpix_put_float_float() + * ncmpix_get_float_float() + * ncmpix_put_double_double() + * ncmpix_get_double_double() + * ncmpix_putn_float_float() + * ncmpix_getn_float_float() + * ncmpix_putn_double_double() + * ncmpix_getn_double_double() + * are derived from xdr_float() and xdr_double() routines + * in the freely available, copyrighted Sun RPCSRC 3.9 + * distribution, xdr_float.c. + * Our "value added" is that these are always memory to memory, + * they handle IEEE subnormals properly, and their "n" versions + * operate speedily on arrays. + */ +/* $Id$ */ + +/* + * An external data representation interface. + */ + +#include "ncx.h" +#include +#include +/* alias poorly named limits.h macros */ +#define SHORT_MAX SHRT_MAX +#define SHORT_MIN SHRT_MIN +#define USHORT_MAX USHRT_MAX +#include +#ifndef FLT_MAX /* This POSIX macro missing on some systems */ +# ifndef NO_IEEE_FLOAT +# define FLT_MAX 3.40282347e+38f +# else +# error "You will need to define FLT_MAX" +# endif +#endif +#include + +/* + * If the machine's float domain is "smaller" than the external one + * use the machine domain + */ +#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 /* 128 is X_FLT_MAX_EXP */ +#undef X_FLOAT_MAX +# define X_FLOAT_MAX FLT_MAX +#undef X_FLOAT_MIN +# define X_FLOAT_MIN (-X_FLOAT_MAX) +#endif + +#if defined(_SX) && _SX != 0 /* NEC SUPER UX */ +#if _INT64 +#undef INT_MAX /* workaround cpp bug */ +#define INT_MAX X_INT_MAX +#undef INT_MIN /* workaround cpp bug */ +#define INT_MIN X_INT_MIN +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX X_INT_MAX +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN X_INT_MIN +#elif _LONG64 +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX 4294967295L +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN -4294967295L +#endif +#endif /* _SX */ + +static const char nada[X_ALIGN] = {0, 0, 0, 0}; + +#ifndef WORDS_BIGENDIAN +/* LITTLE_ENDIAN: DEC and intel */ +/* + * Routines to convert to BIGENDIAN. + * Optimize the swapn?b() and swap?b() routines aggressivly. + */ + +#define SWAP2(a) ( (((a) & 0xff) << 8) | \ + (((a) >> 8) & 0xff) ) + +#define SWAP4(a) ( ((a) << 24) | \ + (((a) << 8) & 0x00ff0000) | \ + (((a) >> 8) & 0x0000ff00) | \ + (((a) >> 24) & 0x000000ff) ) + +/* netcdf-3.6.2beta5 added loop unrolling to many of these routines. Could + * confer a 22% performance increase on little endian platforms if compiler + * does not already aggressively unroll loops */ + +static void +swapn2b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + + while(nn > 3) + { + *op++ = *(++ip); + *op++ = *(ip++ -1); + *op++ = *(++ip); + *op++ = *(ip++ -1); + *op++ = *(++ip); + *op++ = *(ip++ -1); + *op++ = *(++ip); + *op++ = *(ip++ -1); + nn -= 4; + } + while(nn-- != 0) + { + *op++ = *(++ip); + *op++ = *(ip++ -1); + } +} + +# ifndef vax +static void +swap4b(void *dst, const void *src) +{ + char *op = dst; + const char *ip = src; + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; +} +# endif /* !vax */ + +static void +swapn4b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + + while(nn > 3) + { + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; + op[4] = ip[7]; + op[5] = ip[6]; + op[6] = ip[5]; + op[7] = ip[4]; + op[8] = ip[11]; + op[9] = ip[10]; + op[10] = ip[9]; + op[11] = ip[8]; + op[12] = ip[15]; + op[13] = ip[14]; + op[14] = ip[13]; + op[15] = ip[12]; + op += 16; + ip += 16; + nn -= 4; + } + while(nn-- != 0) + { + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; + op += 4; + ip += 4; + } +} + +# ifndef vax +static void +swap8b(void *dst, const void *src) +{ + char *op = dst; + const char *ip = src; + op[0] = ip[7]; + op[1] = ip[6]; + op[2] = ip[5]; + op[3] = ip[4]; + op[4] = ip[3]; + op[5] = ip[2]; + op[6] = ip[1]; + op[7] = ip[0]; +} +# endif /* !vax */ + +# ifndef vax +static void +swapn8b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + + while(nn > 1) + { + op[0] = ip[7]; + op[1] = ip[6]; + op[2] = ip[5]; + op[3] = ip[4]; + op[4] = ip[3]; + op[5] = ip[2]; + op[6] = ip[1]; + op[7] = ip[0]; + op[8] = ip[15]; + op[9] = ip[14]; + op[10] = ip[13]; + op[11] = ip[12]; + op[12] = ip[11]; + op[13] = ip[10]; + op[14] = ip[9]; + op[15] = ip[8]; + op += 16; + ip += 16; + nn -= 2; + } + while(nn-- != 0) + { + op[0] = ip[7]; + op[1] = ip[6]; + op[2] = ip[5]; + op[3] = ip[4]; + op[4] = ip[3]; + op[5] = ip[2]; + op[6] = ip[1]; + op[7] = ip[0]; + op += 8; + ip += 8; + } +} +# endif /* !vax */ + +#endif /* LITTLE_ENDIAN */ + + +/* + * Primitive numeric conversion functions. + */ + +/* x_schar */ + + /* We don't implement and x_schar primitives. */ + + +/* x_short */ + +#if SHORT_MAX == X_SHORT_MAX +typedef short ix_short; +#define SIZEOF_IX_SHORT SIZEOF_SHORT +#define IX_SHORT_MAX SHORT_MAX +#elif INT_MAX >= X_SHORT_MAX +typedef int ix_short; +#define SIZEOF_IX_SHORT SIZEOF_INT +#define IX_SHORT_MAX INT_MAX +#elif LONG_MAX >= X_SHORT_MAX +typedef long ix_short; +#define SIZEOF_IX_SHORT SIZEOF_LONG +#define IX_SHORT_MAX LONG_MAX +#else +#error "ix_short implementation" +#endif + +static void +get_ix_short(const void *xp, ix_short *ip) +{ + const uchar *cp = (const uchar *) xp; + *ip = *cp++ << 8; +#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT + if(*ip & 0x8000) + { + /* extern is negative */ + *ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */ + } +#endif + *ip |= *cp; +} + +static void +put_ix_short(void *xp, const ix_short *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = (*ip) >> 8; + *cp = (*ip) & 0xff; +} + + +int +ncmpix_get_short_schar(const void *xp, schar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_short_uchar(const void *xp, uchar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_short_short(const void *xp, short *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_SHORT && IX_SHORT_MAX == SHORT_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +# if IX_SHORT_MAX > SHORT_MAX + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_get_short_int(const void *xp, int *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_INT && IX_SHORT_MAX == INT_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +# if IX_SHORT_MAX > INT_MAX + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_get_short_long(const void *xp, long *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_LONG && IX_SHORT_MAX == LONG_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + /* assert(LONG_MAX >= X_SHORT_MAX); */ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +#endif +} + +int +ncmpix_get_short_float(const void *xp, float *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +#if 0 /* TODO: determine when necessary */ + if(xx > FLT_MAX || xx < (-FLT_MAX)) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_get_short_double(const void *xp, double *ip) +{ + /* assert(DBL_MAX >= X_SHORT_MAX); */ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncmpix_put_short_schar(void *xp, const schar *ip) +{ + uchar *cp = (uchar *) xp; + if(*ip & 0x80) + *cp++ = 0xff; + else + *cp++ = 0; + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncmpix_put_short_uchar(void *xp, const uchar *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = 0; + *cp = *ip; + return ENOERR; +} + +int +ncmpix_put_short_short(void *xp, const short *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_SHORT && X_SHORT_MAX == SHORT_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < SHORT_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_short_int(void *xp, const int *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_INT && X_SHORT_MAX == INT_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < INT_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_short_long(void *xp, const long *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_LONG && X_SHORT_MAX == LONG_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < LONG_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_short_float(void *xp, const float *ip) +{ + ix_short xx = *ip; + put_ix_short(xp, &xx); + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_put_short_double(void *xp, const double *ip) +{ + ix_short xx = *ip; + put_ix_short(xp, &xx); + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +/* x_int */ + +#if SHORT_MAX == X_INT_MAX +typedef short ix_int; +#define SIZEOF_IX_INT SIZEOF_SHORT +#define IX_INT_MAX SHORT_MAX +#elif INT_MAX >= X_INT_MAX +typedef int ix_int; +#define SIZEOF_IX_INT SIZEOF_INT +#define IX_INT_MAX INT_MAX +#elif LONG_MAX >= X_INT_MAX +typedef long ix_int; +#define SIZEOF_IX_INT SIZEOF_LONG +#define IX_INT_MAX LONG_MAX +#else +#error "ix_int implementation" +#endif + + +static void +get_ix_int(const void *xp, ix_int *ip) +{ + const uchar *cp = (const uchar *) xp; + + *ip = *cp++ << 24; +#if SIZEOF_IX_INT > X_SIZEOF_INT + if(*ip & 0x80000000) + { + /* extern is negative */ + *ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */ + } +#endif + *ip |= (*cp++ << 16); + *ip |= (*cp++ << 8); + *ip |= *cp; +} + +static void +put_ix_int(void *xp, const ix_int *ip) +{ + uchar *cp = (uchar *) xp; + + *cp++ = (*ip) >> 24; + *cp++ = ((*ip) & 0x00ff0000) >> 16; + *cp++ = ((*ip) & 0x0000ff00) >> 8; + *cp = ((*ip) & 0x000000ff); +} + + +int +ncmpix_get_int_schar(const void *xp, schar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_int_uchar(const void *xp, uchar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_int_short(const void *xp, short *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > SHORT_MAX + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_get_int_int(const void *xp, int *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > INT_MAX + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_get_int_long(const void *xp, long *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > LONG_MAX /* unlikely */ + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_get_int_float(const void *xp, float *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +#if 0 /* TODO: determine when necessary */ + if(xx > FLT_MAX || xx < (-FLT_MAX)) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_get_int_double(const void *xp, double *ip) +{ + /* assert((DBL_MAX >= X_INT_MAX); */ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncmpix_put_int_schar(void *xp, const schar *ip) +{ + uchar *cp = (uchar *) xp; + if(*ip & 0x80) + { + *cp++ = 0xff; + *cp++ = 0xff; + *cp++ = 0xff; + } + else + { + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + } + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncmpix_put_int_uchar(void *xp, const uchar *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + *cp = *ip; + return ENOERR; +} + +int +ncmpix_put_int_short(void *xp, const short *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < SHORT_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_int_int(void *xp, const int *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < INT_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_int_long(void *xp, const long *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < LONG_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncmpix_put_int_float(void *xp, const float *ip) +{ + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); + if(*ip > (double)X_INT_MAX || *ip < (double)X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_put_int_double(void *xp, const double *ip) +{ + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + + +/* x_float */ + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) + +static void +get_ix_float(const void *xp, float *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(ip, xp, sizeof(float)); +#else + swap4b(ip, xp); +#endif +} + +static void +put_ix_float(void *xp, const float *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(xp, ip, X_SIZEOF_FLOAT); +#else + swap4b(xp, ip); +#endif +} + +#elif vax + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int exp_hi : 7; + unsigned int sign : 1; + unsigned int mant_hi : 7; + unsigned int exp_lo : 1; + unsigned int mant_lo_hi : 8; + unsigned int mant_lo_lo : 8; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} max = { + { 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x7f, 0x0, 0x0, 0x1, 0x0, 0x0 } /* Max IEEE */ +}; +static struct sgl_limits min = { + { 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } /* Min IEEE */ +}; + +static void +get_ix_float(const void *xp, float *ip) +{ + struct vax_single *const vsp = (struct vax_single *) ip; + const struct ieee_single *const isp = + (const struct ieee_single *) xp; + unsigned exp = isp->exp_hi << 1 | isp->exp_lo; + + switch(exp) { + case 0 : + /* ieee subnormal */ + if(isp->mant_hi == min.ieee.mant_hi + && isp->mant_lo_hi == min.ieee.mant_lo_hi + && isp->mant_lo_lo == min.ieee.mant_lo_lo) + { + *vsp = min.s; + } + else + { + unsigned mantissa = (isp->mant_hi << 16) + | isp->mant_lo_hi << 8 + | isp->mant_lo_lo; + unsigned tmp = mantissa >> 20; + if(tmp >= 4) { + vsp->exp = 2; + } else if (tmp >= 2) { + vsp->exp = 1; + } else { + *vsp = min.s; + break; + } /* else */ + tmp = mantissa - (1 << (20 + vsp->exp )); + tmp <<= 3 - vsp->exp; + vsp->mantissa2 = tmp; + vsp->mantissa1 = (tmp >> 16); + } + break; + case 0xfe : + case 0xff : + *vsp = max.s; + break; + default : + vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo; + vsp->mantissa1 = isp->mant_hi; + } + + vsp->sign = isp->sign; + +} + + +static void +put_ix_float(void *xp, const float *ip) +{ + const struct vax_single *const vsp = + (const struct vax_single *)ip; + struct ieee_single *const isp = (struct ieee_single *) xp; + + switch(vsp->exp){ + case 0 : + /* all vax float with zero exponent map to zero */ + *isp = min.ieee; + break; + case 2 : + case 1 : + { + /* These will map to subnormals */ + unsigned mantissa = (vsp->mantissa1 << 16) + | vsp->mantissa2; + mantissa >>= 3 - vsp->exp; + mantissa += (1 << (20 + vsp->exp)); + isp->mant_lo_lo = mantissa; + isp->mant_lo_hi = mantissa >> 8; + isp->mant_hi = mantissa >> 16; + isp->exp_lo = 0; + isp->exp_hi = 0; + } + break; + case 0xff : /* max.s.exp */ + if( vsp->mantissa2 == max.s.mantissa2 + && vsp->mantissa1 == max.s.mantissa1) + { + /* map largest vax float to ieee infinity */ + *isp = max.ieee; + break; + } /* else, fall thru */ + default : + { + unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + isp->exp_hi = exp >> 1; + isp->exp_lo = exp; + isp->mant_lo_lo = vsp->mantissa2; + isp->mant_lo_hi = vsp->mantissa2 >> 8; + isp->mant_hi = vsp->mantissa1; + } + } + + isp->sign = vsp->sign; + +} + + /* vax */ +#else +#error "ix_float implementation" +#endif + + +int +ncmpix_get_float_schar(const void *xp, schar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_float_uchar(const void *xp, uchar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_float_short(const void *xp, short *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_float_int(const void *xp, int *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (int) xx; + if(xx > (double)INT_MAX || xx < (double)INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_float_long(const void *xp, long *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_float_float(const void *xp, float *ip) +{ + /* TODO */ + get_ix_float(xp, ip); + return ENOERR; +} + +int +ncmpix_get_float_double(const void *xp, double *ip) +{ + /* TODO */ + float xx; + get_ix_float(xp, &xx); + *ip = xx; + return ENOERR; +} + + +int +ncmpix_put_float_schar(void *xp, const schar *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + return ENOERR; +} + +int +ncmpix_put_float_uchar(void *xp, const uchar *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + return ENOERR; +} + +int +ncmpix_put_float_short(void *xp, const short *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 0 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_float_int(void *xp, const int *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 1 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_float_long(void *xp, const long *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 1 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_float_float(void *xp, const float *ip) +{ + put_ix_float(xp, ip); +#ifdef NO_IEEE_FLOAT + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_float_double(void *xp, const double *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; + return ENOERR; +} + +/* x_double */ + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) + +static void +get_ix_double(const void *xp, double *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(ip, xp, sizeof(double)); +#else + swap8b(ip, xp); +#endif +} + +static void +put_ix_double(void *xp, const double *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(xp, ip, X_SIZEOF_DOUBLE); +#else + swap8b(xp, ip); +#endif +} + +#elif vax + +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int exp_hi : 7; + unsigned int sign : 1; + unsigned int mant_6 : 4; + unsigned int exp_lo : 4; + unsigned int mant_5 : 8; + unsigned int mant_4 : 8; + + unsigned int mant_lo : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static const struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x7f, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, /* Min IEEE */ +}; + + +static void +get_ix_double(const void *xp, double *ip) +{ + struct vax_double *const vdp = + (struct vax_double *)ip; + const struct ieee_double *const idp = + (const struct ieee_double *) xp; + { + const struct dbl_limits *lim; + int ii; + for (ii = 0, lim = dbl_limits; + ii < sizeof(dbl_limits)/sizeof(struct dbl_limits); + ii++, lim++) + { + if ((idp->mant_lo == lim->ieee.mant_lo) + && (idp->mant_4 == lim->ieee.mant_4) + && (idp->mant_5 == lim->ieee.mant_5) + && (idp->mant_6 == lim->ieee.mant_6) + && (idp->exp_lo == lim->ieee.exp_lo) + && (idp->exp_hi == lim->ieee.exp_hi) + ) + { + *vdp = lim->d; + goto doneit; + } + } + } + { + unsigned exp = idp->exp_hi << 4 | idp->exp_lo; + vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + } + { + unsigned mant_hi = ((idp->mant_6 << 16) + | (idp->mant_5 << 8) + | idp->mant_4); + unsigned mant_lo = SWAP4(idp->mant_lo); + vdp->mantissa1 = (mant_hi >> 13); + vdp->mantissa2 = ((mant_hi & MASK(13)) << 3) + | (mant_lo >> 29); + vdp->mantissa3 = (mant_lo >> 13); + vdp->mantissa4 = (mant_lo << 3); + } + doneit: + vdp->sign = idp->sign; + +} + + +static void +put_ix_double(void *xp, const double *ip) +{ + const struct vax_double *const vdp = + (const struct vax_double *)ip; + struct ieee_double *const idp = + (struct ieee_double *) xp; + + if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) && + (vdp->mantissa3 == dbl_limits[0].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[0].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[0].d.mantissa1) && + (vdp->exp == dbl_limits[0].d.exp)) + { + *idp = dbl_limits[0].ieee; + goto shipit; + } + if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) && + (vdp->mantissa3 == dbl_limits[1].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[1].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[1].d.mantissa1) && + (vdp->exp == dbl_limits[1].d.exp)) + { + *idp = dbl_limits[1].ieee; + goto shipit; + } + + { + unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + + unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) | + (vdp->mantissa3 << 13) | + ((vdp->mantissa4 >> 3) & MASK(13)); + + unsigned mant_hi = (vdp->mantissa1 << 13) + | (vdp->mantissa2 >> 3); + + if((vdp->mantissa4 & 7) > 4) + { + /* round up */ + mant_lo++; + if(mant_lo == 0) + { + mant_hi++; + if(mant_hi > 0xffffff) + { + mant_hi = 0; + exp++; + } + } + } + + idp->mant_lo = SWAP4(mant_lo); + idp->mant_6 = mant_hi >> 16; + idp->mant_5 = (mant_hi & 0xff00) >> 8; + idp->mant_4 = mant_hi; + idp->exp_hi = exp >> 4; + idp->exp_lo = exp; + } + + shipit: + idp->sign = vdp->sign; + +} + + /* vax */ +#else +#error "ix_double implementation" +#endif + +int +ncmpix_get_double_schar(const void *xp, schar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_double_uchar(const void *xp, uchar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_double_short(const void *xp, short *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_double_int(const void *xp, int *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (int) xx; + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_double_long(const void *xp, long *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncmpix_get_double_float(const void *xp, float *ip) +{ + double xx; + get_ix_double(xp, &xx); + if(xx > FLT_MAX || xx < (-FLT_MAX)) + { + *ip = FLT_MAX; + return NC_ERANGE; + } + if(xx < (-FLT_MAX)) + { + *ip = (-FLT_MAX); + return NC_ERANGE; + } + *ip = (float) xx; + return ENOERR; +} + +int +ncmpix_get_double_double(const void *xp, double *ip) +{ + /* TODO */ + get_ix_double(xp, ip); + return ENOERR; +} + + +int +ncmpix_put_double_schar(void *xp, const schar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncmpix_put_double_uchar(void *xp, const uchar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncmpix_put_double_short(void *xp, const short *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 0 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_double_int(void *xp, const int *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 0 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_double_long(void *xp, const long *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 1 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_double_float(void *xp, const float *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 1 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncmpix_put_double_double(void *xp, const double *ip) +{ + put_ix_double(xp, ip); +#ifdef NO_IEEE_FLOAT + if(*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + + +/* x_size_t */ + +#if SIZEOF_SIZE_T < X_SIZEOF_SIZE_T +#error "x_size_t implementation" +/* netcdf requires size_t which can hold a values from 0 to 2^31 -1 */ +#endif + +int +ncmpix_put_size_t(void **xpp, const size_t *ulp) +{ + /* similar to put_ix_int() */ + uchar *cp = (uchar *) *xpp; + assert(*ulp <= X_SIZE_MAX); + + *cp++ = (uchar)((*ulp) >> 24); + *cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*ulp) & 0x0000ff00) >> 8); + *cp = (uchar)((*ulp) & 0x000000ff); + + *xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +int +ncmpix_get_size_t(const void **xpp, size_t *ulp) +{ + /* similar to get_ix_int */ + const uchar *cp = (const uchar *) *xpp; + + *ulp = (unsigned)(*cp++ << 24); + *ulp |= (*cp++ << 16); + *ulp |= (*cp++ << 8); + *ulp |= *cp; + + *xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +/* x_off_t */ + +/* A previous version of this function would try to let systems with a 4 byte + * off_t read and write the 8-byte offsets of a CDF-2 file. For simplicity, we + * now ensure that platforms with a 4-byte off_t will never open a CDF-2 file + * no matter what the size. + */ +int +ncmpix_put_off_t(void **xpp, const MPI_Offset *lp, size_t sizeof_off_t) +{ + /* similar to put_ix_int() */ + uchar *cp = (uchar *) *xpp; + /* No negative offsets stored in netcdf */ + if (*lp < 0) { + /* assume this is an overflow of a 32-bit int */ + return ERANGE; + } + assert(sizeof_off_t == 4 || sizeof_off_t == 8); + if (sizeof_off_t == 4 ) { + *cp++ = (uchar)(((*lp) & 0xff000000) >> 24); + *cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*lp) & 0x0000ff00) >> 8); + *cp = (uchar)( (*lp) & 0x000000ff); + } else { + *cp++ = (uchar)(((*lp) & 0xff00000000000000ULL) >> 56); + *cp++ = (uchar)(((*lp) & 0x00ff000000000000ULL) >> 48); + *cp++ = (uchar)(((*lp) & 0x0000ff0000000000ULL) >> 40); + *cp++ = (uchar)(((*lp) & 0x000000ff00000000ULL) >> 32); + *cp++ = (uchar)(((*lp) & 0x00000000ff000000ULL) >> 24); + *cp++ = (uchar)(((*lp) & 0x0000000000ff0000ULL) >> 16); + *cp++ = (uchar)(((*lp) & 0x000000000000ff00ULL) >> 8); + *cp = (uchar)( (*lp) & 0x00000000000000ffULL); + } + *xpp = (void *)((char *)(*xpp) + sizeof_off_t); + return ENOERR; +} + +/* see comments for ncmpix_put_off_t */ +int +ncmpix_get_off_t(const void **xpp, MPI_Offset *lp, size_t sizeof_off_t) +{ + /* similar to get_ix_int() */ + const uchar *cp = (const uchar *) *xpp; + assert(sizeof_off_t == 4 || sizeof_off_t == 8); + + if (sizeof_off_t == 4) { + *lp = *cp++ << 24; + *lp |= (*cp++ << 16); + *lp |= (*cp++ << 8); + *lp |= *cp; + } else { + *lp = ((off_t)(*cp++) << 56); + *lp |= ((off_t)(*cp++) << 48); + *lp |= ((off_t)(*cp++) << 40); + *lp |= ((off_t)(*cp++) << 32); + *lp |= ((off_t)(*cp++) << 24); + *lp |= ((off_t)(*cp++) << 16); + *lp |= ((off_t)(*cp++) << 8); + *lp |= (off_t)*cp; + } + *xpp = (const void *)((const char *)(*xpp) + sizeof_off_t); + + + return ENOERR; +} + + +/* + * Aggregate numeric conversion functions. + */ + + + +/* schar */ + +int +ncmpix_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncmpix_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncmpix_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncmpix_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncmpix_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncmpix_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncmpix_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + + +int +ncmpix_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncmpix_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncmpix_pad_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncmpix_pad_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncmpix_pad_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncmpix_pad_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncmpix_pad_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + + +int +ncmpix_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncmpix_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncmpix_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncmpix_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncmpix_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncmpix_pad_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + + + +/* short */ + +int +ncmpix_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_SHORT == SIZEOF_SHORT +/* optimized version */ +int +ncmpix_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(short)); +# else + swapn2b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT); + return ENOERR; +} +#else +int +ncmpix_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncmpix_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncmpix_pad_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncmpix_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + + +int +ncmpix_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_SHORT == SIZEOF_SHORT +/* optimized version */ +int +ncmpix_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_SHORT); +# else + swapn2b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT); + return ENOERR; +} +#else +int +ncmpix_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncmpix_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncmpix_pad_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_pad_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncmpix_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + + + +/* int */ + +int +ncmpix_getn_int_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_int_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_int_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_INT == SIZEOF_INT +/* optimized version */ +int +ncmpix_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(int)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncmpix_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +#if X_SIZEOF_INT == SIZEOF_LONG +/* optimized version */ +int +ncmpix_getn_int_long(const void **xpp, size_t nelems, long *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(long)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncmpix_getn_int_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncmpix_getn_int_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_int_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncmpix_get_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncmpix_putn_int_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_int_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_int_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_INT == SIZEOF_INT +/* optimized version */ +int +ncmpix_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncmpix_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +#if X_SIZEOF_INT == SIZEOF_LONG +/* optimized version */ +int +ncmpix_putn_int_long(void **xpp, size_t nelems, const long *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncmpix_putn_int_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncmpix_putn_int_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_int_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncmpix_put_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* float */ + +int +ncmpix_getn_float_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_float_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_float_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_float_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_float_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncmpix_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(float)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT); + return ENOERR; +} +#elif vax +int +ncmpix_getn_float_float(const void **xpp, size_t nfloats, float *ip) +{ + float *const end = ip + nfloats; + + while(ip < end) + { + struct vax_single *const vsp = (struct vax_single *) ip; + const struct ieee_single *const isp = + (const struct ieee_single *) (*xpp); + unsigned exp = isp->exp_hi << 1 | isp->exp_lo; + + switch(exp) { + case 0 : + /* ieee subnormal */ + if(isp->mant_hi == min.ieee.mant_hi + && isp->mant_lo_hi == min.ieee.mant_lo_hi + && isp->mant_lo_lo == min.ieee.mant_lo_lo) + { + *vsp = min.s; + } + else + { + unsigned mantissa = (isp->mant_hi << 16) + | isp->mant_lo_hi << 8 + | isp->mant_lo_lo; + unsigned tmp = mantissa >> 20; + if(tmp >= 4) { + vsp->exp = 2; + } else if (tmp >= 2) { + vsp->exp = 1; + } else { + *vsp = min.s; + break; + } /* else */ + tmp = mantissa - (1 << (20 + vsp->exp )); + tmp <<= 3 - vsp->exp; + vsp->mantissa2 = tmp; + vsp->mantissa1 = (tmp >> 16); + } + break; + case 0xfe : + case 0xff : + *vsp = max.s; + break; + default : + vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo; + vsp->mantissa1 = isp->mant_hi; + } + + vsp->sign = isp->sign; + + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_FLOAT; + } + return ENOERR; +} +#else +int +ncmpix_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncmpix_getn_float_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncmpix_get_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncmpix_putn_float_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_float_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_float_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_float_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_float_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncmpix_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_FLOAT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT); + return ENOERR; +} +#elif vax +int +ncmpix_putn_float_float(void **xpp, size_t nfloats, const float *ip) +{ + const float *const end = ip + nfloats; + + while(ip < end) + { + const struct vax_single *const vsp = + (const struct vax_single *)ip; + struct ieee_single *const isp = (struct ieee_single *) (*xpp); + + switch(vsp->exp){ + case 0 : + /* all vax float with zero exponent map to zero */ + *isp = min.ieee; + break; + case 2 : + case 1 : + { + /* These will map to subnormals */ + unsigned mantissa = (vsp->mantissa1 << 16) + | vsp->mantissa2; + mantissa >>= 3 - vsp->exp; + mantissa += (1 << (20 + vsp->exp)); + isp->mant_lo_lo = mantissa; + isp->mant_lo_hi = mantissa >> 8; + isp->mant_hi = mantissa >> 16; + isp->exp_lo = 0; + isp->exp_hi = 0; + } + break; + case 0xff : /* max.s.exp */ + if( vsp->mantissa2 == max.s.mantissa2 + && vsp->mantissa1 == max.s.mantissa1) + { + /* map largest vax float to ieee infinity */ + *isp = max.ieee; + break; + } /* else, fall thru */ + default : + { + unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + isp->exp_hi = exp >> 1; + isp->exp_lo = exp; + isp->mant_lo_lo = vsp->mantissa2; + isp->mant_lo_hi = vsp->mantissa2 >> 8; + isp->mant_hi = vsp->mantissa1; + } + } + + isp->sign = vsp->sign; + + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_FLOAT; + } + return ENOERR; +} +#else +int +ncmpix_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncmpix_putn_float_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncmpix_put_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* double */ + +int +ncmpix_getn_double_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_double_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_double_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_double_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_double_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncmpix_getn_double_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncmpix_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(double)); +# else + swapn8b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#elif vax +int +ncmpix_getn_double_double(const void **xpp, size_t ndoubles, double *ip) +{ + double *const end = ip + ndoubles; + + while(ip < end) + { + struct vax_double *const vdp = + (struct vax_double *)ip; + const struct ieee_double *const idp = + (const struct ieee_double *) (*xpp); + { + const struct dbl_limits *lim; + int ii; + for (ii = 0, lim = dbl_limits; + ii < sizeof(dbl_limits)/sizeof(struct dbl_limits); + ii++, lim++) + { + if ((idp->mant_lo == lim->ieee.mant_lo) + && (idp->mant_4 == lim->ieee.mant_4) + && (idp->mant_5 == lim->ieee.mant_5) + && (idp->mant_6 == lim->ieee.mant_6) + && (idp->exp_lo == lim->ieee.exp_lo) + && (idp->exp_hi == lim->ieee.exp_hi) + ) + { + *vdp = lim->d; + goto doneit; + } + } + } + { + unsigned exp = idp->exp_hi << 4 | idp->exp_lo; + vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + } + { + unsigned mant_hi = ((idp->mant_6 << 16) + | (idp->mant_5 << 8) + | idp->mant_4); + unsigned mant_lo = SWAP4(idp->mant_lo); + vdp->mantissa1 = (mant_hi >> 13); + vdp->mantissa2 = ((mant_hi & MASK(13)) << 3) + | (mant_lo >> 29); + vdp->mantissa3 = (mant_lo >> 13); + vdp->mantissa4 = (mant_lo << 3); + } + doneit: + vdp->sign = idp->sign; + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE; + } + return ENOERR; +} + /* vax */ + +#else +int +ncmpix_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncmpix_get_double_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif + +int +ncmpix_putn_double_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_double_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_double_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_double_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_double_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncmpix_putn_double_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncmpix_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ +# ifdef WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE); +# else + swapn8b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#elif vax +int +ncmpix_putn_double_double(void **xpp, size_t ndoubles, const double *ip) +{ + const double *const end = ip + ndoubles; + + while(ip < end) + { + const struct vax_double *const vdp = + (const struct vax_double *)ip; + struct ieee_double *const idp = + (struct ieee_double *) (*xpp); + + if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) && + (vdp->mantissa3 == dbl_limits[0].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[0].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[0].d.mantissa1) && + (vdp->exp == dbl_limits[0].d.exp)) + { + *idp = dbl_limits[0].ieee; + goto shipit; + } + if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) && + (vdp->mantissa3 == dbl_limits[1].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[1].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[1].d.mantissa1) && + (vdp->exp == dbl_limits[1].d.exp)) + { + *idp = dbl_limits[1].ieee; + goto shipit; + } + + { + unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + + unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) | + (vdp->mantissa3 << 13) | + ((vdp->mantissa4 >> 3) & MASK(13)); + + unsigned mant_hi = (vdp->mantissa1 << 13) + | (vdp->mantissa2 >> 3); + + if((vdp->mantissa4 & 7) > 4) + { + /* round up */ + mant_lo++; + if(mant_lo == 0) + { + mant_hi++; + if(mant_hi > 0xffffff) + { + mant_hi = 0; + exp++; + } + } + } + + idp->mant_lo = SWAP4(mant_lo); + idp->mant_6 = mant_hi >> 16; + idp->mant_5 = (mant_hi & 0xff00) >> 8; + idp->mant_4 = mant_hi; + idp->exp_hi = exp >> 4; + idp->exp_lo = exp; + } + + shipit: + idp->sign = vdp->sign; + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE; + } + return ENOERR; +} + /* vax */ + +#else +int +ncmpix_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncmpix_put_double_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif + + +/* + * Other aggregate conversion functions. + */ + +/* text */ + +int +ncmpix_getn_text(const void **xpp, size_t nelems, char *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncmpix_pad_getn_text(const void **xpp, size_t nelems, char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncmpix_putn_text(void **xpp, size_t nelems, const char *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncmpix_pad_putn_text(void **xpp, size_t nelems, const char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} + + +/* opaque */ + +int +ncmpix_getn_void(const void **xpp, size_t nelems, void *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncmpix_pad_getn_void(const void **xpp, size_t nelems, void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncmpix_putn_void(void **xpp, size_t nelems, const void *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncmpix_pad_putn_void(void **xpp, size_t nelems, const void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} + Index: /tags/v1-0-3/src/lib/pnetcdf.h =================================================================== --- /tags/v1-0-3/src/lib/pnetcdf.h (revision 560) +++ /tags/v1-0-3/src/lib/pnetcdf.h (revision 560) @@ -0,0 +1,2125 @@ +/* + * Copyright 1993-1996 University Corporation for Atmospheric Research/Unidata + * + * Portions of this software were developed by the Unidata Program at the + * University Corporation for Atmospheric Research. + * + * Access and use of this software shall impose the following obligations + * and understandings on the user. The user is granted the right, without + * any fee or cost, to use, copy, modify, alter, enhance and distribute + * this software, and any derivative works thereof, and its supporting + * documentation for any purpose whatsoever, provided that this entire + * notice appears in all copies of the software, derivative works and + * supporting documentation. Further, UCAR requests that the user credit + * UCAR/Unidata in any publications that result from the use of this + * software or in any product that includes this software. The names UCAR + * and/or Unidata, however, may not be used in any advertising or publicity + * to endorse or promote any products or commercial entity unless specific + * written permission is obtained from UCAR/Unidata. The user also + * understands that UCAR/Unidata is not obligated to provide the user with + * any support, consulting, training or assistance of any kind with regard + * to the use, operation and performance of this software nor to provide + * the user with any updates, revisions, new versions or "bug fixes." + * + * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* "$Id$" */ + +#ifndef _PNETCDF_ +#define _PNETCDF_ + +#include /* size_t, ptrdiff_t */ +#include /* netcdf functions sometimes return system errors */ +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * The netcdf external data types + */ +typedef enum { + NC_NAT = 0, /* NAT = 'Not A Type' (c.f. NaN) */ + NC_BYTE = 1, /* signed 1 byte integer */ + NC_CHAR = 2, /* ISO/ASCII character */ + NC_SHORT = 3, /* signed 2 byte integer */ + NC_INT = 4, /* signed 4 byte integer */ + NC_FLOAT = 5, /* single precision floating point number */ + NC_DOUBLE = 6 /* double precision floating point number */ +} nc_type; + +typedef nc_type ncmpi_type; + +/* + * The PnetCDF non-blocking I/O request type + */ +struct NCMPI_Req { + int reqtype; + MPI_Request mpi_req; + nc_type vartype; + void *xbuf; + void *cbuf; + void *lbuf; + int nelems; + int cnelems; + int lnelems; + int iscontig_of_ptypes; + void *buf; + int bufcount; + MPI_Datatype datatype; + MPI_Datatype ptype; + MPI_Datatype imaptype; + struct NCMPI_Req *next_req; +}; +typedef struct NCMPI_Req * NCMPI_Request; +#define NCMPI_REQUEST_NULL ((NCMPI_Request)NULL) +#define NCMPI_REQTYPE_READ 1 +#define NCMPI_REQTYPE_WRITE 2 +#define NCMPI_REQTYPE_MREAD 3 +#define NCMPI_REQTYPE_MWRITE 4 + +/* + * Default fill values, used unless _FillValue attribute is set. + * These values are stuffed into newly allocated space as appropriate. + * The hope is that one might use these to notice that a particular datum + * has not been set. + */ +#define NC_FILL_BYTE ((signed char)-127) +#define NC_FILL_CHAR ((char)0) +#define NC_FILL_SHORT ((short)-32767) +#define NC_FILL_INT (-2147483647L) +#define NC_FILL_FLOAT (9.9692099683868690e+36f) /* near 15 * 2^119 */ +#define NC_FILL_DOUBLE (9.9692099683868690e+36) + + +/* + * The above values are defaults. + * If you wish a variable to use a different value than the above + * defaults, create an attribute with the same type as the variable + * and the following reserved name. The value you give the attribute + * will be used as the fill value for that variable. + */ +#define _FillValue "_FillValue" + + +/* + * 'mode' flags for nccreate and ncopen + */ +#define NC_NOWRITE 0 /* default is read only */ +#define NC_WRITE 0x1 /* read & write */ +#define NC_CLOBBER 0 +#define NC_NOCLOBBER 0x4 /* Don't destroy existing file on create */ +#define NC_FILL 0 /* argument to ncsetfill to clear NC_NOFILL */ +#define NC_NOFILL 0x100 /* Don't fill data section an records */ +#define NC_LOCK 0x0400 /* Use locking if available */ +#define NC_SHARE 0x0800 /* Share updates, limit cacheing */ +#define NC_64BIT_OFFSET 0x0200 /* Use large (64-bit) file offsets */ +/* Starting with serial netcdf-3.6 and parallel-netcdf-0.9.2, there are + * different format netCDF files */ +#define NC_FORMAT_CLASSIC 1 +#define NC_FORMAT_64BIT 2 + +/* + * Let nc__create() or nc__open() figure out + * as suitable chunk size. + */ +#define NC_SIZEHINT_DEFAULT 0 + +/* + * In nc__enddef(), align to the chunk size. + */ +#define NC_ALIGN_CHUNK ((size_t)(-1)) + +/* + * 'size' argument to ncdimdef for an unlimited dimension + */ +#define NC_UNLIMITED 0L + +/* + * attribute id to put/get a global attribute + */ +#define NC_GLOBAL -1 + + +/* + * These maximums are enforced by the interface, to facilitate writing + * applications and utilities. However, nothing is statically allocated to + * these sizes internally. + */ +#define NC_MAX_DIMS 512 /* max dimensions per file */ +#define NC_MAX_ATTRS 4096 /* max global or per variable attributes */ +#define NC_MAX_VARS 4096 /* max variables per file */ +#define NC_MAX_NAME 128 /* max length of a name */ +#define NC_MAX_VAR_DIMS NC_MAX_DIMS /* max per variable dimensions */ + + +/* + * The netcdf version 3 functions all return integer error status. + * These are the possible values, in addition to certain + * values from the system errno.h. + */ + +#define NC_ISSYSERR(err) ((err) > 0) + +#define NC_NOERR 0 /* No Error */ + +#define NC_ESMALL (-25) /* size of off_t too small for format */ +#define NC_ENOTINDEP (-26) /* Operation not allowed in collective data mode */ +#define NC_EINDEP (-27) /* Operation not allowed in independent data mode */ +#define NC_EFILE (-28) /* Unknown error in file operation */ +#define NC_EREAD (-29) /* Unknown error in reading file */ +#define NC_EWRITE (-30) /* Unknown error in writting to file */ +#define NC_EMULTIDEFINE (-31) /* NC definations on multiprocesses conflict */ +#define NC_EOFILE (-32) /* file open/creation failed */ +#define NC_EBADID (-33) /* Not a netcdf id */ +#define NC_ENFILE (-34) /* Too many netcdfs open */ +#define NC_EEXIST (-35) /* netcdf file exists && NC_NOCLOBBER */ +#define NC_EINVAL (-36) /* Invalid Argument */ +#define NC_EPERM (-37) /* Write to read only */ +#define NC_ENOTINDEFINE (-38) /* Operation not allowed in data mode */ +#define NC_EINDEFINE (-39) /* Operation not allowed in define mode */ +#define NC_EINVALCOORDS (-40) /* Index exceeds dimension bound */ +#define NC_EMAXDIMS (-41) /* NC_MAX_DIMS exceeded */ +#define NC_ENAMEINUSE (-42) /* String match to name in use */ +#define NC_ENOTATT (-43) /* Attribute not found */ +#define NC_EMAXATTS (-44) /* NC_MAX_ATTRS exceeded */ +#define NC_EBADTYPE (-45) /* Not a netcdf data type */ +#define NC_EBADDIM (-46) /* Invalid dimension id or name */ +#define NC_EUNLIMPOS (-47) /* NC_UNLIMITED in the wrong index */ +#define NC_EMAXVARS (-48) /* NC_MAX_VARS exceeded */ +#define NC_ENOTVAR (-49) /* Variable not found */ +#define NC_EGLOBAL (-50) /* Action prohibited on NC_GLOBAL varid */ +#define NC_ENOTNC (-51) /* Not a netcdf file */ +#define NC_ESTS (-52) /* In Fortran, string too short */ +#define NC_EMAXNAME (-53) /* NC_MAX_NAME exceeded */ +#define NC_EUNLIMIT (-54) /* NC_UNLIMITED size already in use */ +#define NC_ENORECVARS (-55) /* nc_rec op when there are no record vars */ +#define NC_ECHAR (-56) /* Attempt to convert between text & numbers */ +#define NC_EEDGE (-57) /* Edge+start exceeds dimension bound */ +#define NC_ESTRIDE (-58) /* Illegal stride */ +#define NC_EBADNAME (-59) /* Attribute or variable name + contains illegal characters */ +/* N.B. following must match value in ncx.h */ +#define NC_ERANGE (-60) /* Math result not representable */ +#define NC_ENOMEM (-61) /* Memory allocation (malloc) failure */ +#define NC_EVARSIZE (-62) /* One or more variable sizes violate + format constraints */ +#define NC_EDIMSIZE (-63) /* Invalid dimension size */ +/* More error codes: */ +#define NC_EMULTITYPES (-70) /* Multiple types used in memory data */ +#define NC_EIOMISMATCH (-71) /* Input/Output data amount mismatch */ +#define NC_ENEGATIVECNT (-72) /* Negative count is specified */ +#define NC_EUNSPTETYPE (-73) /* Unsupported etype in memory MPI datatype */ + +/* + * The Interface + */ + +/* Declaration modifiers for DLL support (MSC et al) */ + +#if defined(DLL_NETCDF) /* define when library is a DLL */ +# if defined(DLL_EXPORT) /* define when building the library */ +# define MSC_EXTRA __declspec(dllexport) +# else +# define MSC_EXTRA __declspec(dllimport) +# endif +#else +#define MSC_EXTRA +#endif /* defined(DLL_NETCDF) */ + +# define EXTERNL extern MSC_EXTRA + +#include + +/* Begin Prototypes */ + + +const char * +ncmpi_strerror(int err); + +/* Begin Dataset Functions */ + + +int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp); + +int ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp); + +int ncmpi_get_file_info(int ncid, MPI_Info *info_used); + +int ncmpi_delete(char * filename, MPI_Info info); + +int ncmpi_enddef(int ncid); + + +int ncmpi_redef(int ncid); + +int ncmpi_set_default_format(int format, int *old_formatp); + +int ncmpi_sync(int ncid); + + +int ncmpi_abort(int ncid); + + +int ncmpi_begin_indep_data(int ncid); + + +int ncmpi_end_indep_data(int ncid); + + +int ncmpi_close(int ncid); + +int ncmpi_set_fill(int ncid, int fillmode, int *old_modep); +/* End Dataset Functions */ + +/* Begin Define Mode Functions */ + + +int ncmpi_def_dim(int ncid, const char *name, MPI_Offset len, int *idp); + + +int ncmpi_def_var(int ncid, const char *name, nc_type xtype, + int ndims, const int *dimidsp, int *varidp); + + +int ncmpi_rename_dim(int ncid, int dimid, const char *name); + + +int ncmpi_rename_var(int ncid, int varid, const char *name); + +/* End Define Mode Functions */ + +/* Begin Inquiry Functions */ + +const char * +ncmpi_inq_libvers(void); + +int ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, + int *ngattsp, int *unlimdimidp); + + +int ncmpi_inq_ndims(int ncid, int *ndimsp); + + +int ncmpi_inq_nvars(int ncid, int *nvarsp); + + +int ncmpi_inq_natts(int ncid, int *ngattsp); + + +int ncmpi_inq_unlimdim(int ncid, int *unlimdimidp); + + +int ncmpi_inq_dimid(int ncid, const char *name, int *idp); + + +int ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *lenp); + + +int ncmpi_inq_dimname(int ncid, int dimid, char *name); + + +int ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp); + + +int ncmpi_inq_var(int ncid, int varid, char *name, + nc_type *xtypep, int *ndimsp, int *dimidsp, + int *nattsp); + + +int ncmpi_inq_varid(int ncid, const char *name, int *varidp); + + +int ncmpi_inq_varname(int ncid, int varid, char *name); + + +int ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep); + +int ncmpi_inq_varndims(int ncid, int varid, int *ndimsp); + + +int ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp); + + +int ncmpi_inq_varnatts(int ncid, int varid, int *nattsp); + +/* End Inquiry Functions */ + +/* Begin _att */ + + +int ncmpi_inq_att(int ncid, int varid, const char *name, + nc_type *xtypep, MPI_Offset *lenp); + + +int ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp); + + +int ncmpi_inq_atttype(int ncid, int varid, const char *name, + nc_type *xtypep); + + +int ncmpi_inq_attlen(int ncid, int varid, const char *name, + MPI_Offset *lenp); + + +int ncmpi_inq_attname(int ncid, int varid, int attnum, char *name); + + +int ncmpi_copy_att(int ncid_in, int varid_in, const char *name, + int ncid_out, int varid_out); + + +int ncmpi_rename_att(int ncid, int varid, const char *name, + const char *newname); + + +int ncmpi_del_att(int ncid, int varid, const char *name); + + +int ncmpi_put_att_text(int ncid, int varid, const char *name, MPI_Offset len, + const char *op); + + +int ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip); + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_att_uchar(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const unsigned char *op); + + +int ncmpi_get_att_uchar(int ncid, int varid, const char *name, + unsigned char *ip); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_put_att_schar(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const signed char *op); + + +int ncmpi_get_att_schar(int ncid, int varid, const char *name, + signed char *ip); + + +int ncmpi_put_att_short(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const short *op); + + +int ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip); + + +int ncmpi_put_att_int(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const int *op); + + +int ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_att_long(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const long *op); + +int ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_att_float(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const float *op); + + +int ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip); + + +int ncmpi_put_att_double(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const double *op); + + +int ncmpi_get_att_double(int ncid, int varid, const char *name, + double *ip); + +/* End _att */ + +/* Begin {put,get}_var1 */ + + +int ncmpi_put_var1(int ncid, int varid, + const MPI_Offset index[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_var1(int ncid, int varid, + const MPI_Offset index[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_put_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + const unsigned char *op); +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_put_var1_schar(int ncid, int varid, + const MPI_Offset index[], + const signed char *op); + + +int ncmpi_put_var1_text(int ncid, int varid, + const MPI_Offset index[], + const char *op); + + +int ncmpi_put_var1_short(int ncid, int varid, + const MPI_Offset index[], + const short *op); + + +int ncmpi_put_var1_int(int ncid, int varid, + const MPI_Offset index[], + const int *op); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_var1_long(int ncid, int varid, + const MPI_Offset index[], + const long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_var1_float(int ncid, int varid, + const MPI_Offset index[], + const float *op); + + +int ncmpi_put_var1_double(int ncid, int varid, + const MPI_Offset index[], + const double *op); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + unsigned char *ip); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_get_var1_schar(int ncid, int varid, + const MPI_Offset index[], + signed char *ip); + + +int ncmpi_get_var1_text(int ncid, int varid, + const MPI_Offset index[], + char *ip); + + +int ncmpi_get_var1_short(int ncid, int varid, + const MPI_Offset index[], + short *ip); + + +int ncmpi_get_var1_int(int ncid, int varid, + const MPI_Offset index[], + int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_var1_long(int ncid, int varid, + const MPI_Offset index[], + long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_var1_float(int ncid, int varid, + const MPI_Offset index[], + float *ip); + + +int ncmpi_get_var1_double(int ncid, int varid, + const MPI_Offset index[], + double *ip); + +/* End {put,get}_var1 */ + +/* Begin {put,get}_var */ + + +int ncmpi_put_var(int ncid, int varid, const void *buf, int bufcount, MPI_Datatype datatype); + + +int ncmpi_get_var(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype); + + +int ncmpi_get_var_all(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_put_var_uchar(int ncid, int varid, const unsigned char *op); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_put_var_schar(int ncid, int varid, const signed char *op); + + +int ncmpi_put_var_text(int ncid, int varid, const char *op); + + +int ncmpi_put_var_short(int ncid, int varid, const short *op); + + +int ncmpi_put_var_int(int ncid, int varid, const int *op); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_var_long(int ncid, int varid, const long *op); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_var_float(int ncid, int varid, const float *op); + + +int ncmpi_put_var_double(int ncid, int varid, const double *op); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_var_uchar(int ncid, int varid, unsigned char *ip); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_get_var_schar(int ncid, int varid, signed char *ip); + + +int ncmpi_get_var_text(int ncid, int varid, char *ip); + + +int ncmpi_get_var_short(int ncid, int varid, short *ip); + + +int ncmpi_get_var_int(int ncid, int varid, int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_var_long(int ncid, int varid, long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_var_float(int ncid, int varid, float *ip); + + +int ncmpi_get_var_double(int ncid, int varid, double *ip); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_var_uchar_all(int ncid, int varid, unsigned char *ip); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_var_schar_all(int ncid, int varid, signed char *ip); + + +int ncmpi_get_var_text_all(int ncid, int varid, char *ip); + + +int ncmpi_get_var_short_all(int ncid, int varid, short *ip); + + +int ncmpi_get_var_int_all(int ncid, int varid, int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_var_long_all(int ncid, int varid, long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_var_float_all(int ncid, int varid, float *ip); + + +int ncmpi_get_var_double_all(int ncid, int varid, double *ip); + +/* End {put,get}_var */ + +/* Begin {put,get}_vara */ + + +int ncmpi_put_vara_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_vara_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_put_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_put_vara_uchar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op); + + +int ncmpi_put_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_put_vara_schar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op); + + +int ncmpi_put_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op); + + +int ncmpi_put_vara_text_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op); + + +int ncmpi_put_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op); + + +int ncmpi_put_vara_short_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op); + + +int ncmpi_put_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op); + + +int ncmpi_put_vara_int_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op); + + +int ncmpi_put_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_vara_long_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op); + + +int ncmpi_put_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_vara_float_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op); + + +int ncmpi_put_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op); + + +int ncmpi_put_vara_double_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op); + + +int ncmpi_put_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_vara_uchar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip); + + +int ncmpi_get_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_vara_schar_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip); + + +int ncmpi_get_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip); + + +int ncmpi_get_vara_text_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip); + + +int ncmpi_get_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip); + + +int ncmpi_get_vara_short_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip); + + +int ncmpi_get_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip); + + +int ncmpi_get_vara_int_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip); + + +int ncmpi_get_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_vara_long_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip); + + +int ncmpi_get_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_vara_float_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip); + + +int ncmpi_get_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip); + + +int ncmpi_get_vara_double_all(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip); + + +int ncmpi_get_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip); + +/* End {put,get}_vara */ + +/* Begin {put,get}_vars */ + + +int ncmpi_put_vars_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_vars_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_put_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_put_vars_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op); + + +int ncmpi_put_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_vars_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op); + + +int ncmpi_put_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op); + + +int ncmpi_put_vars_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op); + + +int ncmpi_put_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op); + + +int ncmpi_put_vars_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op); + + +int ncmpi_put_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op); + + +int ncmpi_put_vars_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op); + + +int ncmpi_put_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_vars_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op); + + +int ncmpi_put_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_vars_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op); + + +int ncmpi_put_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op); + + +int ncmpi_put_vars_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op); + + +int ncmpi_put_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_vars_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip); + + +int ncmpi_get_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_get_vars_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip); + + +int ncmpi_get_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip); + + +int ncmpi_get_vars_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip); + + +int ncmpi_get_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip); + + +int ncmpi_get_vars_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip); + + +int ncmpi_get_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip); + + +int ncmpi_get_vars_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip); + + +int ncmpi_get_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_vars_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip); + + +int ncmpi_get_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_vars_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip); + + +int ncmpi_get_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip); + + +int ncmpi_get_vars_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip); + + +int ncmpi_get_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip); + +/* End {put,get}_vars */ + +/* Begin {put,get}_varm */ + + +int ncmpi_put_varm_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_varm_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_put_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype); + + +int ncmpi_get_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_put_varm_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op); + + +int ncmpi_put_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_varm_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op); + + +int ncmpi_put_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op); + + +int ncmpi_put_varm_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op); + + +int ncmpi_put_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op); + + +int ncmpi_put_varm_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op); + + +int ncmpi_put_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op); + + +int ncmpi_put_varm_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op); + + +int ncmpi_put_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_put_varm_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op); + + +int ncmpi_put_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_put_varm_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op); + + +int ncmpi_put_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op); + + +int ncmpi_put_varm_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op); + + +int ncmpi_put_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_get_varm_uchar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip); + + +int ncmpi_get_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_get_varm_schar_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip); + + +int ncmpi_get_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip); + + +int ncmpi_get_varm_text_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip); + + +int ncmpi_get_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip); + + +int ncmpi_get_varm_short_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip); + + +int ncmpi_get_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip); + + +int ncmpi_get_varm_int_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip); + + +int ncmpi_get_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_get_varm_long_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip); + + +int ncmpi_get_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_get_varm_float_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip); + + +int ncmpi_get_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip); + + +int ncmpi_get_varm_double_all(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip); + + +int ncmpi_get_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip); + +/* End {put,get}_varm */ + +/* End Prototypes */ + +/* #################################################################### */ +/* Begin: more prototypes to be included for fortran binding conversion */ + +#ifdef ENABLE_NONBLOCKING +/* Begin non-blocking data access functions */ + +int +ncmpi_wait(NCMPI_Request *request); + +int +ncmpi_waitall(int count, NCMPI_Request array_of_requests[]); + +int +ncmpi_waitany(int count, NCMPI_Request array_of_requests[], int *index); + +int +ncmpi_waitsome(int count, NCMPI_Request array_of_requests[], + int *outcount, int array_of_indices[]); + +int +ncmpi_test(NCMPI_Request *request, int *flag); + +int +ncmpi_testall(int count, NCMPI_Request array_of_requests[], int *flag); + +int +ncmpi_testany(int count, NCMPI_Request array_of_requests[], + int *index, int *flag); + +int +ncmpi_testsome(int count, NCMPI_Request array_of_requests[], + int *outcount, int array_of_indices[]); + +int +ncmpi_request_get_status(NCMPI_Request request, int *flag); + +int +ncmpi_request_free(NCMPI_Request *request); + +int +ncmpi_cancel(NCMPI_Request *request); + +/* Begin {put,get}_var1 */ + + +int ncmpi_iput_var1(int ncid, int varid, + const MPI_Offset index[], + const void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +int ncmpi_iget_var1(int ncid, int varid, + const MPI_Offset index[], + void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iput_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + const unsigned char *op, NCMPI_Request *request); +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iput_var1_schar(int ncid, int varid, + const MPI_Offset index[], + const signed char *op, NCMPI_Request *request); + + +int ncmpi_iput_var1_text(int ncid, int varid, + const MPI_Offset index[], + const char *op, NCMPI_Request *request); + + +int ncmpi_iput_var1_short(int ncid, int varid, + const MPI_Offset index[], + const short *op, NCMPI_Request *request); + + +int ncmpi_iput_var1_int(int ncid, int varid, + const MPI_Offset index[], + const int *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iput_var1_long(int ncid, int varid, + const MPI_Offset index[], + const long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_var1_float(int ncid, int varid, + const MPI_Offset index[], + const float *op, NCMPI_Request *request); + + +int ncmpi_iput_var1_double(int ncid, int varid, + const MPI_Offset index[], + const double *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iget_var1_uchar(int ncid, int varid, + const MPI_Offset index[], + unsigned char *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iget_var1_schar(int ncid, int varid, + const MPI_Offset index[], + signed char *ip, NCMPI_Request *request); + + +int ncmpi_iget_var1_text(int ncid, int varid, + const MPI_Offset index[], + char *ip, NCMPI_Request *request); + + +int ncmpi_iget_var1_short(int ncid, int varid, + const MPI_Offset index[], + short *ip, NCMPI_Request *request); + + +int ncmpi_iget_var1_int(int ncid, int varid, + const MPI_Offset index[], + int *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_var1_long(int ncid, int varid, + const MPI_Offset index[], + long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_var1_float(int ncid, int varid, + const MPI_Offset index[], + float *ip, NCMPI_Request *request); + + +int ncmpi_iget_var1_double(int ncid, int varid, + const MPI_Offset index[], + double *ip, NCMPI_Request *request); + +/* End {put,get}_var1 */ + +/* Begin {put,get}_var */ + + +int ncmpi_iput_var(int ncid, int varid, const void *buf, int bufcount, MPI_Datatype datatype, NCMPI_Request *request); + + +int ncmpi_iget_var(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iput_var_uchar(int ncid, int varid, const unsigned char *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iput_var_schar(int ncid, int varid, const signed char *op, NCMPI_Request *request); + + +int ncmpi_iput_var_text(int ncid, int varid, const char *op, NCMPI_Request *request); + + +int ncmpi_iput_var_short(int ncid, int varid, const short *op, NCMPI_Request *request); + + +int ncmpi_iput_var_int(int ncid, int varid, const int *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iput_var_long(int ncid, int varid, const long *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_var_float(int ncid, int varid, const float *op, NCMPI_Request *request); + + +int ncmpi_iput_var_double(int ncid, int varid, const double *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iget_var_uchar(int ncid, int varid, unsigned char *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iget_var_schar(int ncid, int varid, signed char *ip, NCMPI_Request *request); + + +int ncmpi_iget_var_text(int ncid, int varid, char *ip, NCMPI_Request *request); + + +int ncmpi_iget_var_short(int ncid, int varid, short *ip, NCMPI_Request *request); + + +int ncmpi_iget_var_int(int ncid, int varid, int *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_var_long(int ncid, int varid, long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_var_float(int ncid, int varid, float *ip, NCMPI_Request *request); + + +int ncmpi_iget_var_double(int ncid, int varid, double *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +/* End Skip Prototypes for Fortran binding */ + + +/* Begin Skip Prototypes for Fortran binding */ +/* End Skip Prototypes for Fortran binding */ + + +/* End {put,get}_var */ + +/* Begin {put,get}_vara */ + + +int ncmpi_iput_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +int ncmpi_iget_vara(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iput_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const unsigned char *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iput_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const signed char *op, NCMPI_Request *request); + + +int ncmpi_iput_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const char *op, NCMPI_Request *request); + + +int ncmpi_iput_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const short *op, NCMPI_Request *request); + + +int ncmpi_iput_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const int *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const long *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const float *op, NCMPI_Request *request); + + +int ncmpi_iput_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + const double *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_vara_uchar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + unsigned char *ip, NCMPI_Request *request); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_vara_schar(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + signed char *ip, NCMPI_Request *request); + + +int ncmpi_iget_vara_text(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + char *ip, NCMPI_Request *request); + + +int ncmpi_iget_vara_short(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + short *ip, NCMPI_Request *request); + + +int ncmpi_iget_vara_int(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + int *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_vara_long(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_vara_float(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + float *ip, NCMPI_Request *request); + + +int ncmpi_iget_vara_double(int ncid, int varid, + const MPI_Offset start[], const MPI_Offset count[], + double *ip, NCMPI_Request *request); + +/* End {put,get}_vara */ + +/* Begin {put,get}_vars */ + + +int ncmpi_iput_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +int ncmpi_iget_vars(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iput_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *op, NCMPI_Request *request); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const signed char *op, NCMPI_Request *request); + + +int ncmpi_iput_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const char *op, NCMPI_Request *request); + + +int ncmpi_iput_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const short *op, NCMPI_Request *request); + + +int ncmpi_iput_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const int *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iput_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const long *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const float *op, NCMPI_Request *request); + + +int ncmpi_iput_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const double *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_vars_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iget_vars_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + signed char *ip, NCMPI_Request *request); + + +int ncmpi_iget_vars_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + char *ip, NCMPI_Request *request); + + +int ncmpi_iget_vars_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + short *ip, NCMPI_Request *request); + + +int ncmpi_iget_vars_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + int *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_vars_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_vars_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + float *ip, NCMPI_Request *request); + + +int ncmpi_iget_vars_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + double *ip, NCMPI_Request *request); + +/* End {put,get}_vars */ + +/* Begin {put,get}_varm */ + + +int ncmpi_iput_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +int ncmpi_iget_varm(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + void *buf, int bufcount, + MPI_Datatype datatype, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ +int ncmpi_iput_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const unsigned char *op, NCMPI_Request *request); +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const signed char *op, NCMPI_Request *request); + + +int ncmpi_iput_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const char *op, NCMPI_Request *request); + + +int ncmpi_iput_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const short *op, NCMPI_Request *request); + + +int ncmpi_iput_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const int *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iput_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const long *op, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iput_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const float *op, NCMPI_Request *request); + + +int ncmpi_iput_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + const double *op, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_varm_uchar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + unsigned char *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + +int ncmpi_iget_varm_schar(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + signed char *ip, NCMPI_Request *request); + + +int ncmpi_iget_varm_text(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + char *ip, NCMPI_Request *request); + + +int ncmpi_iget_varm_short(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + short *ip, NCMPI_Request *request); + + +int ncmpi_iget_varm_int(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + int *ip, NCMPI_Request *request); + + +/* Begin Skip Prototypes for Fortran binding */ + +int ncmpi_iget_varm_long(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + long *ip, NCMPI_Request *request); + +/* End Skip Prototypes for Fortran binding */ + + +int ncmpi_iget_varm_float(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + float *ip, NCMPI_Request *request); + + +int ncmpi_iget_varm_double(int ncid, int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const MPI_Offset imap[], + double *ip, NCMPI_Request *request); + +/* End {put,get}_varm */ + +/* End non-blocking data access functions */ +#endif + +/* End: more prototypes to be included for fortran binding conversion */ +/* ################################################################## */ + + +/* These macros are defined in serial netcdf (3.5.0) for backwards + * compatibility with older netcdf code. We aren't concerned with backwards + * compatibility, so if your code doesn't compile with parallel-netcdf, maybe + * this is why: + * + * + * OLD NAME NEW NAME + * ---------------------------------- + * FILL_BYTE NC_FILL_BYTE + * FILL_CHAR NC_FILL_CHAR + * FILL_SHORT NC_FILL_SHORT + * FILL_LONG NC_FILL_INT + * FILL_FLOAT NC_FILL_FLOAT + * FILL_DOUBLE NC_FILL_DOUBLE + * + * MAX_NC_DIMS NC_MAX_DIMS + * MAX_NC_ATTRS NC_MAX_ATTRS + * MAX_NC_VARS NC_MAX_VARS + * MAX_NC_NAME NC_MAX_NAME + * MAX_VAR_DIMS NC_MAX_VAR_DIMS + */ + +#if defined(__cplusplus) +} +#endif + +#endif /* _NETCDF_ */ Index: /tags/v1-0-3/src/lib/rnd.h =================================================================== --- /tags/v1-0-3/src/lib/rnd.h (revision 2) +++ /tags/v1-0-3/src/lib/rnd.h (revision 2) @@ -0,0 +1,17 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ +#ifndef _RNDUP + +/* useful for aligning memory */ +#define _RNDUP(x, unit) ((((x) + (unit) - 1) / (unit)) \ + * (unit)) +#define _RNDDOWN(x, unit) ((x) - ((x)%(unit))) + +#define M_RND_UNIT (sizeof(double)) +#define M_RNDUP(x) _RNDUP(x, M_RND_UNIT) +#define M_RNDDOWN(x) __RNDDOWN(x, M_RND_UNIT) + +#endif Index: /tags/v1-0-3/src/lib/var.c =================================================================== --- /tags/v1-0-3/src/lib/var.c (revision 617) +++ /tags/v1-0-3/src/lib/var.c (revision 617) @@ -0,0 +1,839 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#include "nc.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include "ncx.h" +#include "rnd.h" + +/* Prototypes for functions used only in this file */ +static size_t ncx_szof(nc_type type); + +/* + * Free var + * Formerly +NC_free_var(var) + */ +void +ncmpii_free_NC_var(NC_var *varp) +{ + if(varp == NULL) + return; + ncmpii_free_NC_attrarrayV(&varp->attrs); + ncmpii_free_NC_string(varp->name); + free(varp); +} + + +/* + * Common code for ncmpii_new_NC_var() + * and ncx_get_NC_var() + */ +NC_var * +ncmpii_new_x_NC_var( + NC_string *strp, + size_t ndims) +{ + NC_var *varp; + const size_t o1 = M_RNDUP(ndims * sizeof(int)); + const size_t o2 = M_RNDUP(ndims * sizeof(size_t)); + const size_t sz = M_RNDUP(sizeof(NC_var)) + + o1 + o2 + ndims * sizeof(size_t); + + varp = (NC_var *) malloc(sz); + if(varp == NULL ) + return NULL; + (void) memset(varp, 0, sz); + + varp->name = strp; + varp->ndims = ndims; + + if(ndims != 0) + { + /* + * NOTE: lint may complain about the next 3 lines: + * "pointer cast may result in improper alignment". + * We use the M_RNDUP() macro to get the proper alignment. + */ + varp->dimids = (int *)((char *)varp + M_RNDUP(sizeof(NC_var))); + varp->shape = (size_t *)((char *)varp->dimids + o1); + varp->dsizes = (size_t *)((char *)varp->shape + o2); + } + + varp->xsz = 0; + varp->len = 0; + varp->begin = 0; + + return varp; +} + + +/* + * Formerly +NC_new_var() + */ +static NC_var * +ncmpii_new_NC_var(const char *name, nc_type type, + size_t ndims, const int *dimids) +{ + NC_string *strp; + NC_var *varp; + + strp = ncmpii_new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + varp = ncmpii_new_x_NC_var(strp, ndims); + if(varp == NULL ) + { + ncmpii_free_NC_string(strp); + return NULL; + } + + varp->type = type; + + if( ndims != 0 && dimids != NULL) + (void) memcpy(varp->dimids, dimids, ndims * sizeof(int)); + + return(varp); +} + + +static NC_var * +dup_NC_var(const NC_var *rvarp) +{ + NC_var *varp = ncmpii_new_NC_var(rvarp->name->cp, rvarp->type, + rvarp->ndims, rvarp->dimids); + if(varp == NULL) + return NULL; + + + if(ncmpii_dup_NC_attrarrayV(&varp->attrs, &rvarp->attrs) != NC_NOERR) + { + ncmpii_free_NC_var(varp); + return NULL; + } + + (void) memcpy(varp->shape, rvarp->shape, + rvarp->ndims * sizeof(size_t)); + (void) memcpy(varp->dsizes, rvarp->dsizes, + rvarp->ndims * sizeof(size_t)); + varp->xsz = rvarp->xsz; + varp->len = rvarp->len; + varp->begin = rvarp->begin; + + return varp; +} + + +/* vararray */ + + +/* + * Free the stuff "in" (referred to by) an NC_vararray. + * Leaves the array itself allocated. + */ +void +ncmpii_free_NC_vararrayV0(NC_vararray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_var **vpp = ncap->value; + NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + ncmpii_free_NC_var(*vpp); + *vpp = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_vararray values. + * formerly +NC_free_array() + */ +void +ncmpii_free_NC_vararrayV(NC_vararray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + ncmpii_free_NC_vararrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +ncmpii_dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_var *); + ncap->value = (NC_var **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_var **vpp = ncap->value; + const NC_var **drpp = (const NC_var **)ref->value; + NC_var *const *const end = &vpp[ref->nelems]; + for( /*NADA*/; vpp < end; drpp++, vpp++, ncap->nelems++) + { + *vpp = dup_NC_var(*drpp); + if(*vpp == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + ncmpii_free_NC_vararrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp) +{ + NC_var **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_var **) malloc(NC_ARRAY_GROWBY * sizeof(NC_var *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_var **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +static NC_var * +elem_NC_vararray(const NC_vararray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long)elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + + +/* End vararray per se */ + + +/* + * Step thru NC_VARIABLE array, seeking match on name. + * Return varid or -1 on not found. + * *varpp is set to the appropriate NC_var. + * Formerly (sort of) +NC_hvarid + */ +int +ncmpii_NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp) +{ + NC_var **loc; + size_t slen; + int varid; + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + loc = (NC_var **) ncap->value; + + slen = strlen(name); + + for(varid = 0; (size_t) varid < ncap->nelems; varid++, loc++) + { + if(strlen((*loc)->name->cp) == slen && + strncmp((*loc)->name->cp, name, slen) == 0) + { + if(varpp != NULL) + *varpp = *loc; + return(varid); /* Normal return */ + } + } + return(-1); /* not found */ +} + +/* + * For a netcdf type + * return the size of one element in the external representation. + * Note that arrays get rounded up to X_ALIGN boundaries. + * Formerly +NC_xtypelen + * See also ncx_len() + */ +static size_t +ncx_szof(nc_type type) +{ + switch(type){ + case NC_BYTE: + case NC_CHAR: + return(1); + case NC_SHORT : + return(2); + case NC_INT: + return X_SIZEOF_INT; + case NC_FLOAT: + return X_SIZEOF_FLOAT; + case NC_DOUBLE : + return X_SIZEOF_DOUBLE; + default: + assert("ncx_szof invalid type" == 0); + } + /* default */ + return 0; +} + + +/* + * 'compile' the shape and len of a variable + * Formerly +ncmpii_NC_var_shape(var, dims) + */ +int +ncmpii_NC_var_shape(NC_var *varp, const NC_dimarray *dims) +{ + size_t *shp, *dsp, *op; + int *ip; + const NC_dim *dimp; + size_t product = 1; + + varp->xsz = ncx_szof(varp->type); + + if(varp->ndims == 0) + { + goto out; + } + + /* + * use the user supplied dimension indices + * to determine the shape + */ + for(ip = varp->dimids, op = varp->shape + ; ip < &varp->dimids[varp->ndims]; ip++, op++) + { + if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) ) + return NC_EBADDIM; + + dimp = ncmpii_elem_NC_dimarray(dims, (size_t)*ip); + *op = dimp->size; + if(*op == NC_UNLIMITED && ip != varp->dimids) + return NC_EUNLIMPOS; + } + + /* + * Compute the dsizes + */ + /* ndims is > 0 here */ + for(shp = varp->shape + varp->ndims -1, + dsp = varp->dsizes + varp->ndims -1; + shp >= varp->shape; + shp--, dsp--) + { + if(!(shp == varp->shape && IS_RECVAR(varp))) + { + if( *shp <= X_UINT_MAX / product) + { + product *= *shp; + } else + { + product = X_UINT_MAX; + } + } + *dsp = product; + } + + +out : + varp->len = product * varp->xsz; + switch(varp->type) { + case NC_BYTE : + case NC_CHAR : + case NC_SHORT : + if( varp->len%4 != 0 ) + { + varp->len += 4 - varp->len%4; /* round up */ + /* *dsp += 4 - *dsp%4; */ + } + break; + default: + /* already aligned */ + break; + } +#if 0 + if (varp->xsz <= (X_UINT_MAX - 1)/ product) /* if int. mult won't overflow */ + { + varp->len = product * varp->xsz; + switch(varp->type) { + case NC_BYTE : + case NC_CHAR : + case NC_SHORT : + if( varp->len%4 != 0 ) + { + varp->len += 4 - varp->len%4; /* round up */ + /* *dsp += 4 - *dsp%4; */ + } + break; + default: + /* already aligned */ + break; + } + } else + { /* ok for last var to be "too big", indicated by this special len */ + varp->len = X_UINT_MAX; + } + arrayp("\tshape", varp->ndims, varp->shape); + arrayp("\tdsizes", varp->ndims, varp->dsizes); +#endif + return NC_NOERR; +} +/* + * Check whether variable size is less than or equal to vlen_max, + * without overflowing in arithmetic calculations. If OK, return 1, + * else, return 0. For CDF1 format or for CDF2 format on non-LFS + * platforms, vlen_max should be 2^31 - 4, but for CDF2 format on + * systems with LFS it should be 2^32 - 4. + */ +int +ncmpii_NC_check_vlen(NC_var *varp, size_t vlen_max) { + size_t prod=varp->xsz; /* product of xsz and dimensions so far */ + + int ii; + + for(ii = IS_RECVAR(varp) ? 1 : 0; ii < varp->ndims; ii++) { + if (varp->shape[ii] > vlen_max / prod) { + return 0; /* size in bytes won't fit in a 32-bit int */ + } + prod *= varp->shape[ii]; + } + return 1; /* OK */ +} + +/* + * Given valid ncp and varid, return var + * else NULL on error + * Formerly +NC_hlookupvar() + */ +NC_var * +ncmpii_NC_lookupvar(NC *ncp, int varid) +{ + NC_var *varp; + + if(varid == NC_GLOBAL) + { + /* Global is error in this context */ + return(NULL); + } + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + { + return NULL; + } + + assert(varp != NULL); + + return(varp); +} + + +/* Public */ + +int +ncmpi_def_var( int ncid, const char *name, nc_type type, + int ndims, const int *dimids, int *varidp) +{ + int status; + NC *ncp; + int varid; + NC_var *varp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + { + return NC_ENOTINDEFINE; + } + + status = ncmpii_NC_check_name(name); + if(status != NC_NOERR) + return status; + + status = ncmpii_cktype(type); + if(status != NC_NOERR) + return status; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) ndims > X_INT_MAX) /* Backward compat */ + { + return NC_EINVAL; + } + + if(ncp->vars.nelems >= NC_MAX_VARS) + { + return NC_EMAXVARS; + } + + varid = ncmpii_NC_findvar(&ncp->vars, name, &varp); + if(varid != -1) + { + return NC_ENAMEINUSE; + } + + varp = ncmpii_new_NC_var(name, type, ndims, dimids); + if(varp == NULL) + return NC_ENOMEM; + + status = ncmpii_NC_var_shape(varp, &ncp->dims); + if(status != NC_NOERR) + { + ncmpii_free_NC_var(varp); + return status; + } + + status = incr_NC_vararray(&ncp->vars, varp); + if(status != NC_NOERR) + { + ncmpii_free_NC_var(varp); + return status; + } + + if(varidp != NULL) + *varidp = (int)ncp->vars.nelems -1; /* varid */ + return NC_NOERR; +} + + +int +ncmpi_inq_varid(int ncid, const char *name, int *varid_ptr) +{ + int status; + NC *ncp; + NC_var *varp; + int varid; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varid = ncmpii_NC_findvar(&ncp->vars, name, &varp); + if(varid == -1) + { + return NC_ENOTVAR; + } + + *varid_ptr = varid; + return NC_NOERR; +} + + +int +ncmpi_inq_var(int ncid, + int varid, + char *name, + nc_type *typep, + int *ndimsp, + int *dimids, + int *nattsp) +{ + int status; + NC *ncp; + NC_var *varp; + size_t ii; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(name != NULL) + { + (void) strncpy(name, varp->name->cp, varp->name->nchars); + name[varp->name->nchars] = 0; + } + + if(typep != 0) + *typep = varp->type; + if(ndimsp != 0) + { + *ndimsp = (int) varp->ndims; + } + if(dimids != 0) + { + for(ii = 0; ii < varp->ndims; ii++) + { + dimids[ii] = varp->dimids[ii]; + } + } + if(nattsp != 0) + { + *nattsp = (int) varp->attrs.nelems; + } + + return NC_NOERR; +} + + +int +ncmpi_inq_varname(int ncid, int varid, char *name) +{ + int status; + NC *ncp; + NC_var *varp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(name != NULL) + { + (void) strncpy(name, varp->name->cp, varp->name->nchars); + name[varp->name->nchars] = 0; + } + + return NC_NOERR; +} + +int +ncmpi_inq_vartype(int ncid, int varid, nc_type *typep) +{ + int status; + NC *ncp; + NC_var *varp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(typep != 0) + *typep = varp->type; + + return NC_NOERR; +} + +int +ncmpi_inq_varndims(int ncid, int varid, int *ndimsp) +{ + int status; + NC *ncp; + NC_var *varp; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(ndimsp != 0) + { + *ndimsp = (int) varp->ndims; + } + + return NC_NOERR; +} + + +int +ncmpi_inq_vardimid(int ncid, int varid, int *dimids) +{ + int status; + NC *ncp; + NC_var *varp; + size_t ii; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(dimids != 0) + { + for(ii = 0; ii < varp->ndims; ii++) + { + dimids[ii] = varp->dimids[ii]; + } + } + + return NC_NOERR; +} + + +int +ncmpi_inq_varnatts(int ncid, int varid, int *nattsp) +{ + int status; + NC *ncp; + NC_var *varp; + + if(varid == NC_GLOBAL) + return ncmpi_inq_natts(ncid, nattsp); + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(nattsp != 0) + { + *nattsp = (int) varp->attrs.nelems; + } + + return NC_NOERR; +} + +int +ncmpi_rename_var(int ncid, int varid, const char *newname) +{ + int status; + NC *ncp; + NC_var *varp; + NC_string *old, *newStr; + int other; + + status = ncmpii_NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + { + return NC_EPERM; + } + + status = ncmpii_NC_check_name(newname); + if(status != NC_NOERR) + return status; + + /* check for name in use */ + other = ncmpii_NC_findvar(&ncp->vars, newname, &varp); + if(other != -1) + { + return NC_ENAMEINUSE; + } + + varp = ncmpii_NC_lookupvar(ncp, varid); + if(varp == NULL) + { + /* invalid varid */ + return NC_ENOTVAR; /* TODO: is this the right error code? */ + } + + old = varp->name; + if(NC_indef(ncp)) + { + newStr = ncmpii_new_NC_string(strlen(newname),newname); + if(newStr == NULL) + return(-1); + varp->name = newStr; + ncmpii_free_NC_string(old); + return NC_NOERR; + } + + /* else, not in define mode */ + status = ncmpii_set_NC_string(varp->name, newname); + if(status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = ncmpii_NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} Index: /tags/v1-0-3/src/lib/error.c =================================================================== --- /tags/v1-0-3/src/lib/error.c (revision 531) +++ /tags/v1-0-3/src/lib/error.c (revision 531) @@ -0,0 +1,196 @@ +/* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: error.c,v 1.14 90/02/23 16:08:55 davis Exp */ + +/*LINTLIBRARY*/ + +#include "ncconfig.h" + +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include "pnetcdf.h" +#include "nc.h" + +#ifndef NO_STRERROR +#include /* contains prototype for ansi libc function strerror() */ +#else +/* provide a strerror function for older unix systems */ +static char * +strerror(int errnum) +{ + extern int sys_nerr; + extern char *sys_errlist[]; + + if(errnum < 0 || errnum >= sys_nerr) return NULL; + /* else */ + return sys_errlist[errnum]; +} +#endif /* NO_STRERROR */ + + +#ifdef vms +/* UNTESTED */ +/* + * On the vms system, when a system error occurs which is not + * mapped into the unix styled errno values, errno is set EVMSERR + * and a VMS error code is set in vaxc$errno. + * This routine prints the systems message associated with status return + * from a system services call. + */ + +#include +#include +#include + +static const char * +vms_strerror( int status ) +{ + short msglen; + static char msgbuf[256]; + $DESCRIPTOR(message, msgbuf); + register ret; + + msgbuf[0] = 0; + ret = SYS$GETMSG(status, &msglen, &message, 15, 0); + + if(ret != SS$_BUFFEROVF && ret != SS$_NORMAL) { + (void) strcpy(msgbuf, "EVMSERR"); + } + return(msgbuf); +} +#endif /* vms */ + + +static char unknown[] = "Unknown Error"; + + +const char * +ncmpi_strerror(int err) +{ + +#ifdef vms + if(err == EVMSERR) + { + return vms_strerror(err); + } + /* else */ +#endif /* vms */ + + if(NC_ISSYSERR(err)) + { + const char *cp = (const char *) strerror(err); + if(cp == NULL) + return unknown; + /* else */ + return cp; + } + /* else */ + + switch (err) { + case NC_NOERR: + return "No error"; + case NC_ESMALL: + return "Size of off_t too small for requested format "; + case NC_ENOTINDEP: + return "Operation not allowed in collective data mode"; + case NC_EINDEP: + return "Operation not allowed in independent data mode"; + case NC_EFILE: + return "Unknown error in file operation"; + case NC_EREAD: + return "Unknow error occurs in reading file"; + case NC_EWRITE: + return "Unknow error occurs in writting file"; + case NC_EMULTIDEFINE: + return "NC definations on multiprocesses conflict. \nNOTE: Definitions across all processes must agree with one another"; + case NC_EOFILE: + return "Can not open/create file"; + case NC_EBADID: + return "Not a netCDF id"; + case NC_ENFILE: + return "Too many netCDF files open"; + case NC_EEXIST: + return "netCDF file exists && NC_NOCLOBBER"; + case NC_EINVAL: + return "Invalid argument"; + case NC_EPERM: + return "Write to read only"; + case NC_ENOTINDEFINE: + return "Operation not allowed in data mode"; + case NC_EINDEFINE: + return "Operation not allowed in define mode"; + case NC_EINVALCOORDS: + return "Index exceeds dimension bound"; + case NC_EMAXDIMS: + return "NC_MAX_DIMS exceeded"; + case NC_ENAMEINUSE: + return "String match to name in use"; + case NC_ENOTATT: + return "Attribute not found"; + case NC_EMAXATTS: + return "NC_MAX_ATTRS exceeded"; + case NC_EBADTYPE: + return "Not a netCDF data type or _FillValue type mismatch"; + case NC_EBADDIM: + return "Invalid dimension id or name"; + case NC_EUNLIMPOS: + return "NC_UNLIMITED in the wrong index"; + case NC_EMAXVARS: + return "NC_MAX_VARS exceeded"; + case NC_ENOTVAR: + return "Variable not found"; + case NC_EGLOBAL: + return "Action prohibited on NC_GLOBAL varid"; + case NC_ENOTNC: + return "Not a netCDF file"; + case NC_ESTS: + return "In Fortran, string too short"; + case NC_EMAXNAME: + return "NC_MAX_NAME exceeded"; + case NC_EUNLIMIT: + return "NC_UNLIMITED size already in use"; + case NC_ENORECVARS: + return "nc_rec op when there are no record vars"; + case NC_ECHAR: + return "Attempt to convert between text & numbers"; + case NC_EEDGE: + return "Edge+start exceeds dimension bound"; + case NC_ESTRIDE: + return "Illegal stride"; + case NC_EBADNAME: + return "Attribute or variable name contains illegal characters"; + case NC_ERANGE: + return "Numeric conversion not representable"; + case NC_ENOMEM: + return "Memory allocation (malloc) failure"; + case NC_EVARSIZE: + return "One or more variable sizes violate format constraints"; + case NC_EDIMSIZE: + return "Invalid dimension size"; + case NC_EMULTITYPES: + return "Multiple types used in memory data"; + case NC_EIOMISMATCH: + return "Input/Output data amount mismatch"; + case NC_ENEGATIVECNT: + return "Negative count is prohibited"; + case NC_EUNSPTETYPE: + return "Unsupported etype is used in MPI datatype for memory data"; + default: + return unknown; + } + /* default */ + return unknown; +} + +void ncmpii_handle_error(int rank, int mpi_status, char * msg) +{ + char errorString[MPI_MAX_ERROR_STRING]; + int errorStringLen; + MPI_Error_string(mpi_status, errorString, &errorStringLen); + printf("%2d: %s : %s\n", rank, msg, errorString); +} Index: /tags/v1-0-3/src/lib/nctypes.h =================================================================== --- /tags/v1-0-3/src/lib/nctypes.h (revision 515) +++ /tags/v1-0-3/src/lib/nctypes.h (revision 515) @@ -0,0 +1,23 @@ +/***************************************************************************** + * + * This file is created by Northwestern University and Argonne National + * Laboratory + * + ****************************************************************************/ + +#ifndef NCTYPES_H +#define NCTYPES_H + +#ifndef HAVE_PTRDIFF_T +typedef int ptrdiff_t; +#endif + +#ifndef HAVE_SSIZE_T +typedef int ssize_t; +#endif + +#ifndef HAVE_UCHAR +typedef unsigned char uchar; +#endif + +#endif Index: /tags/v1-0-3/src/lib/ncio.h =================================================================== --- /tags/v1-0-3/src/lib/ncio.h (revision 568) +++ /tags/v1-0-3/src/lib/ncio.h (revision 568) @@ -0,0 +1,167 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id$ */ + +#ifndef _NCIO_H_ +#define _NCIO_H_ + +#include /* size_t */ +#include /* off_t */ +#include "pnetcdf.h" + +#include +#ifdef HAVE_MPIO_H +#include +#endif + +typedef struct ncio ncio; /* forward reference */ + +/* + * A value which is an invalid off_t + */ +#define OFF_NONE ((off_t)(-1)) + +/* + * Flags used by the region layer, + * 'rflags' argument to ncio.rel() and ncio.get(). + */ +#define RGN_NOLOCK 0x1 /* Don't lock region. + * Used when contention control handled + * elsewhere. + */ +#define RGN_NOWAIT 0x2 /* return immediate if can't lock, else wait */ + +#define RGN_WRITE 0x4 /* we intend to modify, else read only */ + +#define RGN_MODIFIED 0x8 /* we did modify, else, discard */ + + +/* + * The next four typedefs define the signatures + * of function pointers in struct ncio below. + * They are not used outside of this file and ncio.h, + * They just some casts in the ncio.c more readable. + */ + /* + * Indicate that you are done with the region which begins + * at offset. Only reasonable flag value is RGN_MODIFIED. + */ +typedef int ncmpiio_relfunc(ncio *const nciop, + off_t offset, int rflags); + + /* + * Request that the region (offset, extent) + * be made available through *vpp. + */ +typedef int ncmpiio_getfunc(ncio *const nciop, + off_t offset, size_t extent, + int rflags, + void **const vpp); + + /* + * Like memmove(), safely move possibly overlapping data. + * Only reasonable flag value is RGN_NOLOCK. + */ +typedef int ncmpiio_movefunc(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags); + + /* + * Write out any dirty buffers to disk and + * ensure that next read will get data from disk. + */ +typedef int ncmpiio_syncfunc(ncio *const nciop); + + /* + * Don't call this. + * Internal function called at close to + * free up anything hanging off pvt; + */ +typedef void ncmpiio_freefunc(void *const pvt); + +/* Get around cplusplus "const xxx in class ncio without constructor" error */ +#if defined(__cplusplus) +#define NCIO_CONST +#else +#define NCIO_CONST const +#endif + +/* + * netcdf i/o abstraction + */ +struct ncio { + /* + * A copy of the ioflags argument passed in to ncmpiio_open() + * or ncmpiio_create(). + */ + int ioflags; + + /* + * The file descriptor of the netcdf file. + * This gets handed to the user as the netcdf id. + */ + NCIO_CONST int fd; + + /* + * The MPI File handle and the communicator + * Added by Jianwei Li + */ +#define MPI_COLLECTIVE_FH 2 +#define MPI_INDEPENDENT_FH 8 + +#define NC_collectiveFhOpened(nciop) \ + (fIsSet(nciop->mpioflags, MPI_COLLECTIVE_FH)) + +#define NC_independentFhOpened(nciop) \ + (fIsSet(nciop->mpioflags, MPI_INDEPENDENT_FH)) + +#define set_NC_collectiveFh(nciop) \ + fSet((nciop)->mpioflags, MPI_COLLECTIVE_FH) + +#define set_NC_independentFh(nciop) \ + fSet((nciop)->mpioflags, MPI_INDEPENDENT_FH) + + char* filename; + MPI_File collective_fh; + MPI_File independent_fh; + int mpiomode; + MPI_Comm comm; + MPI_Info mpiinfo; + int mpioflags; + + /* member functions do the work */ + + ncmpiio_relfunc *NCIO_CONST rel; + + ncmpiio_getfunc *NCIO_CONST get; + + ncmpiio_movefunc *NCIO_CONST move; + + ncmpiio_syncfunc *NCIO_CONST sync; + + ncmpiio_freefunc *NCIO_CONST free; /* Implementation private */ + + /* + * A copy of the 'path' argument passed in to ncmpiio_open() + * or ncmpiio_create(). Used by ncabort() to remove (unlink) + * the file and by error messages. + */ + const char *path; + + /* implementation private stuff */ + void *NCIO_CONST pvt; +}; + +#undef NCIO_CONST + +extern ncio * +ncmpiio_new(const char *path, int ioflags); + +extern void +ncmpiio_free(ncio *nciop); + +extern int +ncmpiio_close(ncio *nciop, int doUnlink); + +#endif /* _NCIO_H_ */ Index: /tags/v1-0-3/src/lib/ncx.h =================================================================== --- /tags/v1-0-3/src/lib/ncx.h (revision 566) +++ /tags/v1-0-3/src/lib/ncx.h (revision 566) @@ -0,0 +1,663 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* "$Id$" */ + +#ifndef _NCX_H_ +#define _NCX_H_ + +/* + * An external data representation interface. + * + * This started out as a general replacement for ONC XDR, + * specifically, the xdrmem family of functions. + * + * We eventually realized that we could write more portable + * code if we decoupled any association between the 'C' types + * and the external types. (XDR has this association between the 'C' + * types and the external representations, like xdr_int() takes + * an int argument and goes to an external int representation.) + * So, now there is a matrix of functions. + * + */ + +#include "ncconfig.h" /* output of 'configure' */ +#include "rnd.h" +#include /* size_t */ +#include +#include /* off_t */ +#include +#include +#include "nctypes.h" + +#include +#ifdef HAVE_MPIO_H +#include +#endif + +/* + * The integer return code for the conversion routines + * is 0 (ENOERR) when no error occured, or NC_ERANGE as appropriate + * for an overflow conversion. + */ +#ifndef ENOERR +#define ENOERR 0 +#endif +#ifndef NC_ERANGE +#define NC_ERANGE (-60) /* N.B. must match value in pnetcdf.h */ +#endif +#ifndef NC_ENOMEM +#define NC_ENOMEM (-61) /* N.B. must match value in pnetcdf.h */ +#endif + + +/* + * External sizes of the primitive elements. + */ +#define X_SIZEOF_CHAR 1 +#define X_SIZEOF_SHORT 2 +#define X_SIZEOF_INT 4 /* xdr_int */ +#if 0 +#define X_SIZEOF_LONG 8 */ /* xdr_long_long */ +#endif +#define X_SIZEOF_FLOAT 4 +#define X_SIZEOF_DOUBLE 8 + +/* + * For now, netcdf is limited to 32 bit sizes. + * If compiled with support for "large files" then + * netcdf will use a 64 bit off_t and it can then write a file + * using 64 bit offsets. + * see also X_SIZE_MAX, X_OFF_MAX below + */ +#define X_SIZEOF_OFF_T (sizeof(off_t)) +#define X_SIZEOF_SIZE_T X_SIZEOF_INT + +/* + * limits of the external representation + * we rely on ANSI-C defined constants in limits.h. Do any modern environments + * not have these? + */ +#define X_SCHAR_MIN SCHAR_MIN +#define X_SCHAR_MAX SCHAR_MAX +#define X_UCHAR_MAX UCHAR_MAX +#define X_SHORT_MIN SHRT_MIN +#define X_SHRT_MIN X_SHORT_MIN /* alias compatible with limits.h */ +#define X_SHORT_MAX SHRT_MAX +#define X_SHRT_MAX X_SHORT_MAX /* alias compatible with limits.h */ +#define X_USHORT_MAX USHRT_MAX +#define X_USHRT_MAX X_USHORT_MAX /* alias compatible with limits.h */ +#define X_INT_MIN INT_MIN +#define X_INT_MAX INT_MAX +#define X_UINT_MAX UINT_MAX +#if 0 +#define X_LONG_MIN (-2147483647-1) +#define X_LONG_MAX 2147483647 +#define X_ULONG_MAX 4294967295U +#endif +#define X_FLOAT_MAX FLT_MAX +#define X_FLOAT_MIN -(FLT_MAX) +#define X_FLT_MAX X_FLOAT_MAX /* alias compatible with limits.h */ +/* scalb(1. - scalb(.5 , -52), 1024) */ +#define X_DOUBLE_MAX DBL_MAX +#define X_DOUBLE_MIN -(DBL_MAX) +#define X_DBL_MAX X_DOUBLE_MAX /* alias compatible with limits.h */ + +#define X_SIZE_MAX X_UINT_MAX +#define X_OFF_MAX X_INT_MAX + + +/* Begin ncx_len */ + +/* + * ncx_len_xxx() interfaces are defined as macros below, + * These give the length of an array of nelems of the type. + * N.B. The 'char' and 'short' interfaces give the X_ALIGNED length. + */ +#define X_ALIGN 4 /* a.k.a. BYTES_PER_XDR_UNIT */ + +#define ncmpix_len_char(nelems) \ + _RNDUP((nelems), X_ALIGN) + +#define ncmpix_len_short(nelems) \ + (((nelems) + (nelems)%2) * X_SIZEOF_SHORT) + +#define ncmpix_len_int(nelems) \ + ((nelems) * X_SIZEOF_INT) + +#define ncmpix_len_long(nelems) \ + ((nelems) * X_SIZEOF_LONG) + +#define ncmpix_len_float(nelems) \ + ((nelems) * X_SIZEOF_FLOAT) + +#define ncmpix_len_double(nelems) \ + ((nelems) * X_SIZEOF_DOUBLE) + +/* End ncx_len */ + +#ifdef __CHAR_UNSIGNED__ + /* 'char' is unsigned, declare ncbyte as 'signed char' */ +typedef signed char schar; + +#else + /* 'char' is signed */ +typedef signed char schar; + +#endif /* __CHAR_UNSIGNED__ */ + +/* + * Primitive numeric conversion functions. + * The `put' functions convert from native internal + * type to the external type, while the `get' functions + * convert from the external to the internal. + * + * These take the form + * int ncx_get_{external_type}_{internal_type}( + * const void *xp, + * internal_type *ip + * ); + * int ncx_put_{external_type}_{internal_type}( + * void *xp, + * const internal_type *ip + * ); + * where + * `external_type' and `internal_type' chosen from + schar + uchar + short + ushort + int + uint + long + ulong + float + double + * + * Not all combinations make sense. + * We may not implement all combinations that make sense. + * The netcdf functions that use this ncx interface don't + * use these primitive conversion functions. They use the + * aggregate conversion functions declared below. + * + * Storage for a single element of external type is at the `void * xp' + * argument. + * + * Storage for a single element of internal type is at `ip' argument. + * + * These functions return 0 (ENOERR) when no error occured, + * or NC_ERANGE when the value being converted is too large. + * When NC_ERANGE occurs, an undefined (implementation dependent) + * conversion may have occured. + * + * Note that loss of precision may occur silently. + * + */ + +#if 0 +extern int +ncmpix_get_schar_schar(const void *xp, schar *ip); +extern int +ncmpix_get_schar_uchar(const void *xp, uchar *ip); +extern int +ncmpix_get_schar_short(const void *xp, short *ip); +extern int +ncmpix_get_schar_int(const void *xp, int *ip); +extern int +ncmpix_get_schar_long(const void *xp, long *ip); +extern int +ncmpix_get_schar_float(const void *xp, float *ip); +extern int +ncmpix_get_schar_double(const void *xp, double *ip); + +extern int +ncmpix_put_schar_schar(void *xp, const schar *ip); +extern int +ncmpix_put_schar_uchar(void *xp, const uchar *ip); +extern int +ncmpix_put_schar_short(void *xp, const short *ip); +extern int +ncmpix_put_schar_int(void *xp, const int *ip); +extern int +ncmpix_put_schar_long(void *xp, const long *ip); +extern int +ncmpix_put_schar_float(void *xp, const float *ip); +extern int +ncmpix_put_schar_double(void *xp, const double *ip); +#endif + + +extern int +ncmpix_get_short_schar(const void *xp, schar *ip); +extern int +ncmpix_get_short_uchar(const void *xp, uchar *ip); +extern int +ncmpix_get_short_short(const void *xp, short *ip); +extern int +ncmpix_get_short_int(const void *xp, int *ip); +extern int +ncmpix_get_short_long(const void *xp, long *ip); +extern int +ncmpix_get_short_float(const void *xp, float *ip); +extern int +ncmpix_get_short_double(const void *xp, double *ip); + +extern int +ncmpix_put_short_schar(void *xp, const schar *ip); +extern int +ncmpix_put_short_uchar(void *xp, const uchar *ip); +extern int +ncmpix_put_short_short(void *xp, const short *ip); +extern int +ncmpix_put_short_int(void *xp, const int *ip); +extern int +ncmpix_put_short_long(void *xp, const long *ip); +extern int +ncmpix_put_short_float(void *xp, const float *ip); +extern int +ncmpix_put_short_double(void *xp, const double *ip); + + +extern int +ncmpix_get_int_schar(const void *xp, schar *ip); +extern int +ncmpix_get_int_uchar(const void *xp, uchar *ip); +extern int +ncmpix_get_int_short(const void *xp, short *ip); +extern int +ncmpix_get_int_int(const void *xp, int *ip); +extern int +ncmpix_get_int_long(const void *xp, long *ip); +extern int +ncmpix_get_int_float(const void *xp, float *ip); +extern int +ncmpix_get_int_double(const void *xp, double *ip); + +extern int +ncmpix_put_int_schar(void *xp, const schar *ip); +extern int +ncmpix_put_int_uchar(void *xp, const uchar *ip); +extern int +ncmpix_put_int_short(void *xp, const short *ip); +extern int +ncmpix_put_int_int(void *xp, const int *ip); +extern int +ncmpix_put_int_long(void *xp, const long *ip); +extern int +ncmpix_put_int_float(void *xp, const float *ip); +extern int +ncmpix_put_int_double(void *xp, const double *ip); + + +extern int +ncmpix_get_float_schar(const void *xp, schar *ip); +extern int +ncmpix_get_float_uchar(const void *xp, uchar *ip); +extern int +ncmpix_get_float_short(const void *xp, short *ip); +extern int +ncmpix_get_float_int(const void *xp, int *ip); +extern int +ncmpix_get_float_long(const void *xp, long *ip); +extern int +ncmpix_get_float_float(const void *xp, float *ip); +extern int +ncmpix_get_float_double(const void *xp, double *ip); + +extern int +ncmpix_put_float_schar(void *xp, const schar *ip); +extern int +ncmpix_put_float_uchar(void *xp, const uchar *ip); +extern int +ncmpix_put_float_short(void *xp, const short *ip); +extern int +ncmpix_put_float_int(void *xp, const int *ip); +extern int +ncmpix_put_float_long(void *xp, const long *ip); +extern int +ncmpix_put_float_float(void *xp, const float *ip); +extern int +ncmpix_put_float_double(void *xp, const double *ip); + + +extern int +ncmpix_get_double_schar(const void *xp, schar *ip); +extern int +ncmpix_get_double_uchar(const void *xp, uchar *ip); +extern int +ncmpix_get_double_short(const void *xp, short *ip); +extern int +ncmpix_get_double_int(const void *xp, int *ip); +extern int +ncmpix_get_double_long(const void *xp, long *ip); +extern int +ncmpix_get_double_float(const void *xp, float *ip); +extern int +ncmpix_get_double_double(const void *xp, double *ip); + +extern int +ncmpix_put_double_schar(void *xp, const schar *ip); +extern int +ncmpix_put_double_uchar(void *xp, const uchar *ip); +extern int +ncmpix_put_double_short(void *xp, const short *ip); +extern int +ncmpix_put_double_int(void *xp, const int *ip); +extern int +ncmpix_put_double_long(void *xp, const long *ip); +extern int +ncmpix_put_double_float(void *xp, const float *ip); +extern int +ncmpix_put_double_double(void *xp, const double *ip); + + +/* + * Other primitive conversion functions + * N.B. slightly different interface + * Used by netcdf. + */ + +/* ncx_get_int_size_t */ +extern int +ncmpix_get_size_t(const void **xpp, size_t *ulp); +/* ncx_get_int_off_t */ +extern int +ncmpix_get_off_t(const void **xpp, MPI_Offset *lp, size_t sizeof_off_t); + +/* ncx_put_int_size_t */ +extern int +ncmpix_put_size_t(void **xpp, const size_t *ulp); +/* ncx_put_int_off_t */ +extern int +ncmpix_put_off_t(void **xpp, const MPI_Offset *lp, size_t sizeof_off_t); + + +/* + * Aggregate numeric conversion functions. + * Convert an array. Replaces xdr_array(...). + * These functions are used by netcdf. Unlike the xdr + * interface, we optimize for aggregate conversions. + * This functions should be implemented to take advantage + * of multiple processor / parallel hardware where available. + * + * These take the form + * int ncx_getn_{external_type}_{internal_type}( + * const void *xpp, + * size_t nelems, + * internal_type *ip + * ); + * int ncx_putn_{external_type}_{internal_type}( + * void **xpp, + * size_t nelems, + * const internal_type *ip + * ); + * Where the types are as in the primitive numeric conversion functions. + * + * The value of the pointer to pointer argument, *xpp, is + * expected to reference storage for `nelems' of the external + * type. On return, it modified to reference just past the last + * converted external element. + * + * The types whose external size is less than X_ALIGN also have `pad' + * interfaces. These round (and zero fill on put) *xpp up to X_ALIGN + * boundaries. (This is the usual xdr behavior.) + * + * The `ip' argument should point to an array of `nelems' of + * internal_type. + * + * Range errors (NC_ERANGE) for a individual values in the array + * DO NOT terminate the array conversion. All elements are converted, + * with some having undefined values. + * If any range error occurs, the function returns NC_ERANGE. + * + */ + +extern int +ncmpix_getn_schar_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_getn_schar_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_getn_schar_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_getn_schar_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_getn_schar_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_getn_schar_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_pad_getn_schar_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_pad_getn_schar_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_pad_getn_schar_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_pad_getn_schar_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_pad_getn_schar_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_putn_schar_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_putn_schar_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_putn_schar_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_putn_schar_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_putn_schar_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_putn_schar_double(void **xpp, size_t nelems, const double *ip); + +extern int +ncmpix_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_pad_putn_schar_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_pad_putn_schar_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_pad_putn_schar_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_pad_putn_schar_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_pad_putn_schar_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncmpix_getn_short_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_getn_short_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_getn_short_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_getn_short_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_getn_short_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_getn_short_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_pad_getn_short_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_pad_getn_short_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_pad_getn_short_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_pad_getn_short_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_pad_getn_short_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_pad_getn_short_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_putn_short_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_putn_short_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_putn_short_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_putn_short_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_putn_short_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_putn_short_double(void **xpp, size_t nelems, const double *ip); + +extern int +ncmpix_pad_putn_short_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_pad_putn_short_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_pad_putn_short_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_pad_putn_short_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_pad_putn_short_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_pad_putn_short_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncmpix_getn_int_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_getn_int_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_getn_int_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_getn_int_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_getn_int_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_getn_int_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_getn_int_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_putn_int_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_putn_int_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_putn_int_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_putn_int_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_putn_int_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_putn_int_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_putn_int_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncmpix_getn_float_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_getn_float_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_getn_float_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_getn_float_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_getn_float_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_getn_float_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_getn_float_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_putn_float_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_putn_float_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_putn_float_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_putn_float_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_putn_float_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_putn_float_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_putn_float_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncmpix_getn_double_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncmpix_getn_double_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncmpix_getn_double_short(const void **xpp, size_t nelems, short *ip); +extern int +ncmpix_getn_double_int(const void **xpp, size_t nelems, int *ip); +extern int +ncmpix_getn_double_long(const void **xpp, size_t nelems, long *ip); +extern int +ncmpix_getn_double_float(const void **xpp, size_t nelems, float *ip); +extern int +ncmpix_getn_double_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncmpix_putn_double_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncmpix_putn_double_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncmpix_putn_double_short(void **xpp, size_t nelems, const short *ip); +extern int +ncmpix_putn_double_int(void **xpp, size_t nelems, const int *ip); +extern int +ncmpix_putn_double_long(void **xpp, size_t nelems, const long *ip); +extern int +ncmpix_putn_double_float(void **xpp, size_t nelems, const float *ip); +extern int +ncmpix_putn_double_double(void **xpp, size_t nelems, const double *ip); + + +/* + * Other aggregate conversion functions. + */ + +/* read ASCII characters */ +extern int +ncmpix_getn_text(const void **xpp, size_t nchars, char *cp); +extern int +ncmpix_pad_getn_text(const void **xpp, size_t nchars, char *cp); + +/* write ASCII characters */ +extern int +ncmpix_putn_text(void **xpp, size_t nchars, const char *cp); +extern int +ncmpix_pad_putn_text(void **xpp, size_t nchars, const char *cp); + +/* for symmetry */ +#define ncmpix_getn_char_char(xpp, nelems, fillp) ncmpix_getn_text(xpp, nelems, fillp) +#define ncmpix_putn_char_char(xpp, nelems, fillp) ncmpix_putn_text(xpp, nelems, fillp) + +/* read opaque data */ +extern int +ncmpix_getn_void(const void **xpp, size_t nchars, void *vp); +extern int +ncmpix_pad_getn_void(const void **xpp, size_t nchars, void *vp); + +/* write opaque data */ +extern int +ncmpix_putn_void(void **xpp, size_t nchars, const void *vp); +extern int +ncmpix_pad_putn_void(void **xpp, size_t nchars, const void *vp); + +#endif /* _NCX_H_ */ Index: /tags/v1-0-3/src/libf/put_varm_int1f.c =================================================================== --- /tags/v1-0-3/src/libf/put_varm_int1f.c (revision 451) +++ /tags/v1-0-3/src/libf/put_varm_int1f.c (revision 451) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_varm_int1_ NFMPI_PUT_VARM_INT1 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_varm_int1_ nfmpi_put_varm_int1__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_varm_int1_ nfmpi_put_varm_int1 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_varm_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], const signed char * v7 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li +#include "pnetcdf.h" + +/* Support Windows extension to specify calling convention */ +#ifdef USE_FORT_STDCALL +#define FORT_CALL __stdcall +#elif defined (USE_FORT_CDECL) +#define FORT_CALL __cdecl +#else +#define FORT_CALL +#endif + +/* Handle different mechanisms for passing Fortran CHARACTER to routines */ +#ifdef USE_FORT_MIXED_STR_LEN +#define FORT_MIXED_LEN_DECL , MPI_Fint +#define FORT_END_LEN_DECL +#define FORT_MIXED_LEN(a) , MPI_Fint a +#define FORT_END_LEN(a) +#else +#define FORT_MIXED_LEN_DECL +#define FORT_END_LEN_DECL , MPI_Fint +#define FORT_MIXED_LEN(a) +#define FORT_END_LEN(a) , MPI_Fint a +#endif + +/* Support Windows extension to specify which functions are exported from + shared (DLL) libraries */ +#ifdef HAVE_FORTRAN_API +# ifdef FORTRAN_EXPORTS +# define FORTRAN_API __declspec(dllexport) +# else +# define FORTRAN_API __declspec(dllimport) +# endif +#else +# define FORTRAN_API +#endif + +/* Support an alternate approach for declaring a weak symbol supported by + some versions of gcc */ +#ifdef USE_WEAK_ATTRIBUTE +#define FUNC_ATTRIBUTES(name) __attribute__ ((weak,alias(#name))) +#else +#define FUNC_ATTRIBUTES(name) +#endif + +/* Utility functions */ +int ncmpixVardim( int, int ); + +extern FORTRAN_API int FORT_CALL nfmpi_xstrerror_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2) FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_xinq_libvers_ ( char *v1 FORT_MIXED_LEN(d1) FORT_END_LEN(d1) ); +extern FORTRAN_API int FORT_CALL nfmpi_issyserr_ ( MPI_Fint *v1 ); +/* Define the internal values needed for Fortran support */ + +/* Fortran logicals */ + +/* Fortran logical values */ + +#endif + + + + Index: /tags/v1-0-3/src/libf/put_varm_text_allf.c =================================================================== --- /tags/v1-0-3/src/libf/put_varm_text_allf.c (revision 426) +++ /tags/v1-0-3/src/libf/put_varm_text_allf.c (revision 426) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_varm_text_all_ NFMPI_PUT_VARM_TEXT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_varm_text_all_ nfmpi_put_varm_text_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_varm_text_all_ nfmpi_put_varm_text_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_varm_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_inq_attlen( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_vars_int1f.c =================================================================== --- /tags/v1-0-3/src/libf/put_vars_int1f.c (revision 451) +++ /tags/v1-0-3/src/libf/put_vars_int1f.c (revision 451) @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_vars_int1_ NFMPI_PUT_VARS_INT1 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_vars_int1_ nfmpi_put_vars_int1__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_vars_int1_ nfmpi_put_vars_int1 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_vars_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], const signed char * v6 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v1) p--; + p++; + p1 = (char *)malloc( p-v1 + 1 ); + for (li=0; li<(p-v1); li++) { p1[li] = v1[li]; } + p1[li] = 0; + } + ierr = ncmpi_delete( p1, MPI_Info_f2c(*v2) ); + free( p1 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_vara_intf.c =================================================================== --- /tags/v1-0-3/src/libf/get_vara_intf.c (revision 390) +++ /tags/v1-0-3/src/libf/get_vara_intf.c (revision 390) @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_vara_int_ NFMPI_GET_VARA_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_vara_int_ nfmpi_get_vara_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_vara_int_ nfmpi_get_vara_int +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_vara_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Fint *v5 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + + { ln5 = *v4; + if (ln5 > 0) { + int li; + l5 = (int *)malloc( ln5 * sizeof(int) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; lindims; +} Index: /tags/v1-0-3/src/libf/get_att_int2f.c =================================================================== --- /tags/v1-0-3/src/libf/get_att_int2f.c (revision 259) +++ /tags/v1-0-3/src/libf/get_att_int2f.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_att_int2_ NFMPI_GET_ATT_INT2 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_att_int2_ nfmpi_get_att_int2__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_att_int2_ nfmpi_get_att_int2 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_att_int2_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), short*v4 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_short( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/enddeff.c =================================================================== --- /tags/v1-0-3/src/libf/enddeff.c (revision 259) +++ /tags/v1-0-3/src/libf/enddeff.c (revision 259) @@ -0,0 +1,28 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_enddef_ NFMPI_ENDDEF +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_enddef_ nfmpi_enddef__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_enddef_ nfmpi_enddef +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_enddef_ ( int *v1 ){ + int ierr; + ierr = ncmpi_enddef( *v1 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/defs =================================================================== --- /tags/v1-0-3/src/libf/defs (revision 641) +++ /tags/v1-0-3/src/libf/defs (revision 641) @@ -0,0 +1,1366 @@ +$routine_prefix = "ncmpi_"; +$routine_pattern = "[a-z0-9_]*"; +$out_prefix = "nfmpi_"; +$do_weak = 0; +$do_profiling = 0; + +## Need MPI_Offset / INTEGER(KIND=MPI_OFFSET_KIND) Fortran interface +# $tof77{"MPI_Offset"} = "int *"; +# $tof77{"MPI_Offset *"} = "int *"; +# $tof77{"MPI_Offset*"} = "int *"; +# $tof77{"MPI_Offset\[\]"} = "int"; + +$tof77{"int"} = "int *"; +$tof77{"nc_type"} = "int *"; +$tof77{"nc_type *"} = "int *"; +$tof77{"nc_type*"} = "int *"; +$malloc = "malloc"; +$calloc = "calloc"; +$free = "free"; +$header_file = "mpinetcdf_impl.h"; + +# Error return handling +$errparmtype = ""; +$errparm = ""; +$errparmlval = "ierr"; +$errparmrval = "ierr"; +$returnErrval = 1; +$returnType = "int"; + +#% +#% Change the handling of input MPI handles +%argsneedcast = ( 'MPI_Request *' => '(fixme][)(ARG)', + 'MPI_Status *' => '(MPI_Status *)(ARG)', + 'MPI_File' => 'MPI_File_f2c(ARG)', + 'MPI_Comm' => 'MPI_Comm_f2c(ARG)', + 'MPI_Comm *' => '(fixme][)(ARG)', + 'MPI_Datatype' => 'MPI_Type_f2c(ARG)', + 'MPI_Datatype *' => '(fixme][ *)(ARG)', + 'MPI_Info *' => '(fixme][)(ARG)', + 'MPI_Info' => 'MPI_Info_f2c(ARG)' ); + +# Map some of the names from C to Fortran to replace float with real, +# short with int2 +%CtoFName = ( + 'put_att_float' => 'put_att_real', + 'get_att_float' => 'get_att_real', + 'put_var1_float' => 'put_var1_real', + 'get_var1_float' => 'get_var1_real', + 'put_var_float' => 'put_var_real', + 'get_var_float' => 'get_var_real', + 'put_var_float_all' => 'put_var_real_all', + 'get_var_float_all' => 'get_var_real_all', + 'put_vara_float_all' => 'put_vara_real_all', + 'get_vara_float_all' => 'get_vara_real_all', + 'put_vara_float' => 'put_vara_real', + 'get_vara_float' => 'get_vara_real', + 'put_vars_float_all' => 'put_vars_real_all', + 'get_vars_float_all' => 'get_vars_real_all', + 'put_vars_float' => 'put_vars_real', + 'get_vars_float' => 'get_vars_real', + 'put_varm_float_all' => 'put_varm_real_all', + 'get_varm_float_all' => 'get_varm_real_all', + 'put_varm_float' => 'put_varm_real', + 'get_varm_float' => 'get_varm_real', + + 'put_att_short' => 'put_att_int2', + 'get_att_short' => 'get_att_int2', + 'put_var1_short' => 'put_var1_int2', + 'get_var1_short' => 'get_var1_int2', + 'put_var_short' => 'put_var_int2', + 'get_var_short' => 'get_var_int2', + 'put_var_short_all' => 'put_var_int2_all', + 'get_var_short_all' => 'get_var_int2_all', + 'put_vara_short_all' => 'put_vara_int2_all', + 'get_vara_short_all' => 'get_vara_int2_all', + 'put_vara_short' => 'put_vara_int2', + 'get_vara_short' => 'get_vara_int2', + 'put_vars_short_all' => 'put_vars_int2_all', + 'get_vars_short_all' => 'get_vars_int2_all', + 'put_vars_short' => 'put_vars_int2', + 'get_vars_short' => 'get_vars_int2', + 'put_varm_short_all' => 'put_varm_int2_all', + 'get_varm_short_all' => 'get_varm_int2_all', + 'put_varm_short' => 'put_varm_int2', + 'get_varm_short' => 'get_varm_int2', + + 'put_att_schar' => 'put_att_int1', + 'get_att_schar' => 'get_att_int1', + 'put_var1_schar' => 'put_var1_int1', + 'get_var1_schar' => 'get_var1_int1', + 'put_var_schar' => 'put_var_int1', + 'get_var_schar' => 'get_var_int1', + 'put_var_schar_all' => 'put_var_int1_all', + 'get_var_schar_all' => 'get_var_int1_all', + 'put_vara_schar_all' => 'put_vara_int1_all', + 'get_vara_schar_all' => 'get_vara_int1_all', + 'put_vara_schar' => 'put_vara_int1', + 'get_vara_schar' => 'get_vara_int1', + 'put_vars_schar_all' => 'put_vars_int1_all', + 'get_vars_schar_all' => 'get_vars_int1_all', + 'put_vars_schar' => 'put_vars_int1', + 'get_vars_schar' => 'get_vars_int1', + 'put_varm_schar_all' => 'put_varm_int1_all', + 'get_varm_schar_all' => 'get_varm_int1_all', + 'put_varm_schar' => 'put_varm_int1', + 'get_varm_schar' => 'get_varm_int1' +); +# +# We really need a easier way to force a default for a particular data type +# (e.g., so that we can say "use 'in:intToSizeT' for MPI_Offset. For arrays, +# we still need an argument for the array size +# +# Other transformations: +# variable ids and dimension ids must be shifted by 1 (0... in C, 1... in +# Fortran. This is done with out:OffsetIndex and in:OffsetIndexIn). +# Arrays of ids are handled with in:OffsetIndexInArr:dimension + +%special_args = ( + 'copy_att' => '2:3:5', 'copy_att-3' => 'in:addnull', + 'copy_att-2' => 'in:OffsetIndexIn', + 'copy_att-5' => 'in:OffsetIndexIn', + 'create' => 2, 'create-2' => 'in:addnull' , + 'def_dim' => '2:4', 'def_dim-2' => 'in:addnull', +## Already MPI_Offset match, no need of type cast +# 'def_dim-3' => 'in:intToSizeT', + 'def_dim-4' => 'out:OffsetIndex', + 'def_var' => '2:5:6', + 'def_var-2' => 'in:addnull', + 'def_var-5' => 'in:OffsetIndexInArr:*v4', + 'def_var-6' => 'out:OffsetIndex', + 'del_att' => '2:3', 'del_att-3' => 'in:addnull', + 'del_att-2' => 'in:OffsetIndexIn', + 'get_att_double' => '2:3', 'get_att_double-3' => 'in:addnull', + 'get_att_double-2' => 'in:OffsetIndexIn', + 'get_att_float' => '2:3', 'get_att_float-3' => 'in:addnull', + 'get_att_float-2' => 'in:OffsetIndexIn', + 'get_att_int' => '2:3', 'get_att_int-3' => 'in:addnull', + 'get_att_int-2' => 'in:OffsetIndexIn', + +## Skip long for fortran binding iface +# 'get_att_long' => '2:3', 'get_att_long-3' => 'in:addnull', +# 'get_att_long-2' => 'in:OffsetIndexIn', + + 'get_att_schar' => '2:3:4', 'get_att_schar-3' => 'in:addnull', + 'get_att_schar-2' => 'in:OffsetIndexIn', +# 'get_att_schar-4' => 'out:charBufferOut', + 'get_att_schar-4' => 'out:int1toschar', + 'get_att_short' => '2:3', 'get_att_short-3' => 'in:addnull', + 'get_att_short-2' => 'in:OffsetIndexIn', + 'get_att_text' => '2:3:4', 'get_att_text-3' => 'in:addnull', + 'get_att_text-2' => 'in:OffsetIndexIn', + 'get_att_text-4' => 'out:charBufferOut', + +## Skip uchar for fortran binding iface +# 'get_att_uchar' => '2:3:4', 'get_att_uchar-3' => 'in:addnull', +# 'get_att_uchar-2' => 'in:OffsetIndexIn', +# 'get_att_uchar-4' => 'out:charBufferOut', + + 'get_var1' => '2:3', + 'get_var1-2' => 'in:OffsetIndexIn', + 'get_var1-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_double' => '2:3', + 'get_var1_double-2' => 'in:OffsetIndexIn', + 'get_var1_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_float' => '2:3', + 'get_var1_float-2' => 'in:OffsetIndexIn', + 'get_var1_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_int' => '2:3', + 'get_var1_int-2' => 'in:OffsetIndexIn', + 'get_var1_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_schar' => '2:3', + 'get_var1_schar-2' => 'in:OffsetIndexIn', + 'get_var1_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_short' => '2:3', + 'get_var1_short-2' => 'in:OffsetIndexIn', + 'get_var1_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var1_text' => '2:3:4', + 'get_var1_text-2' => 'in:OffsetIndexIn', + 'get_var1_text-4' => 'out:charBufferOut', + 'get_var1_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_var_double_all' => '2', + 'get_var_double_all-2' => 'in:OffsetIndexIn', + 'get_var_double' => '2', + 'get_var_double-2' => 'in:OffsetIndexIn', + 'get_var_float_all' => '2', + 'get_var_float_all-2' => 'in:OffsetIndexIn', + 'get_var_float' => '2', + 'get_var_float-2' => 'in:OffsetIndexIn', + 'get_var_int_all' => '2', + 'get_var_int_all-2' => 'in:OffsetIndexIn', + 'get_var_int' => '2', + 'get_var_int-2' => 'in:OffsetIndexIn', + 'get_var_schar_all' => '2', + 'get_var_schar_all-2' => 'in:OffsetIndexIn', + 'get_var_short_all' => '2', + 'get_var_short_all-2' => 'in:OffsetIndexIn', + 'get_var_schar' => '2', + 'get_var_schar-2' => 'in:OffsetIndexIn', + 'get_var_short' => '2', + 'get_var_short-2' => 'in:OffsetIndexIn', + 'get_var_text_all' => '2:3', + 'get_var_text_all-2' => 'in:OffsetIndexIn', + 'get_var_text_all-3' => 'out:charBufferOut', + 'get_var_text' => '2:3', + 'get_var_text-2' => 'in:OffsetIndexIn', + 'get_var_text-3' => 'out:charBufferOut', + 'get_var' => '2', + 'get_var-2' => 'in:OffsetIndexIn', + 'get_var_all' => '2', + 'get_var_all-2' => 'in:OffsetIndexIn', + + 'get_vara_all' => '2:3:4', + 'get_vara_all-2' => 'in:OffsetIndexIn', + 'get_vara_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara' => '2:3:4', + 'get_vara-2' => 'in:OffsetIndexIn', + 'get_vara-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_double_all' => '2:3:4', + 'get_vara_double_all-2' => 'in:OffsetIndexIn', + 'get_vara_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_double' => '2:3:4', + 'get_vara_double-2' => 'in:OffsetIndexIn', + 'get_vara_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_float_all' => '2:3:4', + 'get_vara_float_all-2' => 'in:OffsetIndexIn', + 'get_vara_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_float' => '2:3:4', + 'get_vara_float-2' => 'in:OffsetIndexIn', + 'get_vara_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_int_all' => '2:3:4', + 'get_vara_int_all-2' => 'in:OffsetIndexIn', + 'get_vara_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_int' => '2:3:4', + 'get_vara_int-2' => 'in:OffsetIndexIn', + 'get_vara_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_schar_all' => '2:3:4', + 'get_vara_schar_all-2' => 'in:OffsetIndexIn', + 'get_vara_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_short_all' => '2:3:4', + 'get_vara_short_all-2' => 'in:OffsetIndexIn', + 'get_vara_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_schar' => '2:3:4', + 'get_vara_schar-2' => 'in:OffsetIndexIn', + 'get_vara_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_short' => '2:3:4', + 'get_vara_short-2' => 'in:OffsetIndexIn', + 'get_vara_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_text_all' => '2:3:4:5', + 'get_vara_text_all-2' => 'in:OffsetIndexIn', + 'get_vara_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_text_all-5' => 'out:charBufferOut', + 'get_vara_text' => '2:3:4:5', + 'get_vara_text-2' => 'in:OffsetIndexIn', + 'get_vara_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vara_text-5' => 'out:charBufferOut', + + 'get_vars_all' => '2:3:4:5', + 'get_vars_all-2' => 'in:OffsetIndexIn', + 'get_vars_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars' => '2:3:4:5', + 'get_vars-2' => 'in:OffsetIndexIn', + 'get_vars-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double_all' => '2:3:4:5', + 'get_vars_double_all-2' => 'in:OffsetIndexIn', + 'get_vars_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double' => '2:3:4:5', + 'get_vars_double-2' => 'in:OffsetIndexIn', + 'get_vars_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_double-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float_all' => '2:3:4:5', + 'get_vars_float_all-2' => 'in:OffsetIndexIn', + 'get_vars_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float' => '2:3:4:5', + 'get_vars_float-2' => 'in:OffsetIndexIn', + 'get_vars_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_float-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int_all' => '2:3:4:5', + 'get_vars_int_all-2' => 'in:OffsetIndexIn', + 'get_vars_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int' => '2:3:4:5', + 'get_vars_int-2' => 'in:OffsetIndexIn', + 'get_vars_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_int-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar_all' => '2:3:4:5', + 'get_vars_schar_all-2' => 'in:OffsetIndexIn', + 'get_vars_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short_all' => '2:3:4:5', + 'get_vars_short_all-2' => 'in:OffsetIndexIn', + 'get_vars_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar' => '2:3:4:5', + 'get_vars_schar-2' => 'in:OffsetIndexIn', + 'get_vars_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_schar-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short' => '2:3:4:5', + 'get_vars_short-2' => 'in:OffsetIndexIn', + 'get_vars_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_short-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text_all' => '2:3:4:5:6', + 'get_vars_text_all-2' => 'in:OffsetIndexIn', + 'get_vars_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text_all-6' => 'out:charBufferOut', + 'get_vars_text' => '2:3:4:5:6', + 'get_vars_text-2' => 'in:OffsetIndexIn', + 'get_vars_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_vars_text-6' => 'out:charBufferOut', + + 'get_varm_all' => '2:3:4:5:6', + 'get_varm_all-2' => 'in:OffsetIndexIn', + 'get_varm_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm' => '2:3:4:5:6', + 'get_varm-2' => 'in:OffsetIndexIn', + 'get_varm-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double_all' => '2:3:4:5:6', + 'get_varm_double_all-2' => 'in:OffsetIndexIn', + 'get_varm_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double' => '2:3:4:5:6', + 'get_varm_double-2' => 'in:OffsetIndexIn', + 'get_varm_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_double-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float_all' => '2:3:4:5:6', + 'get_varm_float_all-2' => 'in:OffsetIndexIn', + 'get_varm_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float' => '2:3:4:5:6', + 'get_varm_float-2' => 'in:OffsetIndexIn', + 'get_varm_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_float-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int_all' => '2:3:4:5:6', + 'get_varm_int_all-2' => 'in:OffsetIndexIn', + 'get_varm_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int' => '2:3:4:5:6', + 'get_varm_int-2' => 'in:OffsetIndexIn', + 'get_varm_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_int-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar_all' => '2:3:4:5:6', + 'get_varm_schar_all-2' => 'in:OffsetIndexIn', + 'get_varm_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short_all' => '2:3:4:5:6', + 'get_varm_short_all-2' => 'in:OffsetIndexIn', + 'get_varm_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar' => '2:3:4:5:6', + 'get_varm_schar-2' => 'in:OffsetIndexIn', + 'get_varm_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_schar-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short' => '2:3:4:5:6', + 'get_varm_short-2' => 'in:OffsetIndexIn', + 'get_varm_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_short-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text_all' => '2:3:4:5:6:7', + 'get_varm_text_all-2' => 'in:OffsetIndexIn', + 'get_varm_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text_all-7' => 'out:charBufferOut', + 'get_varm_text' => '2:3:4:5:6:7', + 'get_varm_text-2' => 'in:OffsetIndexIn', + 'get_varm_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'get_varm_text-7' => 'out:charBufferOut', + + 'inq' => '5', 'inq-5' => 'out:OffsetIndex', + 'inq_att' => '2:3', 'inq_att-3' => 'in:addnull', + 'inq_att-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'inq_att-5' => 'out:sizetToInt', + 'inq_attid' => '2:3:4', 'inq_attid-3' => 'in:addnull', + 'inq_attid-2' => 'in:OffsetIndexIn', + 'inq_attid-4' => 'out:OffsetIndex', + 'inq_attlen' => '2:3', 'inq_attlen-3' => 'in:addnull', + 'inq_attlen-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'inq_attlen-4' => 'out:sizetToInt', + 'inq_attname' => '2:3:4', 'inq_attname-4' => 'out:blankpad', + 'inq_attname-2' => 'in:OffsetIndexIn', + 'inq_attname-3' => 'in:OffsetIndexIn', + 'inq_atttype' => '2:3', 'inq_atttype-3' => 'in:addnull', + 'inq_atttype-2' => 'in:OffsetIndexIn', + 'inq_attdim' => 3, 'inq_attdim-3' => 'in:addnull', + 'inq_dim' => '2:3', + 'inq_dim-2' => 'in:OffsetIndexIn', + 'inq_dim-3' => 'out:blankpad', +## Already MPI_Offset match, no need of type cast +# 'inq_dim-4' => 'out:sizetToInt', + 'inq_dimid' => '2:3', 'inq_dimid-2' => 'in:addnull', + 'inq_dimid-3' => 'out:OffsetIndex', + 'inq_dimlen' => '2', + 'inq_dimlen-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'inq_dimlen-3' => 'out:sizetToInt', + 'inq_dimname' => '2:3', + 'inq_dimname-2' => 'in:OffsetIndexIn', + 'inq_dimname-3' => 'out:blankpad', + 'inq_unlimdim' => 2, + 'inq_unlimdim-2' => 'out:OffsetIndex', + 'inq_var' => '2:3:6', + 'inq_var-2' => 'in:OffsetIndexIn', + 'inq_var-3' => 'out:blankpad', + 'inq_var-6' => 'out:reorderIntArrOut:ncmpixVardim(*v1,*v2-1)', + 'inq_vardimid' => '2:3', + 'inq_vardimid-2' => 'in:OffsetIndexIn', + 'inq_vardimid-3' => 'out:reorderIntArrOut:ncmpixVardim(*v1,*v2-1)', + 'inq_varid' => '2:3', 'inq_varid-2' => 'in:addnull', + 'inq_varid-3' => 'out:OffsetIndex', + 'inq_varname' => '2:3', + 'inq_varname-2' => 'in:OffsetIndexIn', + 'inq_varname-3' => 'out:blankpad', + 'inq_varnatts' => '2', + 'inq_varnatts-2' => 'in:OffsetIndexIn', + 'inq_varndims' => '2', + 'inq_varndims-2' => 'in:OffsetIndexIn', + 'inq_vartype' => '2', + 'inq_vartype-2' => 'in:OffsetIndexIn', + 'open' => 2, 'open-2' => 'in:addnull', + 'delete' => 1, 'delete-1' => 'in:addnull', + 'put_att_double' => '2:3', 'put_att_double-3' => 'in:addnull', + 'put_att_double-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'put_att_double-5' => 'in:intToSizeT', + 'put_att_float' => '2:3', 'put_att_float-3' => 'in:addnull', + 'put_att_float-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'put_att_float-5' => 'in:intToSizeT', + 'put_att_int' => '2:3', 'put_att_int-3' => 'in:addnull', + 'put_att_int-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'put_att_int-5' => 'in:intToSizeT', + +## Skip long for fortran binding iface +# 'put_att_long' => '2:3', 'put_att_long-3' => 'in:addnull', +# 'put_att_long-2' => 'in:OffsetIndexIn', +# 'put_att_long-5' => 'in:intToSizeT', + + 'put_att_schar' => '2:3:6', 'put_att_schar-3' => 'in:addnull', + 'put_att_schar-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'put_att_schar-5' => 'in:intToSizeT', +# 'put_att_schar-6' => 'in:charBufferIn', + 'put_att_schar-6' => 'in:int1toschar', + 'put_att_short' => '2:3', 'put_att_short-3' => 'in:addnull', + 'put_att_short-2' => 'in:OffsetIndexIn', +## Already MPI_Offset match, no need of type cast +# 'put_att_short-5' => 'in:intToSizeT', + 'put_att_text' => '2:3:5', 'put_att_text-3' => 'in:addnull', +## Already MPI_Offset match, no need of type cast +# 'put_att_text-4' => 'in:intToSizeT', + 'put_att_text-5' => 'in:charBufferIn', + 'put_att_text-2' => 'in:OffsetIndexIn', + +## Skip uchar for fortran binding iface +# 'put_att_uchar' => '2:3', 'put_att_uchar-3' => 'in:charBufferIn', +# 'put_att_uchar-2' => 'in:OffsetIndexIn', +# 'put_att_uchar-5' => 'in:intToSizeT', + + 'put_var1' => '2:3', + 'put_var1-2' => 'in:OffsetIndexIn', + 'put_var1-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_double' => '2:3', + 'put_var1_double-2' => 'in:OffsetIndexIn', + 'put_var1_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_float' => '2:3', + 'put_var1_float-2' => 'in:OffsetIndexIn', + 'put_var1_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_int' => '2:3', + 'put_var1_int-2' => 'in:OffsetIndexIn', + 'put_var1_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_schar' => '2:3', + 'put_var1_schar-2' => 'in:OffsetIndexIn', + 'put_var1_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_short' => '2:3', + 'put_var1_short-2' => 'in:OffsetIndexIn', + 'put_var1_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_var1_text' => '2:3:4', 'put_var1_text-4' => 'in:charBufferIn', + 'put_var1_text-2' => 'in:OffsetIndexIn', + 'put_var1_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + + 'put_var_double_all' => '2', + 'put_var_double_all-2' => 'in:OffsetIndexIn', + 'put_var_double' => '2', + 'put_var_double-2' => 'in:OffsetIndexIn', + 'put_var_float_all' => '2', + 'put_var_float_all-2' => 'in:OffsetIndexIn', + 'put_var_float' => '2', + 'put_var_float-2' => 'in:OffsetIndexIn', + 'put_var_int_all' => '2', + 'put_var_int_all-2' => 'in:OffsetIndexIn', + 'put_var_int' => '2', + 'put_var_int-2' => 'in:OffsetIndexIn', + 'put_var_schar_all' => '2', + 'put_var_schar_all-2' => 'in:OffsetIndexIn', + 'put_var_short_all' => '2', + 'put_var_short_all-2' => 'in:OffsetIndexIn', + 'put_var_schar' => '2', + 'put_var_schar-2' => 'in:OffsetIndexIn', + 'put_var_short' => '2', + 'put_var_short-2' => 'in:OffsetIndexIn', + 'put_var_text' => '2:3', 'put_var_text-3' => 'in:charBufferIn', + 'put_var_text-2' => 'in:OffsetIndexIn', + 'put_var_text_all' => '2:3', + 'put_var_text_all-3' => 'in:charBufferIn', + 'put_var_text_all-2' => 'in:OffsetIndexIn', + 'put_var' => '2', + 'put_var-2' => 'in:OffsetIndexIn', + 'put_vara_all' => '2:3:4', + 'put_vara_all-2' => 'in:OffsetIndexIn', + 'put_vara_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara' => '2:3:4', + 'put_vara-2' => 'in:OffsetIndexIn', + 'put_vara-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_double' => '2:3:4', + 'put_vara_double-2' => 'in:OffsetIndexIn', + 'put_vara_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_double_all' => '2:3:4', + 'put_vara_double_all-2' => 'in:OffsetIndexIn', + 'put_vara_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_float' => '2:3:4', + 'put_vara_float-2' => 'in:OffsetIndexIn', + 'put_vara_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_float_all' => '2:3:4', + 'put_vara_float_all-2' => 'in:OffsetIndexIn', + 'put_vara_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_int' => '2:3:4', + 'put_vara_int-2' => 'in:OffsetIndexIn', + 'put_vara_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_int_all' => '2:3:4', + 'put_vara_int_all-2' => 'in:OffsetIndexIn', + 'put_vara_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_schar' => '2:3:4', + 'put_vara_schar-2' => 'in:OffsetIndexIn', + 'put_vara_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_short' => '2:3:4', + 'put_vara_short-2' => 'in:OffsetIndexIn', + 'put_vara_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_schar_all' => '2:3:4', + 'put_vara_schar_all-2' => 'in:OffsetIndexIn', + 'put_vara_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_short_all' => '2:3:4', + 'put_vara_short_all-2' => 'in:OffsetIndexIn', + 'put_vara_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_text_all' => '2:3:4:5', + 'put_vara_text_all-2' => 'in:OffsetIndexIn', + 'put_vara_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_text_all-5' => 'in:charBufferIn', + 'put_vara_text' => '2:3:4:5', + 'put_vara_text-2' => 'in:OffsetIndexIn', + 'put_vara_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vara_text-5' => 'in:charBufferIn', + + 'put_vars_all' => '2:3:4:5', + 'put_vars_all-2' => 'in:OffsetIndexIn', + 'put_vars_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars' => '2:3:4:5', + 'put_vars-2' => 'in:OffsetIndexIn', + 'put_vars-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double_all' => '2:3:4:5', + 'put_vars_double_all-2' => 'in:OffsetIndexIn', + 'put_vars_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double' => '2:3:4:5', + 'put_vars_double-2' => 'in:OffsetIndexIn', + 'put_vars_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_double-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float_all' => '2:3:4:5', + 'put_vars_float_all-2' => 'in:OffsetIndexIn', + 'put_vars_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float' => '2:3:4:5', + 'put_vars_float-2' => 'in:OffsetIndexIn', + 'put_vars_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_float-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int_all' => '2:3:4:5', + 'put_vars_int_all-2' => 'in:OffsetIndexIn', + 'put_vars_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int' => '2:3:4:5', + 'put_vars_int-2' => 'in:OffsetIndexIn', + 'put_vars_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_int-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar_all' => '2:3:4:5', + 'put_vars_schar_all-2' => 'in:OffsetIndexIn', + 'put_vars_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short_all' => '2:3:4:5', + 'put_vars_short_all-2' => 'in:OffsetIndexIn', + 'put_vars_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar' => '2:3:4:5', + 'put_vars_schar-2' => 'in:OffsetIndexIn', + 'put_vars_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_schar-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short' => '2:3:4:5', + 'put_vars_short-2' => 'in:OffsetIndexIn', + 'put_vars_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_short-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text_all' => '2:3:4:5:6', + 'put_vars_text_all-2' => 'in:OffsetIndexIn', + 'put_vars_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text_all-6' => 'in:charBufferIn', + 'put_vars_text' => '2:3:4:5:6', + 'put_vars_text-2' => 'in:OffsetIndexIn', + 'put_vars_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_vars_text-6' => 'in:charBufferIn', + + 'put_varm_all' => '2:3:4:5:6', + 'put_varm_all-2' => 'in:OffsetIndexIn', + 'put_varm_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm' => '2:3:4:5:6', + 'put_varm-2' => 'in:OffsetIndexIn', + 'put_varm-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double_all' => '2:3:4:5:6', + 'put_varm_double_all-2' => 'in:OffsetIndexIn', + 'put_varm_double_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double' => '2:3:4:5:6', + 'put_varm_double-2' => 'in:OffsetIndexIn', + 'put_varm_double-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_double-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float_all' => '2:3:4:5:6', + 'put_varm_float_all-2' => 'in:OffsetIndexIn', + 'put_varm_float_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float' => '2:3:4:5:6', + 'put_varm_float-2' => 'in:OffsetIndexIn', + 'put_varm_float-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_float-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int_all' => '2:3:4:5:6', + 'put_varm_int_all-2' => 'in:OffsetIndexIn', + 'put_varm_int_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int' => '2:3:4:5:6', + 'put_varm_int-2' => 'in:OffsetIndexIn', + 'put_varm_int-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_int-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar_all' => '2:3:4:5:6', + 'put_varm_schar_all-2' => 'in:OffsetIndexIn', + 'put_varm_schar_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short_all' => '2:3:4:5:6', + 'put_varm_short_all-2' => 'in:OffsetIndexIn', + 'put_varm_short_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar' => '2:3:4:5:6', + 'put_varm_schar-2' => 'in:OffsetIndexIn', + 'put_varm_schar-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_schar-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short' => '2:3:4:5:6', + 'put_varm_short-2' => 'in:OffsetIndexIn', + 'put_varm_short-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_short-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text_all' => '2:3:4:5:6:7', + 'put_varm_text_all-2' => 'in:OffsetIndexIn', + 'put_varm_text_all-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text_all-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text_all-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text_all-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text_all-7' => 'in:charBufferIn', + 'put_varm_text' => '2:3:4:5:6:7', + 'put_varm_text-2' => 'in:OffsetIndexIn', + 'put_varm_text-3' => 'in:intToSizeTOffsetArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text-4' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text-5' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text-6' => 'in:intToSizeTArr:ncmpixVardim(*v1,*v2-1)', + 'put_varm_text-7' => 'in:charBufferIn', + + 'rename_att' => '2:3:4', 'rename_att-3' => 'in:addnull', + 'rename_att-2' => 'in:OffsetIndexIn', + 'rename_att-4' => 'in:addnull', + 'rename_dim' => '2:3', 'rename_dim-3' => 'in:addnull', + 'rename_dim-2' => 'in:OffsetIndexIn', + 'rename_var' => '2:3', 'rename_var-3' => 'in:addnull', + 'rename_var-2' => 'in:OffsetIndexIn', + ); +$build_prototypes = 1; +$buildMakefile = 0; +$prototype_header_file = "mpifnetcdf.h"; +$argsneedcast{'const MPI_Offset []'} = '(const MPI_Offset *)(ARG)'; +$argsneedcast{'nc_type *'} = '(nc_type *)(ARG)'; +$argsneedcast{'nc_type'} = '(nc_type)(ARG)'; + +# Special handling for integer*1 routines +$declarg{'put_att_int1-6'} = 'const signed char *'; +$declarg{'get_att_int1-4'} = 'signed char *'; +$declarg{'get_var1_int1-4'} = 'signed char *'; +$declarg{'get_var_int1_all-3'} = 'signed char *'; +$declarg{'get_var_int1-3'} = 'signed char *'; +$declarg{'get_vara_int1_all-5'} = 'signed char *'; +$declarg{'get_vara_int1-5'} = 'signed char *'; +$declarg{'get_vars_int1_all-6'} = 'signed char *'; +$declarg{'get_vars_int1-6'} = 'signed char *'; +$declarg{'put_var1_int1-4'} = 'const signed char *'; +$declarg{'put_var_int1-3'} = 'const signed char *'; +$declarg{'put_vara_int1_all-5'} = 'const signed char *'; +$declarg{'put_vara_int1-5'} = 'const signed char *'; +$declarg{'put_vars_int1_all-6'} = 'const signed char *'; +$declarg{'put_vars_int1-6'} = 'const signed char *'; +$declarg{'get_varm_int1_all-7'} = 'signed char *'; +$declarg{'get_varm_int1-7'} = 'signed char *'; +$declarg{'put_varm_int1_all-7'} = 'const signed char *'; +$declarg{'put_varm_int1-7'} = 'const signed char *'; + +# Special argument handling +# Special routines are used whose names are created from the name +# used in the hashes above (routinename-position) and these special routine +# names. +# void foo( MPI_Fint *v1, etc ) +# { +# /* Special declarations needed for the variables */ +# __decl( ) +# /* Special processing need for in variables */ +# _ftoc( ) +# /* Call the function. Replace special arguments with the output from */ +# __arg( ) +# /* Special post call processing (for out variables) */ +# _ctof( l$count, v$count ) /* local (C) variable name, fortran var name */ +# Not all routines must be provided +# use $declarg{routine-position} to replace the handling of input +# arguments (in the definition) +# E.g., $declarg{'put_att_schar-6'} = 'const signed char *'; +# +# Routines needed for special argument handling for MPI_Offset +# --------------------------------------------------------------------------- +# Convert from an int array to an Aint array for routines taking an Aint as +# input +# usage is +# 'Type_struct' => '3', 'Type_struct-3' => 'in:intToAintArr:*v1', +# where *v1 will give the array size (the number is the number of the argument) + +# Set justCopy to 1 make a copy only when sizet and int are different sizes +# Use 0 to always copy *and* invert order of elements +$justCopy = 0; + +sub intToSizeTArr_in_decl { + my $count = $_[0]; + print $OUTFD " MPI_Offset *l$count = 0;\n"; +} +sub intToSizeTArr_ftoc { + my $count = $_[0]; + # We use a local variable for the array size because we may need to + # call a function of some of the other arguments to get the array size + if ($justCopy) { + print $OUTFD " +#ifdef HAVE_SIZET_LARGER_THAN_FINT + { int ln = $Array_size; + if (ln > 0) { + int li; + l$count = (MPI_Offset *)$malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l$count = (MPI_Offset *)$malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li '3', 'Type_struct-3' => 'in:intToAintArr:*v1', +# where *v1 will give the array size (the number is the number of the argument) +# Also converts from 1-based to 0-based values. +# +# Set justCopy to 1 make a copy only when sizet and int are different sizes +# Use 0 to always copy *and* invert order of elements +$justCopy = 0; + +sub intToSizeTOffsetArr_in_decl { + my $count = $_[0]; + &intToSizeTArr_in_decl( $count ); +} +sub intToSizeTOffsetArr_ftoc { + my $count = $_[0]; + # We use a local variable for the array size because we may need to + # call a function of some of the other arguments to get the array size + # We can never just copy because we must shift + if ($justCopy && 0) { + print $OUTFD " +#ifdef HAVE_SIZET_LARGER_THAN_FINT + { int ln = $Array_size; + if (ln > 0) { + int li; + l$count = (MPI_Offset *)$malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l$count = (MPI_Offset *)$malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li '3', 'Type_struct-3' => 'in:reorderIntArr:*v1', +# where *v1 will give the array size (the number is the number of the argument) + +sub reorderIntArr_in_decl { + my $count = $_[0]; + print $OUTFD " MPI_Offset *l$count=0;\n"; +} +sub reorderIntArr_ftoc { + my $count = $_[0]; + # We use a local variable for the array size because we may need to + # call a function of some of the other arguments to get the array size + # Always copy and invert order + print $OUTFD " + { int ln = $Array_size; + if (ln > 0) { + int li; + l$count = (MPI_Offset *)$malloc( ln * sizeof(int) ); + for (li=0; li '3', 'Type_struct-3' => 'in:reorderIntArrOut:*v1', +# where *v1 will give the array size (the number is the number of the argument) + +sub reorderIntArrOut_out_decl { + my $count = $_[0]; + print $OUTFD " int *l$count=0;\n int ln$count;\n"; +} +sub reorderIntArrOut_out_ftoc { + my $count = $_[0]; + # We use a local variable for the array size because we may need to + # call a function of some of the other arguments to get the array size + # Always copy and invert order + print $OUTFD " + ln$count = $Array_size; + if (ln$count > 0) { + l$count = (int *)$malloc( ln$count * sizeof(int) ); + }\n"; +} +sub reorderIntArrOut_out_arg { + my $count = $_[0]; + print $OUTFD "l$count"; +} +# This routine is invoked even for the in case (to free the result) +sub reorderIntArrOut_ctof { + my $lname = $_[0]; + my $vname = $_[1]; + print $OUTFD " + if ($lname) { + int li; + if (!$errparmrval) { + for (li=0; li '3', 'inq_varid-3' => 'out:OffsetIndex', + +sub OffsetIndex_out_decl { + my $count = $_[0]; +} +sub OffsetIndex_out_ftoc { + my $count = $_[0]; +} +sub OffsetIndex_out_arg { + my $count = $_[0]; + print $OUTFD "v$count"; +} +sub OffsetIndex_ctof { + my $lname = $_[0]; + my $vname = $_[1]; + print $OUTFD " + if (!$errparmrval) *v$count = *v$count + 1;\n"; +} +# ------------------------------------------------------------------------- +# For input of indices, subtract one to the result +# usage is +# 'inq_dim' => '3', 'inq_dim-3' => 'in:OffsetIndexIn', + +sub OffsetIndexIn_in_decl { + my $count = $_[0]; + print $OUTFD " int l$count = *v$count - 1;\n"; +} +sub OffsetIndexIn_ftoc { + my $count = $_[0]; +} +sub OffsetIndexIn_in_arg { + my $count = $_[0]; + print $OUTFD "l$count"; +} +sub OffsetIndexIn_ctof { + my $lname = $_[0]; + my $vname = $_[1]; +} +# ------------------------------------------------------------------------- +# For input of an array of indices, subtract one from the result. +# Also, reverse the order of the array indices +# usage is +# 'def_var' => '3', 'def_var-3' => 'in:OffsetIndexInArr', +# Note: +# This used MPI_Offset instead of int for the type in the C call. +# This did not match the one use of this routine, in defA-var +sub OffsetIndexInArr_in_decl { + my $count = $_[0]; + print $OUTFD " int *l$count=0;\n int ln$count;\n"; +} +sub OffsetIndexInArr_ftoc { + my $count = $_[0]; + print $OUTFD " + { ln$count = $Array_size; + if (ln$count > 0) { + int li; + l$count = (int *)$malloc( ln$count * sizeof(int) ); + for (li=0; lixstrerrorf.c" ) || die "Cannot open xstrerrorf.c\n"; + $out_prefix = "nfmpi_"; + $files[$#files+1] = "xstrerrorf.c"; + $args = "int *, char *"; + &print_header( "ncfmpi_xstrerror", "xstrerror", $args ); + &print_routine_type_decl( $OUTFD, "xstrerror" ); + &print_args( $OUTFD, $args, 0, "xstrerror" ); + print $OUTFD "{ + const char *p = ncmpi_strerror( *v1 ); + int i; + /* d2 is the length of the string passed into the routine */ + for (i=0; infxutil.c" ) || die "Cannot open nfxutil.c\n"; + $files[$#files+1] = "nfxutil.c"; + print $OUTFD " +#include \"nc.h\" +#include \"mpinetcdf_impl.h\" +int ncmpixVardim( int ncid, int varid ) +{ + NC_var *varp; + NC *ncp; + int status; + + status = ncmpii_NC_check_id(ncid, &ncp); + if (status != NC_NOERR) return status; + varp = ncmpii_NC_lookupvar(ncp, varid); + if (varp == NULL) return NC_ENOTVAR; + return varp->ndims; +}\n"; + close ($OUTFD); +} + +sub ncfxinqlibvers { + $OUTFD = "NCFXINQLIBVERSFD"; + open( $OUTFD, ">xinq_libversf.c" ) || die "Cannot open xinq_libversf.c\n"; + $out_prefix = "nfmpi_"; + $args = "char *"; + $files[$#files+1] = "xinq_libversf.c"; + &print_header( "ncfmpi_xinq_libvers", "xinq_libvers", $args ); + &print_routine_type_decl( $OUTFD, "xinq_libvers" ); + &print_args( $OUTFD, $args, 0, "xinq_libvers" ); + print $OUTFD "{ + const char *p = ncmpi_inq_libvers(); + int i; + /* d1 is the length of the string passed into the routine */ + for (i=0; iissyserrf.c" ) || die "Cannot open issyserrf.c\n"; + $out_prefix = "nfmpi_"; + $args = "int *"; + $files[$#files+1] = "issyserrf.c"; + &print_header( "ncfmpi_issyserr", "issyserr", $args ); + &print_routine_type_decl( $OUTFD, "issyserr" ); + &print_args( $OUTFD, $args, 0, "issyserr" ); + print $OUTFD "{ + if (*v1 > 0) + return 1; + else + return 0; +}\n"; + close ($OUTFD); + +} + +sub get_file_info { + $OUTFD = "GETFILEINFOFD"; + open( $OUTFD, ">get_file_infof.c" ) || die "Cannot open get_file_infof.c\n"; + $out_prefix = "nfmpi_"; + $files[$#files+1] = "get_file_infof.c"; + $args = "int *, int *"; + &print_header( "ncfmpi_get_file_info", "get_file_info", $args ); + &print_routine_type_decl( $OUTFD, "get_file_info" ); + &print_args( $OUTFD, $args, 0, "get_file_info" ); + print $OUTFD "{ + int ierr; + MPI_Info info; + + ierr = ncmpi_get_file_info( *v1, &info ); + *v2 = MPI_Info_c2f(info); + return ierr; +}\n"; + close ($OUTFD); + +} + + +return 1; + +# Local variables: +# mode: perl +# End: +# +# vim:ft=perl Index: /tags/v1-0-3/src/libf/put_var1_doublef.c =================================================================== --- /tags/v1-0-3/src/libf/put_var1_doublef.c (revision 390) +++ /tags/v1-0-3/src/libf/put_var1_doublef.c (revision 390) @@ -0,0 +1,46 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_var1_double_ NFMPI_PUT_VAR1_DOUBLE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_var1_double_ nfmpi_put_var1_double__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_var1_double_ nfmpi_put_var1_double +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_var1_double_ ( int *v1, int *v2, MPI_Offset v3[], double*v4 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li/dev/null 2>&1 ; then + rm -f .tmp + sed -e 's/FORT_DLL_SPEC/FORTRAN_API/g' $file > .tmp + mv .tmp $file + fi +done Index: /tags/v1-0-3/src/libf/inq_varnattsf.c =================================================================== --- /tags/v1-0-3/src/libf/inq_varnattsf.c (revision 259) +++ /tags/v1-0-3/src/libf/inq_varnattsf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_varnatts_ NFMPI_INQ_VARNATTS +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_varnatts_ nfmpi_inq_varnatts__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_varnatts_ nfmpi_inq_varnatts +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_varnatts_ ( int *v1, int *v2, MPI_Fint *v3 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_inq_varnatts( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_varidf.c =================================================================== --- /tags/v1-0-3/src/libf/inq_varidf.c (revision 259) +++ /tags/v1-0-3/src/libf/inq_varidf.c (revision 259) @@ -0,0 +1,41 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_varid_ NFMPI_INQ_VARID +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_varid_ nfmpi_inq_varid__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_varid_ nfmpi_inq_varid +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_varid_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), MPI_Fint *v3 FORT_END_LEN(d2) ){ + int ierr; + char *p2; + + {char *p = v2 + d2 - 1; + int li; + while (*p == ' ' && p > v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + ierr = ncmpi_inq_varid( *v1, p2, v3 ); + free( p2 ); + + if (!ierr) *v3 = *v3 + 1; + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_dimf.c =================================================================== --- /tags/v1-0-3/src/libf/inq_dimf.c (revision 641) +++ /tags/v1-0-3/src/libf/inq_dimf.c (revision 641) @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_dim_ NFMPI_INQ_DIM +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_dim_ nfmpi_inq_dim__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_dim_ nfmpi_inq_dim +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_dim_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Offset*v4 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + p3 = (char *)calloc( d3 + 1,1 ); + ierr = ncmpi_inq_dim( *v1, l2, p3, v4 ); + + {char *p = v3, *pc=p3; + while (*pc) {*p++ = *pc++;} + while ((p-v3) < d3) { *p++ = ' '; } + } + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_dimidf.c =================================================================== --- /tags/v1-0-3/src/libf/inq_dimidf.c (revision 259) +++ /tags/v1-0-3/src/libf/inq_dimidf.c (revision 259) @@ -0,0 +1,41 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_dimid_ NFMPI_INQ_DIMID +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_dimid_ nfmpi_inq_dimid__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_dimid_ nfmpi_inq_dimid +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_dimid_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), MPI_Fint *v3 FORT_END_LEN(d2) ){ + int ierr; + char *p2; + + {char *p = v2 + d2 - 1; + int li; + while (*p == ' ' && p > v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + ierr = ncmpi_inq_dimid( *v1, p2, v3 ); + free( p2 ); + + if (!ierr) *v3 = *v3 + 1; + return ierr; +} Index: /tags/v1-0-3/src/libf/rename_dimf.c =================================================================== --- /tags/v1-0-3/src/libf/rename_dimf.c (revision 259) +++ /tags/v1-0-3/src/libf/rename_dimf.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_rename_dim_ NFMPI_RENAME_DIM +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_rename_dim_ nfmpi_rename_dim__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_rename_dim_ nfmpi_rename_dim +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_rename_dim_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_rename_dim( *v1, l2, p3 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_vara_double_allf.c =================================================================== --- /tags/v1-0-3/src/libf/put_vara_double_allf.c (revision 390) +++ /tags/v1-0-3/src/libf/put_vara_double_allf.c (revision 390) @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_vara_double_all_ NFMPI_PUT_VARA_DOUBLE_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_vara_double_all_ nfmpi_put_vara_double_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_vara_double_all_ nfmpi_put_vara_double_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_vara_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], double*v5 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_inq_attid( *v1, l2, p3, v4 ); + free( p3 ); + + if (!ierr) *v4 = *v4 + 1; + return ierr; +} Index: /tags/v1-0-3/src/libf/get_vars_int_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_vars_int_allf.c (revision 390) +++ /tags/v1-0-3/src/libf/get_vars_int_allf.c (revision 390) @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_vars_int_all_ NFMPI_GET_VARS_INT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_vars_int_all_ nfmpi_get_vars_int_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_vars_int_all_ nfmpi_get_vars_int_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_vars_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Fint *v6 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) + return 1; + else + return 0; +} Index: /tags/v1-0-3/src/libf/put_var_realf.c =================================================================== --- /tags/v1-0-3/src/libf/put_var_realf.c (revision 259) +++ /tags/v1-0-3/src/libf/put_var_realf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_var_real_ NFMPI_PUT_VAR_REAL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_var_real_ nfmpi_put_var_real__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_var_real_ nfmpi_put_var_real +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_var_real_ ( int *v1, int *v2, float*v3 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_put_var_float( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_vara_int2f.c =================================================================== --- /tags/v1-0-3/src/libf/get_vara_int2f.c (revision 390) +++ /tags/v1-0-3/src/libf/get_vara_int2f.c (revision 390) @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_vara_int2_ NFMPI_GET_VARA_INT2 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_vara_int2_ nfmpi_get_vara_int2__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_vara_int2_ nfmpi_get_vara_int2 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_vara_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], short*v5 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + l6 = (int *)malloc( ln6 * sizeof(int) ); + } + ierr = ncmpi_inq_var( *v1, l2, p3, (nc_type *)(v4), v5, l6, v7 ); + + {char *p = v3, *pc=p3; + while (*pc) {*p++ = *pc++;} + while ((p-v3) < d3) { *p++ = ' '; } + } + free( p3 ); + + if (l6) { + int li; + if (!ierr) { + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_del_att( *v1, l2, p3 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/mpifnetcdf.h =================================================================== --- /tags/v1-0-3/src/libf/mpifnetcdf.h (revision 560) +++ /tags/v1-0-3/src/libf/mpifnetcdf.h (revision 560) @@ -0,0 +1,182 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +/* Prototypes for Fortran Interface Functions */ + +extern FORTRAN_API int FORT_CALL nfmpi_create_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2), int *v3, MPI_Fint *v4, MPI_Fint *v5 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_open_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2), int *v3, MPI_Fint *v4, MPI_Fint *v5 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_file_info_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_delete_ ( char *v1 FORT_MIXED_LEN(d1), MPI_Fint *v2 FORT_END_LEN(d1) ); +extern FORTRAN_API int FORT_CALL nfmpi_enddef_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_redef_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_set_default_format_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_sync_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_abort_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_begin_indep_data_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_end_indep_data_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_close_ ( int *v1 ); +extern FORTRAN_API int FORT_CALL nfmpi_set_fill_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_def_dim_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), MPI_Offset *v3, MPI_Fint *v4 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_def_var_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), int *v3, int *v4, MPI_Fint *v5, MPI_Fint *v6 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_rename_dim_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_rename_var_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_ ( int *v1, MPI_Fint *v2, MPI_Fint *v3, MPI_Fint *v4, MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_ndims_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_nvars_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_natts_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_unlimdim_ ( int *v1, MPI_Fint *v2 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_dimid_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), MPI_Fint *v3 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_dim_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Offset*v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_dimname_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_dimlen_ ( int *v1, int *v2, MPI_Offset*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_var_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Fint *v5, MPI_Fint *v6, MPI_Fint *v7 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_varid_ ( int *v1, char *v2 FORT_MIXED_LEN(d2), MPI_Fint *v3 FORT_END_LEN(d2) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_varname_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_vartype_ ( int *v1, int *v2, int *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_varndims_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_vardimid_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_varnatts_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_att_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset*v5 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_attid_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Fint *v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_atttype_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_attlen_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Offset*v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_inq_attname_ ( int *v1, int *v2, int *v3, char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d4) ); +extern FORTRAN_API int FORT_CALL nfmpi_copy_att_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, int *v5 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_rename_att_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d3) FORT_END_LEN(d4) ); +extern FORTRAN_API int FORT_CALL nfmpi_del_att_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Offset *v4, char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d3) FORT_END_LEN(d5) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d3) FORT_END_LEN(d4) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_int1_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, const signed char * v6 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_int1_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), signed char * v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_int2_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, short*v6 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_int2_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), short*v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_int_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, MPI_Fint *v6 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_int_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Fint *v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_real_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, float*v6 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_real_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), float*v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_att_double_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, double*v6 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_att_double_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), double*v4 FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_ ( int *v1, int *v2, MPI_Offset v3[], void*v4, int *v5, MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_ ( int *v1, int *v2, MPI_Offset v3[], void*v4, int *v5, MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_int1_ ( int *v1, int *v2, MPI_Offset v3[], const signed char * v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_text_ ( int *v1, int *v2, MPI_Offset v3[], char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d4) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_int2_ ( int *v1, int *v2, MPI_Offset v3[], short*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Fint *v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_real_ ( int *v1, int *v2, MPI_Offset v3[], float*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var1_double_ ( int *v1, int *v2, MPI_Offset v3[], double*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_int1_ ( int *v1, int *v2, MPI_Offset v3[], signed char * v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_text_ ( int *v1, int *v2, MPI_Offset v3[], char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d4) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_int2_ ( int *v1, int *v2, MPI_Offset v3[], short*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Fint *v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_real_ ( int *v1, int *v2, MPI_Offset v3[], float*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var1_double_ ( int *v1, int *v2, MPI_Offset v3[], double*v4 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_ ( int *v1, int *v2, void*v3, int *v4, MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_ ( int *v1, int *v2, void*v3, int *v4, MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_all_ ( int *v1, int *v2, void*v3, int *v4, MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_int1_ ( int *v1, int *v2, const signed char * v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_int2_ ( int *v1, int *v2, short*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_int_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_real_ ( int *v1, int *v2, float*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_var_double_ ( int *v1, int *v2, double*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int1_ ( int *v1, int *v2, signed char * v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int2_ ( int *v1, int *v2, short*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_real_ ( int *v1, int *v2, float*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_double_ ( int *v1, int *v2, double*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int1_all_ ( int *v1, int *v2, signed char * v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_text_all_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int2_all_ ( int *v1, int *v2, short*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_int_all_ ( int *v1, int *v2, MPI_Fint *v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_real_all_ ( int *v1, int *v2, float*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_var_double_all_ ( int *v1, int *v2, double*v3 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], void*v5, int *v6, MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], void*v5, int *v6, MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], void*v5, int *v6, MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], void*v5, int *v6, MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], const signed char * v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], const signed char * v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d5) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d5) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], short*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], short*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], float*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], float*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], double*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vara_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], double*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], signed char * v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], signed char * v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d5) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d5) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], short*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], short*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Fint *v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], float*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], float*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], double*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vara_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], double*v5 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], const signed char * v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], const signed char * v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], char *v6 FORT_MIXED_LEN(d6) FORT_END_LEN(d6) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], char *v6 FORT_MIXED_LEN(d6) FORT_END_LEN(d6) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], short*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], short*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], float*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], float*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], double*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_vars_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], double*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], signed char * v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], signed char * v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], char *v6 FORT_MIXED_LEN(d6) FORT_END_LEN(d6) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], char *v6 FORT_MIXED_LEN(d6) FORT_END_LEN(d6) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], short*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], short*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Fint *v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], float*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], float*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], double*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_vars_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], double*v6 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], void*v7, int *v8, MPI_Fint *v9 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], void*v7, int *v8, MPI_Fint *v9 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], void*v7, int *v8, MPI_Fint *v9 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], void*v7, int *v8, MPI_Fint *v9 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], const signed char * v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], const signed char * v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], short*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], short*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], float*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], float*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], double*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_put_varm_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], double*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], signed char * v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], signed char * v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_text_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], short*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int2_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], short*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], MPI_Fint *v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_real_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], float*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_real_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], float*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], double*v7 ); +extern FORTRAN_API int FORT_CALL nfmpi_get_varm_double_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], double*v7 ); Index: /tags/v1-0-3/src/libf/rename_varf.c =================================================================== --- /tags/v1-0-3/src/libf/rename_varf.c (revision 259) +++ /tags/v1-0-3/src/libf/rename_varf.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_rename_var_ NFMPI_RENAME_VAR +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_rename_var_ nfmpi_rename_var__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_rename_var_ nfmpi_rename_var +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_rename_var_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_rename_var( *v1, l2, p3 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_varm_int1_allf.c =================================================================== --- /tags/v1-0-3/src/libf/put_varm_int1_allf.c (revision 451) +++ /tags/v1-0-3/src/libf/put_varm_int1_allf.c (revision 451) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_varm_int1_all_ NFMPI_PUT_VARM_INT1_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_varm_int1_all_ nfmpi_put_varm_int1_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_varm_int1_all_ nfmpi_put_varm_int1_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_varm_int1_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], const signed char * v7 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_copy_att( *v1, l2, p3, *v4, l5 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_att_realf.c =================================================================== --- /tags/v1-0-3/src/libf/put_att_realf.c (revision 577) +++ /tags/v1-0-3/src/libf/put_att_realf.c (revision 577) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_att_real_ NFMPI_PUT_ATT_REAL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_att_real_ nfmpi_put_att_real__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_att_real_ nfmpi_put_att_real +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_att_real_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, float*v6 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_float( *v1, l2, p3, (nc_type)(*v4), *v5, v6 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/README.fixups =================================================================== --- /tags/v1-0-3/src/libf/README.fixups (revision 174) +++ /tags/v1-0-3/src/libf/README.fixups (revision 174) @@ -0,0 +1,11 @@ +the fortran bindings are automatically generated from the c header file. This +is nifty, but not flawless. Compliation under 'gcc -Wall' will give some +warnings. + +If you regenerate the fortran interface, remember to fix the folowing things by hand: + +nfmpi_create_: +. include + +nfmpi_open_: +. include Index: /tags/v1-0-3/src/libf/get_vara_text_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_vara_text_allf.c (revision 390) +++ /tags/v1-0-3/src/libf/get_vara_text_allf.c (revision 390) @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_vara_text_all_ NFMPI_GET_VARA_TEXT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_vara_text_all_ nfmpi_get_vara_text_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_vara_text_all_ nfmpi_get_vara_text_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_vara_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d5) ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_inq_att( *v1, l2, p3, (nc_type *)(v4), v5 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_varnamef.c =================================================================== --- /tags/v1-0-3/src/libf/inq_varnamef.c (revision 641) +++ /tags/v1-0-3/src/libf/inq_varnamef.c (revision 641) @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_varname_ NFMPI_INQ_VARNAME +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_varname_ nfmpi_inq_varname__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_varname_ nfmpi_inq_varname +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_varname_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + p3 = (char *)calloc( d3 + 1,1 ); + ierr = ncmpi_inq_varname( *v1, l2, p3 ); + + {char *p = v3, *pc=p3; + while (*pc) {*p++ = *pc++;} + while ((p-v3) < d3) { *p++ = ' '; } + } + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_nvarsf.c =================================================================== --- /tags/v1-0-3/src/libf/inq_nvarsf.c (revision 259) +++ /tags/v1-0-3/src/libf/inq_nvarsf.c (revision 259) @@ -0,0 +1,28 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_inq_nvars_ NFMPI_INQ_NVARS +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_inq_nvars_ nfmpi_inq_nvars__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_inq_nvars_ nfmpi_inq_nvars +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_inq_nvars_ ( int *v1, MPI_Fint *v2 ){ + int ierr; + ierr = ncmpi_inq_nvars( *v1, v2 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_varm_text_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_varm_text_allf.c (revision 426) +++ /tags/v1-0-3/src/libf/get_varm_text_allf.c (revision 426) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_varm_text_all_ NFMPI_GET_VARM_TEXT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_varm_text_all_ nfmpi_get_varm_text_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_varm_text_all_ nfmpi_get_varm_text_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_varm_text_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], char *v7 FORT_MIXED_LEN(d7) FORT_END_LEN(d7) ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_schar( *v1, l2, p3, (nc_type)(*v4), *v5, v6 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_varm_intf.c =================================================================== --- /tags/v1-0-3/src/libf/get_varm_intf.c (revision 426) +++ /tags/v1-0-3/src/libf/get_varm_intf.c (revision 426) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_varm_int_ NFMPI_GET_VARM_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_varm_int_ nfmpi_get_varm_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_varm_int_ nfmpi_get_varm_int +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_varm_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], MPI_Fint *v7 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + + {char *p = v4 + d4 - 1; + int li; + while (*p == ' ' && p > v4) p--; + p++; + p4 = (char *)malloc( p-v4 + 1 ); + for (li=0; li<(p-v4); li++) { p4[li] = v4[li]; } + p4[li] = 0; + } + ierr = ncmpi_rename_att( *v1, l2, p3, p4 ); + free( p3 ); + free( p4 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/inq_libversf.f =================================================================== --- /tags/v1-0-3/src/libf/inq_libversf.f (revision 603) +++ /tags/v1-0-3/src/libf/inq_libversf.f (revision 603) @@ -0,0 +1,10 @@ + character *80 function nfmpi_inq_libvers() + integer ierr + character *(80) tmpstr + + integer nfmpi_xinq_libvers + external nfmpi_xinq_libvers + + ierr = nfmpi_xinq_libvers(tmpstr) + nfmpi_inq_libvers = tmpstr + end Index: /tags/v1-0-3/src/libf/get_att_doublef.c =================================================================== --- /tags/v1-0-3/src/libf/get_att_doublef.c (revision 259) +++ /tags/v1-0-3/src/libf/get_att_doublef.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_att_double_ NFMPI_GET_ATT_DOUBLE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_att_double_ nfmpi_get_att_double__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_att_double_ nfmpi_get_att_double +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_att_double_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), double*v4 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_double( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var_int1f.c =================================================================== --- /tags/v1-0-3/src/libf/get_var_int1f.c (revision 451) +++ /tags/v1-0-3/src/libf/get_var_int1f.c (revision 451) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_int1_ NFMPI_GET_VAR_INT1 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_int1_ nfmpi_get_var_int1__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_int1_ nfmpi_get_var_int1 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_int1_ ( int *v1, int *v2, signed char * v3 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var_schar( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var_text_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_var_text_allf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_var_text_allf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_text_all_ NFMPI_GET_VAR_TEXT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_text_all_ nfmpi_get_var_text_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_text_all_ nfmpi_get_var_text_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_text_all_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var_text_all( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_att_textf.c =================================================================== --- /tags/v1-0-3/src/libf/put_att_textf.c (revision 560) +++ /tags/v1-0-3/src/libf/put_att_textf.c (revision 560) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_att_text_ NFMPI_PUT_ATT_TEXT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_att_text_ nfmpi_put_att_text__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_att_text_ nfmpi_put_att_text +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_att_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Offset *v4, char *v5 FORT_MIXED_LEN(d5) FORT_END_LEN(d3) FORT_END_LEN(d5) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_text( *v1, l2, p3, *v4, v5 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_varm_double_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_varm_double_allf.c (revision 426) +++ /tags/v1-0-3/src/libf/get_varm_double_allf.c (revision 426) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_varm_double_all_ NFMPI_GET_VARM_DOUBLE_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_varm_double_all_ nfmpi_get_varm_double_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_varm_double_all_ nfmpi_get_varm_double_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_varm_double_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], double*v7 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_int( *v1, l2, p3, (nc_type)(*v4), *v5, v6 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_att_realf.c =================================================================== --- /tags/v1-0-3/src/libf/get_att_realf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_att_realf.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_att_real_ NFMPI_GET_ATT_REAL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_att_real_ nfmpi_get_att_real__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_att_real_ nfmpi_get_att_real +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_att_real_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), float*v4 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_float( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var_textf.c =================================================================== --- /tags/v1-0-3/src/libf/get_var_textf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_var_textf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_text_ NFMPI_GET_VAR_TEXT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_text_ nfmpi_get_var_text__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_text_ nfmpi_get_var_text +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3) FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var_text( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_vars_allf.c =================================================================== --- /tags/v1-0-3/src/libf/put_vars_allf.c (revision 540) +++ /tags/v1-0-3/src/libf/put_vars_allf.c (revision 540) @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_vars_all_ NFMPI_PUT_VARS_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_vars_all_ nfmpi_put_vars_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_vars_all_ nfmpi_put_vars_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_vars_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + ierr = ncmpi_create( MPI_Comm_f2c(*v1), p2, *v3, MPI_Info_f2c(*v4), v5 ); + free( p2 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_varsf.c =================================================================== --- /tags/v1-0-3/src/libf/put_varsf.c (revision 540) +++ /tags/v1-0-3/src/libf/put_varsf.c (revision 540) @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_vars_ NFMPI_PUT_VARS +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_vars_ nfmpi_put_vars__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_vars_ nfmpi_put_vars +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_vars_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li readonly + parameter(ncrdwr = 1) +! in create phase, cleared by ncendef + parameter(nccreat = 2) +! on create destroy existing file + parameter(ncexcl = 4) +! in define mode, cleared by ncendef + parameter(ncindef = 8) +! synchronise numrecs on change (x'10') + parameter(ncnsync = 16) +! synchronise whole header on change (x'20') + parameter(nchsync = 32) +! numrecs has changed (x'40') + parameter(ncndirty = 64) +! header info has changed (x'80') + parameter(nchdirty = 128) +! prefill vars on endef and increase of record, the default behavior + parameter(ncfill = 0) +! do not fill vars on endef and increase of record (x'100') + parameter(ncnofill = 256) +! isa link (x'8000') + parameter(nclink = 32768) + +! +! 'mode' arguments for nccreate and ncopen +! + parameter(ncnowrit = 0) + parameter(ncwrite = ncrdwr) + parameter(ncclob = nf_clobber) + parameter(ncnoclob = nf_noclobber) + +! +! 'size' argument to ncdimdef for an unlimited dimension +! + integer ncunlim + parameter(ncunlim = 0) + +! +! attribute id to put/get a global attribute +! + parameter(ncglobal = 0) + +! +! advisory maximums: +! + parameter(maxncop = 32) + parameter(maxncdim = 100) + parameter(maxncatt = 2000) + parameter(maxncvar = 2000) +! not enforced + parameter(maxncnam = 128) + parameter(maxvdims = maxncdim) + +! +! global netcdf error status variable +! initialized in error.c +! + +! no error + parameter(ncnoerr = nf_noerr) +! not a netcdf id + parameter(ncebadid = nf_ebadid) +! too many netcdfs open + parameter(ncenfile = -31) ! nc_syserr +! netcdf file exists && ncnoclob + parameter(nceexist = nf_eexist) +! invalid argument + parameter(nceinval = nf_einval) +! write to read only + parameter(nceperm = nf_eperm) +! operation not allowed in data mode + parameter(ncenotin = nf_enotindefine ) +! operation not allowed in define mode + parameter(nceindef = nf_eindefine) +! coordinates out of domain + parameter(ncecoord = nf_einvalcoords) +! maxncdims exceeded + parameter(ncemaxds = nf_emaxdims) +! string match to name in use + parameter(ncename = nf_enameinuse) +! attribute not found + parameter(ncenoatt = nf_enotatt) +! maxncattrs exceeded + parameter(ncemaxat = nf_emaxatts) +! not a netcdf data type + parameter(ncebadty = nf_ebadtype) +! invalid dimension id + parameter(ncebadd = nf_ebaddim) +! ncunlimited in the wrong index + parameter(nceunlim = nf_eunlimpos) +! maxncvars exceeded + parameter(ncemaxvs = nf_emaxvars) +! variable not found + parameter(ncenotvr = nf_enotvar) +! action prohibited on ncglobal varid + parameter(nceglob = nf_eglobal) +! not a netcdf file + parameter(ncenotnc = nf_enotnc) + parameter(ncests = nf_ests) + parameter (ncentool = nf_emaxname) + parameter(ncfoobar = 32) + parameter(ncsyserr = -31) + +! +! global options variable. used to determine behavior of error handler. +! initialized in lerror.c +! + parameter(ncfatal = 1) + parameter(ncverbos = 2) + +! +! default fill values. these must be the same as in the c interface. +! + integer filbyte + integer filchar + integer filshort + integer fillong + real filfloat + doubleprecision fildoub + + parameter (filbyte = -127) + parameter (filchar = 0) + parameter (filshort = -32767) + parameter (fillong = -2147483647) + parameter (filfloat = 9.9692099683868690e+36) + parameter (fildoub = 9.9692099683868690e+36) + +! +! Define the following NF_*_IS_C_* macros appropriatly for your system. +! The "INT1", "INT2" and "INT" after the "NF_" refer to the NF_INT1_T +! FORTRAN datatype, the NF_INT2_T FORTRAN datatype, and the INTEGER +! FORTRAN datatype, respectively. If the respective FORTRAN datatype +! does not exist, then do not define the corresponding macro. +#undef NF_INT1_IS_C_SIGNED_CHAR +#undef NF_INT1_IS_C_SHORT +#undef NF_INT1_IS_C_INT +#undef NF_INT1_IS_C_LONG +#undef NF_INT2_IS_C_SHORT +#undef NF_INT2_IS_C_INT +#undef NF_INT2_IS_C_LONG +#undef NF_INT_IS_C_INT +#undef NF_INT_IS_C_LONG +#undef NF_REAL_IS_C_FLOAT +#undef NF_REAL_IS_C_DOUBLE +#undef NF_DOUBLEPRECISION_IS_C_DOUBLE +#undef NF_DOUBLEPRECISION_IS_C_FLOAT + +! The number of bytes in a MPI_Offset +#undef SIZEOF_MPI_OFFSET + +#define NFMPI_OFFSET INTEGER*SIZEOF_MPI_OFFSET + +! now we can define nfmpi_unlimited properly + integer*SIZEOF_MPI_OFFSET nfmpi_unlimited + parameter (nfmpi_unlimited = 0) Index: /tags/v1-0-3/src/libf/put_att_doublef.c =================================================================== --- /tags/v1-0-3/src/libf/put_att_doublef.c (revision 577) +++ /tags/v1-0-3/src/libf/put_att_doublef.c (revision 577) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_att_double_ NFMPI_PUT_ATT_DOUBLE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_att_double_ nfmpi_put_att_double__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_att_double_ nfmpi_put_att_double +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_att_double_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), int *v4, MPI_Offset *v5, double*v6 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_double( *v1, l2, p3, (nc_type)(*v4), *v5, v6 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_var1_intf.c =================================================================== --- /tags/v1-0-3/src/libf/put_var1_intf.c (revision 390) +++ /tags/v1-0-3/src/libf/put_var1_intf.c (revision 390) @@ -0,0 +1,46 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_var1_int_ NFMPI_PUT_VAR1_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_var1_int_ nfmpi_put_var1_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_var1_int_ nfmpi_put_var1_int +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_var1_int_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Fint *v4 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_schar( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_varf.c =================================================================== --- /tags/v1-0-3/src/libf/get_varf.c (revision 608) +++ /tags/v1-0-3/src/libf/get_varf.c (revision 608) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_ NFMPI_GET_VAR +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_ nfmpi_get_var__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_ nfmpi_get_var +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_ ( int *v1, int *v2, void*v3, int *v4, MPI_Fint *v5 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var( *v1, l2, v3, *v4, MPI_Type_f2c(*v5) ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var_int_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_var_int_allf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_var_int_allf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_int_all_ NFMPI_GET_VAR_INT_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_int_all_ nfmpi_get_var_int_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_int_all_ nfmpi_get_var_int_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_int_all_ ( int *v1, int *v2, MPI_Fint *v3 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var_int_all( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_att_textf.c =================================================================== --- /tags/v1-0-3/src/libf/get_att_textf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_att_textf.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_att_text_ NFMPI_GET_ATT_TEXT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_att_text_ nfmpi_get_att_text__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_att_text_ nfmpi_get_att_text +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_att_text_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), char *v4 FORT_MIXED_LEN(d4) FORT_END_LEN(d3) FORT_END_LEN(d4) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_text( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_var1_int1f.c =================================================================== --- /tags/v1-0-3/src/libf/put_var1_int1f.c (revision 451) +++ /tags/v1-0-3/src/libf/put_var1_int1f.c (revision 451) @@ -0,0 +1,46 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_var1_int1_ NFMPI_PUT_VAR1_INT1 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_var1_int1_ nfmpi_put_var1_int1__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_var1_int1_ nfmpi_put_var1_int1 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_var1_int1_ ( int *v1, int *v2, MPI_Offset v3[], const signed char * v4 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_inq_atttype( *v1, l2, p3, (nc_type *)(v4) ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var_intf.c =================================================================== --- /tags/v1-0-3/src/libf/get_var_intf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_var_intf.c (revision 259) @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var_int_ NFMPI_GET_VAR_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var_int_ nfmpi_get_var_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var_int_ nfmpi_get_var_int +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var_int_ ( int *v1, int *v2, MPI_Fint *v3 ){ + int ierr; + int l2 = *v2 - 1; + ierr = ncmpi_get_var_int( *v1, l2, v3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_vars_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_vars_allf.c (revision 540) +++ /tags/v1-0-3/src/libf/get_vars_allf.c (revision 540) @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_vars_all_ NFMPI_GET_VARS_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_vars_all_ nfmpi_get_vars_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_vars_all_ nfmpi_get_vars_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_vars_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], void*v6, int *v7, MPI_Fint *v8 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + l3 = (int *)malloc( ln3 * sizeof(int) ); + } + ierr = ncmpi_inq_vardimid( *v1, l2, l3 ); + + if (l3) { + int li; + if (!ierr) { + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + ierr = ncmpi_def_dim( *v1, p2, *v3, v4 ); + free( p2 ); + + if (!ierr) *v4 = *v4 + 1; + return ierr; +} Index: /tags/v1-0-3/src/libf/get_varm_int2_allf.c =================================================================== --- /tags/v1-0-3/src/libf/get_varm_int2_allf.c (revision 426) +++ /tags/v1-0-3/src/libf/get_varm_int2_allf.c (revision 426) @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_varm_int2_all_ NFMPI_GET_VARM_INT2_ALL +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_varm_int2_all_ nfmpi_get_varm_int2_all__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_varm_int2_all_ nfmpi_get_varm_int2_all +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_varm_int2_all_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], MPI_Offset v5[], MPI_Offset v6[], short*v7 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + MPI_Offset *l5 = 0; + MPI_Offset *l6 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v2) p--; + p++; + p2 = (char *)malloc( p-v2 + 1 ); + for (li=0; li<(p-v2); li++) { p2[li] = v2[li]; } + p2[li] = 0; + } + ierr = ncmpi_open( MPI_Comm_f2c(*v1), p2, *v3, MPI_Info_f2c(*v4), v5 ); + free( p2 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_att_intf.c =================================================================== --- /tags/v1-0-3/src/libf/get_att_intf.c (revision 259) +++ /tags/v1-0-3/src/libf/get_att_intf.c (revision 259) @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_att_int_ NFMPI_GET_ATT_INT +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_att_int_ nfmpi_get_att_int__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_att_int_ nfmpi_get_att_int +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_att_int_ ( int *v1, int *v2, char *v3 FORT_MIXED_LEN(d3), MPI_Fint *v4 FORT_END_LEN(d3) ){ + int ierr; + int l2 = *v2 - 1; + char *p3; + + {char *p = v3 + d3 - 1; + int li; + while (*p == ' ' && p > v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_get_att_int( *v1, l2, p3, v4 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/get_var1_doublef.c =================================================================== --- /tags/v1-0-3/src/libf/get_var1_doublef.c (revision 390) +++ /tags/v1-0-3/src/libf/get_var1_doublef.c (revision 390) @@ -0,0 +1,46 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_get_var1_double_ NFMPI_GET_VAR1_DOUBLE +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_get_var1_double_ nfmpi_get_var1_double__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_get_var1_double_ nfmpi_get_var1_double +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_get_var1_double_ ( int *v1, int *v2, MPI_Offset v3[], double*v4 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li v3) p--; + p++; + p3 = (char *)malloc( p-v3 + 1 ); + for (li=0; li<(p-v3); li++) { p3[li] = v3[li]; } + p3[li] = 0; + } + ierr = ncmpi_put_att_short( *v1, l2, p3, (nc_type)(*v4), *v5, v6 ); + free( p3 ); + return ierr; +} Index: /tags/v1-0-3/src/libf/put_vara_int1f.c =================================================================== --- /tags/v1-0-3/src/libf/put_vara_int1f.c (revision 451) +++ /tags/v1-0-3/src/libf/put_vara_int1f.c (revision 451) @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + * + * This file is automatically generated by buildiface -infile=../lib/pnetcdf.h -deffile=defs + * DO NOT EDIT + */ +#include "mpinetcdf_impl.h" + + +#ifdef F77_NAME_UPPER +#define nfmpi_put_vara_int1_ NFMPI_PUT_VARA_INT1 +#elif defined(F77_NAME_LOWER_2USCORE) +#define nfmpi_put_vara_int1_ nfmpi_put_vara_int1__ +#elif !defined(F77_NAME_LOWER_USCORE) +#define nfmpi_put_vara_int1_ nfmpi_put_vara_int1 +/* Else leave name alone */ +#endif + + +/* Prototypes for the Fortran interfaces */ +#include "mpifnetcdf.h" +FORTRAN_API int FORT_CALL nfmpi_put_vara_int1_ ( int *v1, int *v2, MPI_Offset v3[], MPI_Offset v4[], const signed char * v5 ){ + int ierr; + int l2 = *v2 - 1; + MPI_Offset *l3 = 0; + MPI_Offset *l4 = 0; + + { int ln = ncmpixVardim(*v1,*v2-1); + if (ln > 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l3 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l4 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l5 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li 0) { + int li; + l6 = (MPI_Offset *)malloc( ln * sizeof(MPI_Offset) ); + for (li=0; li + files. + + - Fortran routines will pass in a 64 bit integer for some parameters (those + corresponding to MPI_Offset type in the C routines). Declare those + parameters as 'integer(kind=MPI_OFFSET_KIND)' + + - In places where you might use NF_UNLIMITED to define an unlimited + dimension in one of the nfmpi_ routines, use NFMPI_UNLIMITED. + NFMPI_UNLIMITED will be defined as the proper type for nfmpi_def_dim, + whereas nf_unlimited might be too small + + - Parallel-NetCDF relies on MPI-IO. ROMIO, the most common MPI-IO + implementation, can make use of a prefix in front of the file name to + specify the underlying file system and override ROMIO's autodetection. A + typical prefix would look like "nfs:" or "pvfs2:". Bear this in mind if + you use a file name with ':' characters. In some cases, ROMIO might + think you are passing in a prefix and will complain about an unsupported + file system type. If that happens, add a file-system prefix to your file + name. + + Contact the parallel-netcdf mailing list (parallel-netcdf@mcs.anl.gov) if + you are confused by the above. + + - To build parallel-netcdf you will need some additional programs: + - either yacc or bison + - either lex or flex + These are usually part of your operating system's development tools. Index: /tags/v1-0-3/CREDITS =================================================================== --- /tags/v1-0-3/CREDITS (revision 594) +++ /tags/v1-0-3/CREDITS (revision 594) @@ -0,0 +1,34 @@ +Parallel-netCDF is a joint effort between Northwestern University and Argonne +National Laboratory. We have aslo been fortunate to recieve a great deal of +help from the community. A partial list follows. Thanks everyone! + +- Parallel-NetCDF uses a great deal of NetCDF code, so the project would not + have gotten as far as it did as quickly as it did without the efforts of the + Unidata group. + +- Joachim Worringen and Rene Redler + helped us build and run correctly on NEC SX-6 + +- John Tannahill contributed a great deal of effort + testing and improving our Fortran bindings + +- Richard Hedges was another early adopter and + offered a lot of configuration tips, particularly for IFC + +- Renier Vogelsang provided valuable assistance with the IRIX + port + +- Greg Sjaardema's CDF-2 patch gave us and serial NetCDF + large file support + +- Jim Edwards provided a great deal of assitance with our + AIX port + +- Tyce Mclarty also did a lot of AIX work for us + +- Christopher Subich contributed several configure + fixes, improving our handling of cross-compile environments. + +- Kurt Glaesemann contributed numerous cleanups for + pnetcdf on ia64 with HP-MPI + Index: /tags/v1-0-3/macros.make.def =================================================================== --- /tags/v1-0-3/macros.make.def (revision 2) +++ /tags/v1-0-3/macros.make.def (revision 2) @@ -0,0 +1,88 @@ +# $Id$ + +# The purpose of this file is to contain common make(1) macros. +# It should be processed by every execution of that utility. + + +# POSIX shell. Shouldn't be necessary -- but is under IRIX 5.3. +SHELL = /bin/sh + + +# Installation Directories: +prefix = /opt/netcdf +exec_prefix = $(prefix) +INCDIR = $(exec_prefix)/include +LIBDIR = $(exec_prefix)/lib +BINDIR = $(exec_prefix)/bin +MANDIR = $(prefix)/man + + +# Preprocessing: +M4 = m4 +M4FLAGS = -B10000 +CPP = c89 -E +CPPFLAGS = $(INCLUDES) $(DEFINES) @CPPFLAGS@ +FPP = +FPPFLAGS = $(CPPFLAGS) +CXXCPPFLAGS = $(CPPFLAGS) + + +# Compilation: +CC = c89 +CXX = CC +FC = f77 +CFLAGS = -g +CXXFLAGS = $(CFLAGS) @CXXFLAGS@ +FFLAGS = -g +CC_MAKEDEPEND = : +COMPILE.c = $(CC) -c $(CFLAGS) $(CPPFLAGS) +COMPILE.cxx = $(CXX) -c $(CXXFLAGS) $(CXXCPPFLAGS) +COMPILE.f = $(FC) -c $(FFLAGS) +# The following command isn't available on some systems; therefore, the +# `.F.o' rule is relatively complicated. +COMPILE.F = $(COMPILE.f) + + +# Linking: +MATHLIB = +FLIBS = +LIBS = +LINK.c = $(CC) -o $@ $(CFLAGS) $(LDFLAGS) +LINK.cxx = $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) +LINK.F = $(FC) -o $@ $(FFLAGS) $(FLDFLAGS) +LINK.f = $(FC) -o $@ $(FFLAGS) $(FLDFLAGS) + + +# NetCDF files: +NCDUMP = ncdump +NCGEN = ncgen + + +# Manual pages: +WHATIS = +# The following macro should be empty on systems that don't +# allow users to create their own manual-page indexes. +MAKEWHATIS_CMD = + + +# Misc. Utilities: +AR = ar +ARFLAGS = cru # NB: SunOS 4 doesn't like `-' option prefix +RANLIB = +TARFLAGS = -chf + + +# Dummy macros: used only as placeholders to silence GNU make. They are +# redefined, as necessary, in subdirectory makefiles. +HEADER = dummy_header +HEADER1 = dummy_header1 +HEADER2 = dummy_header2 +LIBRARY = dummy_library.a +MANUAL = dummy_manual +PROGRAM = dummy_program + + +# Distribution macros: +FTPDIR = /home/ftp/pub/$(PACKAGE) +FTPBINDIR = +VERSION = dummy_version Index: /tags/v1-0-3/README.bgl =================================================================== --- /tags/v1-0-3/README.bgl (revision 530) +++ /tags/v1-0-3/README.bgl (revision 530) @@ -0,0 +1,44 @@ +# 5 October 2005 +# Building parallel-netcdf on BGL + +Be sure to run configure with the --build and --host flags to put it in "cross +compile mode". This will make configure use compile-only tests, insted of the +usual compile-and-run tests (running tests on the bgl login node won't work as +the compute nodes are totaly different). + +configure --build powerpc32-unknown-gnu --host powerpc-suse-linux \ + --with-mpi=/bgl/BlueLight/ppcfloor/bglsys/ + +It's possible to build pnetcdf with the IBM xl compilers, but you have to set +quite a few environment variables + +export CC=blrts_xlc +export MPICC=blrts_xlc +export CXX=blrts_xlC +export MPICXX=blrts_xlC +export FC=blrts_xlf +export F77=blrts_xlf +export MPIF77=blrts_xlf + +export CFLAGS="-I/bgl/BlueLight/ppcfloor/bglsys/include" +export LIBS="-L/bgl/BlueLight/ppcfloor/bglsys/lib -lmpich.rts -lmsglayer.rts -ldevices.rts -lrts.rts -ldevices.rts -lrts.rts" + +configure --build powerpc32-unknown-gnu --host powerpc-suse-linux + +Several early versions of IBM's MPI-IO implementation would segfault under +certain workloads. If you are running driver version "V1R3M0_240_2006-060623" +or newer, the segfault issue should be resolved. If you are running an older +driver, read on: + +When built against some older BlueGene drivers, nc_test does not run +completley without setting a special environment variable, hitting a seg fault +deep inside ROMIO. We first noticed this in IBM's "Driver 202" MPI and also in +"V1R1M1_253_2005-051003" and "V1R2M1_020_2006-060110" We have told IBM +developers about the problem. Code that makes use of the ncmpi_get_vara_*_all +or ncmpi_put_vara_*_all routines will likely trigger a seg fault. IBM has +provided a workaround: if your code seg-faults, try setting the +"BGLMPIO_TUNEBLOCKING" environment variable to 0. With this environment +variable set, nc_tests runs to completion and passes. For one real-world +example, the FLASH-IO benchmark with 8 processors sees a 5% performance hit +when writing out plotfiles. That increases to 22% with 16 processors. Again, upgrading to the latest BlueGene drivers should fix this issue. + Index: /tags/v1-0-3/README.bgp =================================================================== --- /tags/v1-0-3/README.bgp (revision 642) +++ /tags/v1-0-3/README.bgp (revision 642) @@ -0,0 +1,21 @@ +# 4 December 2008 +# Building parallel-netcdf on BGP + +Building for BGP is not so different from BGL: front end node is still a cross compile host for the back end. + +Be sure to run configure with the --build and --host flags to put it in "cross +compile mode". This will make configure use compile-only tests, insted of the +usual compile-and-run tests (running tests on the bgp login node won't work as +the compute nodes are totaly different). + +configure --build powerpc-bgp-linux --host powerpc64-suse-linux \ + --with-mpi=/bgsys/drivers/ppcfloor/comm + +It's possible to build pnetcdf with the IBM xl compilers: + +./configure --build powerpc-bgp-linux --host powerpc64-suse-linux \ + CC=mpixlc MPICC=mpixlc FC=mpixlf90 \ + MPIF77=mpixlf90 F77=mpixlf90 F90=mpixlf90 + +As far as we know, there are no issues with pnetcdf on BGP, but should you find any, email parallel-netcdf@mcs.anl.gov + Index: /tags/v1-0-3/doc/latex8.sty =================================================================== --- /tags/v1-0-3/doc/latex8.sty (revision 93) +++ /tags/v1-0-3/doc/latex8.sty (revision 93) @@ -0,0 +1,175 @@ +% --------------------------------------------------------------- +% +% $Id$ +% +% by Paolo.Ienne@di.epfl.ch +% +% --------------------------------------------------------------- +% +% no guarantee is given that the format corresponds perfectly to +% IEEE 8.5" x 11" Proceedings, but most features should be ok. +% +% --------------------------------------------------------------- +% with LaTeX2e: +% ============= +% +% use as +% \documentclass[10pt,twocolumn]{article} +% \usepackage{latex8} +% \usepackage{times} +% +% --------------------------------------------------------------- + +% with LaTeX 2.09: +% ================ +% +% use as +% \documentstyle[times,twocolumn,latex8]{article} +% +% --------------------------------------------------------------- +% with both versions: +% =================== +% +% specify \pagestyle{empty} to omit page numbers in the final +% version +% +% specify references as +% \bibliographystyle{latex8} +% \bibliography{...your files...} +% +% use Section{} and SubSection{} instead of standard section{} +% and subsection{} to obtain headings in the form +% "1.3. My heading" +% +% --------------------------------------------------------------- + +\typeout{IEEE 8.5 x 11-Inch Proceedings Style `latex8.sty'.} + +% ten point helvetica bold required for captions +% in some sites the name of the helvetica bold font may differ, +% change the name here: +\font\tenhv = phvb at 10pt +%\font\tenhv = phvb7t at 10pt + +% eleven point times bold required for second-order headings +% \font\elvbf = cmbx10 scaled 1100 +\font\elvbf = ptmb scaled 1100 + +% set dimensions of columns, gap between columns, and paragraph indent +\setlength{\textheight}{8.875in} +\setlength{\textwidth}{6.875in} +\setlength{\columnsep}{0.3125in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\parindent}{1pc} +\setlength{\oddsidemargin}{-.19in} +\setlength{\evensidemargin}{-.19in} +%\setlength{\evensidemargin}{-.304in} + +% memento from size10.clo +% \normalsize{\@setfontsize\normalsize\@xpt\@xiipt} +% \small{\@setfontsize\small\@ixpt{11}} +% \footnotesize{\@setfontsize\footnotesize\@viiipt{9.5}} +% \scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt} +% \tiny{\@setfontsize\tiny\@vpt\@vipt} +% \large{\@setfontsize\large\@xiipt{14}} +% \Large{\@setfontsize\Large\@xivpt{18}} +% \LARGE{\@setfontsize\LARGE\@xviipt{22}} +% \huge{\@setfontsize\huge\@xxpt{25}} +% \Huge{\@setfontsize\Huge\@xxvpt{30}} + +\def\@maketitle + { + \newpage + \null + \vskip .375in + \begin{center} + {\Large \bf \@title \par} + % additional two empty lines at the end of the title + \vspace*{24pt} + { + \large + \lineskip .5em + \begin{tabular}[t]{c} + \@author + \end{tabular} + \par + } + % additional small space at the end of the author name + \vskip .5em + { + \large + \begin{tabular}[t]{c} + \@affiliation + \end{tabular} + \par + \ifx \@empty \@email + \else + \begin{tabular}{r@{~}l} + E-mail: & {\tt \@email} + \end{tabular} + \par + \fi + } + % additional empty line at the end of the title block + \vspace*{12pt} + \end{center} + } + +\def\abstract + {% + \centerline{\large\bf Abstract}% + \vspace*{12pt}% + \it% + } + +\def\endabstract + { + % additional empty line at the end of the abstract + \vspace*{12pt} + } + +\def\affiliation#1{\gdef\@affiliation{#1}} \gdef\@affiliation{} + +\def\email#1{\gdef\@email{#1}} +\gdef\@email{} + +\newlength{\@ctmp} +\newlength{\@figindent} +\setlength{\@figindent}{1pc} + +\long\def\@makecaption#1#2{ + \vskip 10pt + \setbox\@tempboxa\hbox{\tenhv\noindent #1.~#2} + \setlength{\@ctmp}{\hsize} + \addtolength{\@ctmp}{-\@figindent}\addtolength{\@ctmp}{-\@figindent} + % IF longer than one indented paragraph line + \ifdim \wd\@tempboxa >\@ctmp + % THEN set as an indented paragraph + \begin{list}{}{\leftmargin\@figindent \rightmargin\leftmargin} + \item[]\tenhv #1.~#2\par + \end{list} + \else + % ELSE center + \hbox to\hsize{\hfil\box\@tempboxa\hfil} + \fi} + +% correct heading spacing and type +\def\section{\@startsection {section}{1}{\z@} + {14pt plus 1pt minus 1pt}{14pt plus 1pt minus 1pt} {\large\bf}} +\def\subsection{\@startsection {subsection}{2}{\z@} + {13pt plus 1pt minus 1pt}{13pt plus 1pt minus 1pt} {\elvbf}} +\def\subsubsection{\@startsection {subsubsection}{3}{\z@}{12pt plus 1pt minus 1pt} +{12pt plus 1pt minus 1pt}{\normalsize\bf}} +\def\subsubsubsection{\@startsection {paragraph}{3}{\z@}{11pt plus 1pt minus 1pt} +{11pt plus 1pt minus 1pt}{\small\bf}} + +% add the period after section numbers +\newcommand{\Section}[1]{\section{\hskip -1em.~#1}} +\newcommand{\SubSection}[1]{\subsection{\hskip -1em.~#1}} +\newcommand{\SubSubSection}[1]{\subsubsection{\hskip -1em.~#1}} +\newcommand{\SubSubSubSection}[1]{\subsubsubsection{\hskip -1em.~#1}} + +% end of file latex8.sty +% --------------------------------------------------------------- Index: /tags/v1-0-3/doc/symbol_renaming.txt =================================================================== --- /tags/v1-0-3/doc/symbol_renaming.txt (revision 418) +++ /tags/v1-0-3/doc/symbol_renaming.txt (revision 418) @@ -0,0 +1,23 @@ +# +# We want apps to be able to link with both serial NetCDF and Parallel-NetCDF, +# so we had to alter some symbols in the library. The following list is a +# start at documenting the changes. I found such a list helpful when merging +# netcdf-3.5 patches to pnetcdf +# + +serial parallel +------------------------- +ncx_len_NC ncmpii_hdr_len_NC +ncx_put_NC ncmpii_hdr_put_NC +nc_get_NC ncmpii_hdr_get_NC +ncx_get_size_t ncmpix_get_size_t +new_NC ncmpii_new_NC +v1h_get_NC_attarray hdr_len_NC_attarray +ncx_len_NC_var hdr_len_NC_var +ncx_len_NC_vararray hdr_len_NC_vararray +check_v1hs hdr_check_buffer +struct v1hs struct bufferinfo +NC_* ncmpii_NC_* +nc__ +ncx_* ncmpix_* + Index: /tags/v1-0-3/doc/netcdf-api.bbl =================================================================== --- /tags/v1-0-3/doc/netcdf-api.bbl (revision 2) +++ /tags/v1-0-3/doc/netcdf-api.bbl (revision 2) @@ -0,0 +1,10 @@ +\begin{thebibliography}{1} + +\bibitem{thakur:romio} +Rajeev Thakur, William Gropp, and Ewing Lusk. +\newblock Data sieving and collective {I/O} in {ROMIO}. +\newblock In {\em Proceedings of the Seventh Symposium on the Frontiers of + Massively Parallel Computation}, pages 182--189. IEEE Computer Society Press, + February 1999. + +\end{thebibliography} Index: /tags/v1-0-3/doc/porting_notes.txt =================================================================== --- /tags/v1-0-3/doc/porting_notes.txt (revision 582) +++ /tags/v1-0-3/doc/porting_notes.txt (revision 582) @@ -0,0 +1,48 @@ + + these are some rough notes for porting code from the serial netcdf api to + the pnetcdf API. Pnetcdf is very similar but there are some changes that + have to be made: + + +. the nc_* functions are called ncmpi_* + +. the nf_* functions are called nfmpi_* + +. ncmpi_open takes a communicator and an info structure, in addition to the + parameters in the serial nc_open() + +For example: + status = nc_open(path, NC_NOWRITE, &ncid); +becomes + status = ncmpi_open(MPI_COMM_WORLD, path, NC_NOWRITE, + MPI_INFO_NULL, &ncid); + +. if you make any independent calls ( those not ending in _all), you must put + yourself into independent data mode with ncmpi_begin_indep_data(ncid) and + ncmpi_end_indep_data(ncid) + +. FILL_DOUBLE and FILL_FLOAT are called NC_FILL_DOUBLE and NC_FILL_FLOAT + respectively. We do not define these NetCDF-2.x era constants in pnetcdf. + +. #include . If you want, define a communicator. MPI_COMM_WORLD + should work ok for most things. + +. somewhere near main, call MPI_Init(): pnetcdf won't do that for you. + +. pnetcdf does not implement nc_advise + +. pnetcdf does not support all types that serial netcdf supports. see + src/lib/TODO for more specifics + +. If for some reason your code uses 'ptrdiff_t' types, consider using + MPI_Offset types + +. likewise, in many places where serial netcdf takes size_t types, we instead + take MPI_Offset types + +. Fortran users should '#include ' and '#include "pnetcdf.inc"'. + Don't use the Fortran INCLUDE directive + +. Fortran dimension sizes should be declared as type + INTEGER(KIND=MPI_OFFSET_KIND) + Index: /tags/v1-0-3/doc/netcdf-api.tex =================================================================== --- /tags/v1-0-3/doc/netcdf-api.tex (revision 561) +++ /tags/v1-0-3/doc/netcdf-api.tex (revision 561) @@ -0,0 +1,996 @@ +\documentclass[10pt]{article} +% \usepackage{utopia} + +\pagestyle{plain} + +\addtolength{\hoffset}{-2cm} +\addtolength{\textwidth}{4cm} + +\addtolength{\voffset}{-1.5cm} +\addtolength{\textheight}{3cm} + +\setlength{\parindent}{0pt} +\setlength{\parskip}{11pt} + +\title{A Parallel API for Creating and Reading NetCDF Files} + +\begin{document} + +\maketitle + +\begin{abstract} +Scientists recognize the importance of portable and efficient mechanisms for +storing datasets created and used by their applications. NetCDF is one such +mechanism and is popular in a number of applicaiton domains because of its +availability on a wide variety of platforms and its easy to use API. However, +this API was originally designed for use in serial codes, and so the semantics +of the interface are not designed to allow for high performance parallel +access. + +In this work we present a new API for creating and reading NetCDF datasets, +the \emph{Parallel NetCDF API}. This interface builds on the original NetCDF +interface and defines semantics for parallel access to NetCDF datasets. The +interface is built on top of MPI-IO, allowing for further performance gains +through the use of collective I/O optimizations that already exist in MPI-IO +implementations. + +\end{abstract} + +\section{Introduction} + +NetCDF is a popular package for storing data files in scientific applications. +NetCDF consists of both an API and a portable file format. The API provides a +consistent interface for access NetCDF files across multiple platforms, while +the NetCDF file format guarantees data portability. + +The NetCDF API provides a convenient mechanism for a single process to define +and access variables and attributes in a NetCDF file. However, it does not +define a parallel access mechanism. In particular there is no mechanism for +concurrently writing to a NetCDF data file. Because of this, parallel +applications operating on NetCDF files must serialize access. This is +typically accomplished by shipping all data to and from a single process that +performs NetCDF operations. This mode of access is both cumbersome to the +application programmer and considerably slower than parallel access to the +NetCDF file. This mode can be particularly inconvenient when data set sizes +exceed the size of available memory on a single node; in this case the data +must be split into pieces to be shipped and written. + +In this document we propose an alternative API for accessing NetCDF format +files in a parallel application. This API allows all processes in a parallel +application to access the NetCDF file simultaneously, which is considerably +more convenient than the serial API and allows for significantly higher +performance. + +\emph{Note subset of interface that we are implementing, including both what +types we support and any functions that we might be leaving out.} + +\section{Preliminaries} + +In MPI, communicators are typically used to describe collections of processes +to MPI calls (e.g. the collective MPI-1 calls). In our parallel NetCDF API we +will similarly use a communicator to denote a collection of MPI processes that +will access a NetCDF file. By describing this collection of processes, we +provide the underlying implementation (of our parallel NetCDF API) with +information that it can use to ensure that the file is kept in a consistent +state. + +Further, by using the collective operations provided in our parallel NetCDF +API (ones in which all processes in this collection participate), application +programmers provide the underlying implementation with an opportunity to +further optimize access to the NetCDF file. These optimizations are performed +without further intervention by the application programmer and have been +proven to provide huge performance wins in multidimensional dataset access \cite{thakur:romio}, +exactly the kinds of accesses used in NetCDF. + +All this said, the original NetCDF interface is made available with a minimum +of changes so that users migrating from the original NetCDF interface will +have little trouble moving to this new, parallel NetCDF interface. + +The decision to slightly modify the API was not made lightly. It is +relatively trivial to port NetCDF to use MPI-IO through the use of the MPI-IO +independent access calls. However, it was only though adding this concept of +a collection of processes simultaneously accessing the file and adding +collective access semantics that we could hope to eliminate the serialization +step necessary in the original API or gain the performance advantages +available from the use of collective optimizations. Thus our performance +requirements mandated these small adjustments. + +% Finally, some of the calls in our API utilize MPI datatypes. These datatypes +% allow one to describe noncontiguous regions of data (in this case memory +% regions) as an endpoint of a data transfer. + +\section{Parallel NetCDF API} + +The NetCDF interface breaks access into two \emph{modes}, ``define'' mode and +``data'' mode. The define mode is used to describe the data set to be stored, +while the data mode is used for storing and retrieving data values. + +We maintain these modes and (for the most part) maintain the operations when +in define mode. We will discuss the API for opening and closing a dataset and +for moving between modes first, next cover inquiry functions, then cover the +define mode, attribute functions, and finally discuss the API for data mode. + +% +% PREFIX +% +We will prefix our C interface calls with ``ncmpi'' and our Fortran interface +calls with ``nfmpi''. This ensures no naming clashes with existing NetCDF +libraries and does not conflict with the desire to reserve the ``MPI'' prefix +for functions that are part of the MPI standard. + +All of our functions return integer NetCDF status values, just as the original +NetCDF interface does. + +We will only discuss points where our interface deviates from the original +interface in the following sections. A complete function listing is included +in Appendix A. + +\subsection{Variable and Parameter Types} + +% +% MPI_Offset +% +Rather than using \texttt{size\_t} types for size parameters passed in to our +functions, we choose to use \texttt{MPI\_Offset} type instead. For many +systems \texttt{size\_t} is a 32-bit unsigned value, which limits the maximum +range of values to 4~GBytes. The \texttt{MPI\_Offset} is typically a 64-bit +value, so it does not have this limitation. This gives us room to extend the +file size capabilities of NetCDF at a later date. + +\emph{Add mapping of MPI types to NetCDF types.} + +\emph{Is NetCDF already exactly in external32 format?} + +\subsection{Dataset Functions} + +As mentioned before, we will define a collection of processes that are +operating on the file by passing in a MPI communicator. This communicator is +passed in the call to \texttt{ncmpi\_create} or \texttt{ncmpi\_open}. These +calls are collective across all processes in the communicator. The second +additional parameter is an \texttt{MPI\_Info}. This is used to pass hints in +to the implementation (e.g. expected access pattern, aggregation +information). The value \texttt{MPI\_INFO\_NULL} may be passed in if the user +does not want to take advantage of this feature. + +\begin{verbatim} +int ncmpi_create(MPI_Comm comm, + const char *path, + int cmode, + MPI_Info info, + int *ncidp) + +int ncmpi_open(MPI_Comm comm, + const char *path, + int omode, + MPI_Info info, + int *ncidp) +\end{verbatim} + +\subsection{Define Mode Functions} + +\emph{All define mode functions are collective} (see Appendix B for +rationale). + +All processes in the communicator must call them with the same values. At the +end of the define mode the values passed in by all processes are checked to +verify that they match, and if they do not then an error is returned from the +\texttt{ncmpi\_enddef}. + + +\subsection{Inquiry Functions} + +\emph{These calls are all collective operations} (see Appendix B for +rationale). + +As in the original NetCDF interface, they may be called from either define or +data mode. \emph{ They return information stored prior to the last open, +enddef, or sync.} + +% In the original NetCDF interface the inquiry functions could be called from +% either data or define mode. To aid in the implementation of these functions +% in a parallel library, \emph{inquiry functions may only be called in data mode +% in the parallel NetCDF API}. They return information stored prior to the last +% open, enddef, or sync. This ensures that the NetCDF metadata need only be +% kept up-to-date on all nodes when in data mode. +% + +\subsection{Attribute Functions} + +\emph{These calls are all collective operations} (see Appendix B for +rationale). + +Attributes in NetCDF are intended for storing scalar or vector values that +describe a variable in some way. As such the expectation is that these +attributes will be small enough to fit into memory. + +In the original interface, attribute operations can be performed in either +define or data mode; however, it is possible for attribute operations that +modify attributes (e.g. copy or create attributes) to fail if in data mode. +This is possible because such operations can cause the amount of space needed +to grow. In this case the cost of the operation can be on the order of a copy +of the entire dataset. We will maintain these semantics. + +\subsection{Data Mode Functions} + +The most important change from the original NetCDF interface with respect to +data mode functions is the split of data mode into two distinct modes: +\emph{collective data mode} and \emph{independent data mode}. \emph{By default when +a user calls \texttt{ncmpi\_enddef} or \texttt{ncmpi\_open}, the user will be +in collective data mode.} The expectation is that most users will be using the +collective operations; these users will never need to switch to independent +data mode. In collective data mode, all processes must call the same function +on the same ncid at the same point in the code. Different parameters for +values such as start, count, and stride, are acceptable. Knowledge that all +processes will be calling the function allows for additional optimization +under the API. In independent mode processes do not need to coordinate calls +to the API; however, this limits the optimizations that can be applied to I/O operations. + +A pair of new dataset operations \texttt{ncmpi\_begin\_indep\_data} and +\texttt{ncmpi\_end\_indep\_data} switch into and out of independent data mode. +These calls are collective. Calling \texttt{ncmpi\_close} or +\texttt{ncmpi\_redef} also leaves independent data mode. + +\begin{verbatim} +int ncmpi_begin_indep_data(int ncid) + +int ncmpi_end_indep_data(int ncid) +\end{verbatim} + +The separation of the data mode into two distinct data modes is necessary to +provide consistent views of file data when moving between MPI-IO collective +and independent operations. + +We have chosen to implement two collections of data mode functions. The first +collection closely mimics the original NetCDF access functions and is intended +to serve as an easy path of migration from the original NetCDF interface to +the parallel NetCDF interface. We call this subset of our parallel NetCDF +interface the \emph{high level data mode} interface. + +The second collection uses more MPI functionality in order to provide better +handling of internal data representations and to more fully expose the +capabilities of MPI-IO to the application programmer. All of the first +collection will be implemented in terms of these calls. We will denote this +the \emph{flexible data mode} interface. + +In both collections, both independent and collective operations are provided. +Collective function names end with \texttt{\_all}. They are collective across +the communicator associated with the ncid, so all those processes must call +the function at the same time. + +Remember that in all cases the input data type is converted into the +appropriate type for the variable stored in the NetCDF file. + +\subsubsection{High Level Data Mode Interface} + +The independent calls in this interface closely resemble the NetCDF data mode +interface. The only major change is the use of \texttt{MPI\_Offset} types in +place of \texttt{size\_t} types, as described previously. + +The collective calls have the same arguments as their independent +counterparts, but they must be called by all processes in the communicator +associated with the ncid. + +Here are the example prototypes for accessing a strided subarray of a variable +in a NetCDF file; the remainder of the functions are listed in Appendix A. + +In our initial implementation the following data function types will be +implemented for independent access: single data value read and write (var1), +entire variable read and write (var), array of values read and write (vara), +and subsampled array of values read and write (vars). Collective versions of +these types will also be provided, with the exception of a collective entire +variable write; semantically this doesn't make sense. + +We could use the same function names for both independent and collective +operations (relying instead on the mode associated with the ncid); however, we +feel that the interface is cleaner, and it will be easier to detect bugs, with +separate calls for independent and collective access. + +% \textbf{Strided Subarray Access} +% +Independent calls for writing or reading a strided subarray of values to/from +a NetCDF variable (values are contiguous in memory): +\begin{verbatim} +int ncmpi_put_vars_uchar(int ncid, + int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + const unsigned char *up) + +int ncmpi_get_vars_uchar(int ncid, + int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *up) +\end{verbatim} + +Collective calls for writing or reading a strided subarray of values to/from a +NetCDF variable (values are contiguous in memory). +\begin{verbatim} +int ncmpi_put_vars_uchar_all(int ncid, + int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *up) + +int ncmpi_get_vars_uchar_all(int ncid, + int varid, + const MPI_Offset start[], + const MPI_Offset count[], + const MPI_Offset stride[], + unsigned char *up) +\end{verbatim} + +\emph{Note what calls are and aren't implemented at this time.} + +\subsubsection{Flexible Data Mode Interface} + +This smaller set of functions is all that is needed to implement the data mode +functions. These are also made available to the application programmer. + +The advantage of these functions is that they allow the programmer to use MPI +datatypes to describe the in-memory organization of the values. The only +mechanism provides in the original NetCDF interface for such a description is +the mapped array calls. Mapped arrays are a suboptimal method of describing +any regular pattern in memory. + +In all these functions the varid, start, count, and stride values refer to the +data in the file (just as in a NetCDF vars-type call). The buf, count, and +datatype fields refer to data in memory. + +Here are examples for subarray access: +\begin{verbatim} +int ncmpi_put_vars(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + const void *buf, + int count, + MPI_Datatype datatype) + +int ncmpi_get_vars(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype) + +int ncmpi_put_vars_all(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype) + +int ncmpi_get_vars_all(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype) +\end{verbatim} + + +\subsubsection{Mapping Between NetCDF and MPI Types} + +It is assumed here that the datatypes passed to the flexible NetCDF interface +use only one basic datatype. For example, the datatype can be arbitrarily +complex, but it cannot consist of both \texttt{MPI\_FLOAT} and +\texttt{MPI\_INT} values, but only one of these basic types. + +\emph{Describe status of type support.} + + +\subsection{Missing} + +Calls that were in John M.'s list but that we haven't mentioned here yet. + +Attribute functions, strerror, text functions, get\_vara\_text (?). + +\section{Examples} + +This section will hopefully soon hold some examples, perhaps based on writing +out the 1D and 2D Jacobi examples in the Using MPI book using our interface? + +\section{Implementation Notes} + +Here we will keep any particular implementation details. As the +implementation matures, this section should discuss implementation decisions. + +One trend that will be seen throughout here is the use of collective I/O +routines when it would be possible to use independent operations. There are +two reasons for this. First, for some operations (such as reading the +header), there are important optimizations that can be made to more +efficiently read data from the I/O system, especially as the number of NetCDF +application processes increases. Second, the use of collective routines +allows for the use of aggregation routines in the MPI-IO implementation. This +allows us to redirect I/O to nodes that have access to I/O resources in +systems where not all processes have access. This isn't currently possible +using the independent I/O calls. + +See the ROMIO User's Guide for more information on the aggregation hints, in +particular the \texttt{cb\_config\_list} hint. + +\subsection{Questions for Users on Implementation} +\begin{itemize} +\item Is this emphasis on collective operations appropriate or problematic? +\item Is C or Fortran the primary language for NetCDF programs? +\end{itemize} + +\subsection{I/O routines} + +All I/O within our implementation will be performed through MPI-IO. + +No temporary files will be created at any time. + +% +% HEADER I/O +% +\subsection{Header I/O} + +\emph{It is assumed that headers are too small to benefit from parallel I/O.} + +All header updates will be performed with collective I/O, but only rank 0 will +provide any input data. This is important because only through the collective +calls can our \texttt{cb\_config\_list} hint be used to control what hosts +actually do writing. Otherwise we could pick some arbitrary process to do +I/O, but we have no way of knowing if that was a process that the user +intended to do I/O in the first place (thus that process might not even be +able to write to the file!) + +Headers are written all at once at \texttt{ncmpi\_enddef}. + +Likewise collective I/O will be used when reading the header, which should +simply be used to read the entire header to everyone on open. + +\emph{First cut might not do this.} + +\subsection{Code Reuse} +We will not reuse any NetCDF code. This will give us an opportunity to leave +out any code pertaining to optimizations on specific machines (e.g. Cray) that +we will not need and, more importantly, cannot test. + +\subsection{Providing Independent and Collective I/O} +In order to make use of \texttt{MPI\_File\_set\_view} for both independent and +collective NetCDF operations, we will need to open the NetCDF file separately +for both, with the input communicator for collective I/O and with +MPI\_COMM\_SELF for independent I/O. However, we can defer opening the file +for independent access until an independent access call is made if we like. +This can be an important optimization as we scale. + +Synchronization when switching between collective and independent access is +mandatory to ensure correctness under the MPI I/O model. + +\subsection{Outline of I/O} + +Outline of steps to I/O: +\begin{itemize} +\item MPI\_File is extracted from ncid +\item variable type is extracted from varid +\item file view is created from: + \begin{itemize} + \item metadata associated with ncid + \item variable index info, array size, limited/unlimited, type from varid + \item start/count/stride info + \end{itemize} +\item datatype/count must match number of elements specified by + start/count/stride +\item status returns normal mpi status information, which is mapped to a + NetCDF error code. +\end{itemize} + + +\section{Future Work} + +Since MPI-IO has the capability to perform nonblocking operations, it makes +sense to provide a NetCDF interface that exposes this capability: + +\begin{verbatim} +ncmpi_iput_vars(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype, + MPI_Request *request); + +ncmpi_iget_vars(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype, + MPI_Request *request); + +int ncmpi_wait(MPI_Request *request, + MPI_Status *status); + +int ncmpi_test(MPI_Request *request, + int *flag, + MPI_Status *status); +\end{verbatim} + +% +% BIBLIOGRAPHY +% +\bibliography{./pario} +\bibliographystyle{plain} + +% +% APPENDIX A: FUNCTION LISTING +% +\section*{Appendix A: C API Listing} + +% +% DATASET FUNCTIONS +% +\subsection*{A.1 Dataset Functions} + +\begin{verbatim} +int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp); + +int ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp); + +int ncmpi_enddef(int ncid); + +int ncmpi_redef(int ncid); + +int ncmpi_get_file_info(int ncid, MPI_Info *info_used); + +int ncmpi_sync(int ncid); + +int ncmpi_abort(int ncid); + +int ncmpi_begin_indep_data(int ncid); + +int ncmpi_end_indep_data(int ncid); + +int ncmpi_close(int ncid); +\end{verbatim} + +% +% INQUIRY FUNCTIONS +% +\subsection*{A.2 Inquiry Functions} + +\begin{verbatim} +int ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); + +int ncmpi_inq_ndims(int ncid, int *ndimsp); + +int ncmpi_inq_nvars(int ncid, int *nvarsp); + +int ncmpi_inq_natts(int ncid, int *ngattsp); + +int ncmpi_inq_unlimdim(int ncid, int *unlimdimidp); + +int ncmpi_inq_dimid(int ncid, const char *name, int *idp); + +int ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *lenp); + +int ncmpi_inq_dimname(int ncid, int dimid, char *name); + +int ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp); + +int ncmpi_inq_var(int ncid, int varid, char *name, nc_type *xtypep, + int *ndimsp, int *dimidsp, int *nattsp); + +int ncmpi_inq_varid(int ncid, const char *name, int *varidp); + +int ncmpi_inq_varname(int ncid, int varid, char *name); + +int ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep); + +int ncmpi_inq_varndims(int ncid, int varid, int *ndimsp); + +int ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp); + +int ncmpi_inq_varnatts(int ncid, int varid, int *nattsp); + +\end{verbatim} + +% +% DEFINE FUNCTIONS +% +\subsection*{A.3 Define Mode Functions} + +\begin{verbatim} +int ncmpi_def_dim(int ncid, const char *name, MPI_Offset len, int *idp); + +int ncmpi_def_var(int ncid, const char *name, nc_type xtype, int ndims, + const int *dimidsp, int *varidp); + +int ncmpi_rename_dim(int ncid, int dimid, const char *name); + +int ncmpi_rename_var(int ncid, int varid, const char *name); + +\end{verbatim} +% +% ATTRIBUTE FUNCTIONS +% +\subsection*{A.4 Attribute Functions} + +\begin{verbatim} +int ncmpi_inq_att(int ncid, int varid, const char *name, nc_type *xtypep, + MPI_Offset *lenp); + +int ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp); + +int ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep); + +int ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp); + +int ncmpi_inq_attname(int ncid, int varid, int attnum, char *name); + +int ncmpi_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, + int varid_out); + +int ncmpi_rename_att(int ncid, int varid, const char *name, const char *newname); + +int ncmpi_del_att(int ncid, int varid, const char *name); + +int ncmpi_put_att_text(int ncid, int varid, const char *name, MPI_Offset len, + const char *op); + +int ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip); + +int ncmpi_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype, + MPI_Offset len, const unsigned char *op); + +int ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip); + +int ncmpi_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, + MPI_Offset len, const signed char *op); + +int ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *ip); + +int ncmpi_put_att_short(int ncid, int varid, const char *name, nc_type xtype, + MPI_Offset len, const short *op); + +int ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip); + +int ncmpi_put_att_int(int ncid, int varid, const char *name, nc_type xtype, + MPI_Offset len, const int *op); + +int ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip); + +int ncmpi_put_att_long(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const long *op); + +int ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip); + +int ncmpi_put_att_float(int ncid, int varid, const char *name, + nc_type xtype, MPI_Offset len, const float *op); + +int ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip); + +int ncmpi_put_att_double(int ncid, int varid, const char *name, nc_type xtype, + MPI_Offset len, const double *op); + + +int ncmpi_get_att_double(int ncid, int varid, const char *name, double *ip); +\end{verbatim} +% +% DATA FUNCTIONS +% +\subsection*{A.5 Data Mode Functions} + +Recall that the data mode functions are split into the High Level data mode interface and the +Flexible data mode interface. + +\subsubsection*{A.5.1 High Level Data Mode Interface} + +The High Level functions most closely mimic the original NetCDF data mode interface. + +\emph{What about the single variable and varm functions? Are they important?} + +\begin{verbatim} +int ncmpi_put_vara_short_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const short *op); + +int ncmpi_put_vara_short(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const short *op); + +int ncmpi_put_vara_int_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const int *op); + +int ncmpi_put_vara_int(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const int *op); + +int ncmpi_put_vara_float_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const float *op); + +int ncmpi_put_vara_float(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const float *op); + +int ncmpi_put_vara_double_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const double *op); + +int ncmpi_put_vara_double(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const double *op); + +int ncmpi_get_vara_short_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], short *ip); + +int ncmpi_get_vara_short(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], short *ip); + +int ncmpi_get_vara_int_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], int *ip); + +int ncmpi_get_vara_int(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], int *ip); + +int ncmpi_get_vara_float_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], float *ip); + +int ncmpi_get_vara_float(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], float *ip); + +int ncmpi_get_vara_double_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], double *ip); + +int ncmpi_get_vara_double(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], double *ip); + +int ncmpi_put_vars_short_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const short *op); + +int ncmpi_put_vars_short(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const short *op); + +int ncmpi_put_vars_int_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const int *op); + +int ncmpi_put_vars_int(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const int *op); + +int ncmpi_put_vars_float_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const float *op); + +int ncmpi_put_vars_float(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const float *op); + +int ncmpi_put_vars_double_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const double *op); + +int ncmpi_put_vars_double(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const double *op); + +int ncmpi_get_vars_short_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + short *ip); + +int ncmpi_get_vars_short(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + short *ip); + +int ncmpi_get_vars_int_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + int *ip); + +int ncmpi_get_vars_int(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], int *ip); + +int ncmpi_get_vars_float_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + float *ip); + +int ncmpi_get_vars_float(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], float *ip); + +int ncmpi_get_vars_double_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + double *ip); + +int ncmpi_get_vars_double(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + double *ip); +\end{verbatim} + +\subsubsection*{A.5.2 Flexible Data Mode Interface} + +Note that there are considerably fewer functions in the flexible data mode +inteface, because these functions can handle all different types with the same +call. All of the high level functions are written in terms of these +functions. + +\begin{verbatim} +int ncmpi_put_vara_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const void *buf, int bufcount, + MPI_Datatype datatype); + +int ncmpi_get_vara_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], void *buf, int bufcount, + MPI_Datatype datatype); + +int ncmpi_put_vara(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const void *buf, int bufcount, + MPI_Datatype datatype); + +int ncmpi_get_vara(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], void *buf, int bufcount, + MPI_Datatype datatype); + +int ncmpi_put_vars_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], + const void *buf, int bufcount, MPI_Datatype datatype); + +int ncmpi_get_vars_all(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], void *buf, + int bufcount, MPI_Datatype datatype); + +int ncmpi_put_vars(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], const void *buf, + int bufcount, MPI_Datatype datatype); + +int ncmpi_get_vars(int ncid, int varid, const MPI_Offset start[], + const MPI_Offset count[], const MPI_Offset stride[], void *buf, + int bufcount, MPI_Datatype datatype); +\end{verbatim} +% +% APPENDIX B: RATIONALE +% +\section*{Appendix B: Rationale} + +This section covers the rationale behind our decisions on API specifics. + +% +% define mode function semantics +% +\subsection*{B.1 Define Mode Function Semantics} + +There are two options to choose from here, either forcing a single process to +make these calls (funnelled) or forcing all these calls to be collective with +the same data. Note that making them collective does \emph{not} imply any +communication at the time the call is made. + +Both of these options allow for better error detection than what we +previously described (functions independent, anyone could call, only node +0's data was used). Error detection could be performed at the end of the +define mode to minimize costs. + +In fact, it is only fractionally more costly to implement collectives than +funneled (including the error detection). To do this one simply bcast's +process 0's values out (which one would have to do anyway) and then +allgathers a single char or int from everyone indicating if there was a +problem. + +There has to be some synchronization at the end of the define mode in any +case, so this extra error detection comes at an especially low cost. + +\subsection*{B.2 Attribute and Inquiry Function Semantics} + +There are similar options here to the ones for define mode functions. + +One option would be to make these functions independent. This would be easy +for read operations, but would be more difficult for write operations. In +particular we would need to gather up modifications at some point in order to +distribute them out to all processes. Ordering of modifications might also be +an issue. Finally, we would want to constrain use of these independent +operations to the define mode so that we would have an obvious point at which +to perform this collect and distribute operation (e.g. \texttt{ncmpi\_enddef}). + +Another option would be to make all of these functions collective. This is an +unnecessary constraint for the read operations, but it helps in implementing +the write operations (we can distribute modifications right away) and allows +us to maintain the use of these functions outside define mode if we wish. +This is also more consistent with the SPMD model that (we think) our users are +using. + +The final option would be to allow independent use of the read operations but +force collective use of the write operations. This would result in confusing +semantics. + +For now we will implement the second option, all collective operation. Based +on feedback from users we will consider relaxing this constraint. + +\subsubsection*{Questions for Users Regarding Attribute and Inquiry Functions} +\begin{itemize} +\item Are attribute calls used in data mode? +\item Is it inconvenient that the inquiry functions are collective? +\end{itemize} + +\subsection*{B.3 Splitting Data Mode into Collective and Independent Data Modes} + +In both independent and collective MPI-IO operations, it is important to be +able to set the file view to allow for noncontiguous file regions. However, +since the \texttt{MPI\_File\_set\_view} is a collective operation, it is +impossible to use a single file handle to perform collective I/O and still be +able to arbitrarily reset the file view before an independent operation +(because all the processes would need to participate in the file set view). + +For this reason it is necessary to have two file handles in the case where +both independent and collective I/O will be performed. One file handle is +opened with \texttt{MPI\_COMM\_SELF} and is used for independent operations, +while the other is opened with the communicator containing all the processes +for the collective operations. + +It is difficult if not impossible in the general case to ensure consistency of +access when a collection of processes are using multiple MPI\_File handles to +access the same file with mixed independent and collective operations. +However, if explicit and collective synchronization points are introduced +between phases where collective and independent I/O operations will be +performed, then the correct set of operations to ensure a consistent view can +be inserted at this point. + +\emph{Does this explanation make any sense? I think we need to document this.} + +\subsection*{B.4 Even More MPI-Like Data Mode Functions} + +Recall that our flexible NetCDF interface has functions such as: +\begin{verbatim} +int ncmpi_put_vars(int ncid, + int varid, + MPI_Offset start[], + MPI_Offset count[], + MPI_Offset stride[], + void *buf, + int count, + MPI_Datatype datatype) +\end{verbatim} + +It is possible to move to an even more MPI-like interface by using an MPI +datatype to describe the file region in addition to using datatypes for the +memory region: +\begin{verbatim} +int ncmpi_put(int ncid, + int varid, + MPI_Datatype file_dtype, + void *buf, + int count, + MPI_Datatype mem_dtype) +\end{verbatim} + +At first glance this looks rather elegant. However, this isn't as clean as it +seems. The \texttt{file\_dtype} in this case has to describe the variable +layout \emph{in terms of the variable array}, not in terms of the file, +because the user doesn't know about the internal file layout. So the +underlying implementation would need to tear apart \texttt{file\_dtype} and +rebuild a new datatype, on the fly, that corresponded to the data layout in +the file as a whole. This is complicated by the fact that +\texttt{file\_dtype} could be arbitrarily complex. + +The flexible NetCDF interface parameters, \texttt{start}, \texttt{count}, and +\texttt{stride} must also be used to build a file type, but the process is +considerably simpler. + +\subsection*{B.5 MPI and NetCDF Types} + +\subsubsection*{Questions for Users Regarding MPI and NetCDF Types} + +\begin{itemize} +\item How do users use text strings? +\item What types are our users using? +\end{itemize} + +\end{document} + + + + + + + + Index: /tags/v1-0-3/doc/Makefile =================================================================== --- /tags/v1-0-3/doc/Makefile (revision 2) +++ /tags/v1-0-3/doc/Makefile (revision 2) @@ -0,0 +1,6 @@ +all: doc +doc: + latex netcdf-api.tex + latex netcdf-api.tex +clean: + rm *.dvi *.log *.aux Index: /tags/v1-0-3/macros.make.in =================================================================== --- /tags/v1-0-3/macros.make.in (revision 567) +++ /tags/v1-0-3/macros.make.in (revision 567) @@ -0,0 +1,92 @@ +# $Id$ + +# The purpose of this file is to contain common make(1) macros. +# It should be processed by every execution of that utility. + + +# POSIX shell. Shouldn't be necessary -- but is under IRIX 5.3. +SHELL = /bin/sh + + +# Installation Directories: +SRCDIR = @SRCDIR@ +prefix = @prefix@ +exec_prefix = $(prefix) +INCDIR = $(exec_prefix)/include +LIBDIR = $(exec_prefix)/lib +BINDIR = $(exec_prefix)/bin +MANDIR = $(prefix)/man + + +# Preprocessing: +M4 = @M4@ +M4FLAGS = @M4FLAGS@ +CPP = @CPP@ +CPPFLAGS = $(INCLUDES) $(DEFINES) @CPPFLAGS@ +FPP = @FPP@ +FPPFLAGS = $(CPPFLAGS) +CXXCPPFLAGS = $(CPPFLAGS) + + +# Compilation: +CC = @MPICC@ +CXX = @CXX@ +FC = @MPIF77@ +F90 = @F90@ +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +FFLAGS = @FFLAGS@ +F90FLAGS = @F90FLAGS@ +NETCDF.MOD = @NETCDF_MOD@ +CC_MAKEDEPEND = @CC_MAKEDEPEND@ +COMPILE.c = $(CC) -c $(CFLAGS) $(CPPFLAGS) +COMPILE.cxx = $(CXX) -c $(CXXFLAGS) $(CXXCPPFLAGS) +COMPILE.f = $(FC) -c $(FFLAGS) +COMPILE.F90 = $(F90) -c $(F90FLAGS) +# The following command isn't available on some systems; therefore, the +# `.F.o' rule is relatively complicated. +COMPILE.F = @COMPILE_F@ + + +# Linking: +MATHLIB = @MATHLIB@ +FLIBS = @FLIBS@ +F90LIBS = @F90LIBS@ +LIBS = @LDFLAGS@ @LIBS@ +F90LDFLAGS = $(LDFLAGS) +LINK.c = $(CC) -o $@ $(CFLAGS) $(LDFLAGS) +LINK.cxx = $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) +LINK.F = $(FC) -o $@ $(FFLAGS) $(FLDFLAGS) +LINK.f = $(FC) -o $@ $(FFLAGS) $(FLDFLAGS) +LINK.F90 = $(F90) -o $@ $(F90FLAGS) $(F90LDFLAGS) + + +# Manual pages: +WHATIS = @WHATIS@ +# The following macro should be empty on systems that don't +# allow users to create their own manual-page indexes. +MAKEWHATIS_CMD = @MAKEWHATIS_CMD@ + + +# Misc. Utilities: +AR = @AR@ +ARFLAGS = @ARFLAGS@ +RANLIB = @RANLIB@ +TARFLAGS = -chf + + +# Dummy macros: used only as placeholders to silence GNU make. They are +# redefined, as necessary, in subdirectory makefiles. +HEADER = dummy_header +HEADER1 = dummy_header1 +HEADER2 = dummy_header2 +HEADER3 = dummy_header3 +LIBRARY = dummy_library.a +MANUAL = dummy_manual +PROGRAM = dummy_program + + +# Distribution macros: +FTPDIR = /home/ftp/pub/$(PACKAGE) +FTPBINDIR = @FTPBINDIR@ +VERSION = dummy_version Index: /tags/v1-0-3/INSTALL =================================================================== --- /tags/v1-0-3/INSTALL (revision 137) +++ /tags/v1-0-3/INSTALL (revision 137) @@ -0,0 +1,74 @@ +To INSTALL parallel netCDF library: + + 1. autoconf (only necessary if you make changes to configure.in) + + 2. ./configure --prefix= --with-mpi=/path/to/implementation + the --with-mpi argument should specify the prefix of where the mpi + implementation was installed. If your mpicc is in + /usr/local/mpich-1.2.3/bin/mpicc then use the prefix + --with-mpi=/usr/local/mpich-1.2.3 + + NOTE: If configure cannot find your MPI implementation's C and/or + Fortran compilers, define *both* the MPICC and MPIF77 + environment variables to be the name of those compilers. The + configure script will then use those values instead of trying + to guess. + + 3. make + + We have tried to make the Makefiles platform-independent. + However, each platform has its own make quirks: if you run into + problems, please send a report to the developers at + parallel-netcdf@mcs.anl.gov. If you have GNU Make, try using + that. + + 4. make install + +IF THIS DOESN'T WORK: + +Autoconf should do the right thing: using the system compiler to perform +autoconf tests and then use the MPI compilers to build parallel-netcdf. +If you need to set specific flags for a platform, and autoconf does not +set them for you, then you will have to set some environment variables +to help out the configure script. Here are some suggested settings: + + For Solaris + MPICC=mpicc + + For SGI Origin2000 + MPICC = mpicc + ------------ OR ------------- + CC='/bin/cc -64 -mips4 -lmpi' + CPPFLAGS=-DNDEBUG + CFLAGS=-O + FC='/bin/f90 -64' + FFLAGS=-O + F90='/bin/f90 -64' + CXX='/bin/CC -64' + CXXFLAGS=-O + + For Linux + MPICC=mpicc + CPPFLAGS='-DNDEBUG -Df2cFortran' + CFLAGS=-O + CXX=g++ + FFLAGS='-O -W' + + For IBM SP-2 + MPICC mpcc_r + MPIF77 /bin/mpxlf_r + F90 /bin/mpxlf90_r + F90FLAGS -qsuffix=f=f90 + CXX /bin/mpxlC_r + ------------- OR ------------- + CC xlc + FC /bin/xlf + F90 /bin/xlf90 + F90FLAGS -qsuffix=f=f90 + CXX /bin/xlC + then manually edit macros.make: + CC = mpcc_r + FC = mpxlf_r + F90 = mpxlf90_r + F90FLAGS = -qsuffix=f=f90 + CXX = mpxlC_r Index: /tags/v1-0-3/rules.make =================================================================== --- /tags/v1-0-3/rules.make (revision 505) +++ /tags/v1-0-3/rules.make (revision 505) @@ -0,0 +1,224 @@ +# $Id$ + +# The purpose of this file is to contain common make(1) rules. +# It should be processed by every execution of the that utility. + +.SUFFIXES: +.SUFFIXES: .a .o .i .f .c .cpp .F .y .l .m4 + + +################################################################################ +# Compilation (including preprocessing): + +.c.o: + $(COMPILE.c) $< + +.c.i: + $(CPP) $(CPPFLAGS) $< >$@ + +.cpp.o: + $(COMPILE.cxx) $< + +# Not all FORTRAN compilers support C-preprocessing of *.F files; ergo, a +# relatively complicated rule ensues. +.F.o: + @case "$(COMPILE.F)" in \ + '') \ + set -x; \ + $(FPP) $(FPPFLAGS) -C $*.F | grep -v '^#' >$*-tmp.f || \ + (rm $*-tmp.f ; exit 1); \ + $(COMPILE.f) -o $@ $*-tmp.f || (rm $*-tmp.f; exit 1); \ + rm $*-tmp.f; \ + ;; \ + *) \ + set -x; \ + $(COMPILE.F) $<; \ + ;; \ + esac + +.f.o: + $(COMPILE.f) $< + +#.F.f: +# $(FPP) $(FPPFLAGS) $*.F | grep -v '^#' >$*.f || (rm $*.f; exit 1) + +.m4.c: + $(M4) $(M4FLAGS) $< >$@ + +.m4.F: + $(M4) $(M4FLAGS) $< >$@ + + +################################################################################ +# Libraries: + +lib: $(LIBRARY) + +$(LIBRARY): $(LIB_OBJS) FORCE + $(AR) $(ARFLAGS) $@ $(LIB_OBJS) + $(RANLIB) $@ + +#------------------------------------------------------------------------------- +# Shared Libraries: +# +# Here only as a place holder and notebook. Don't try to use this stuff +# unless you really, really know what you're doing! (And even then we +# guarantee nothing!) +# +shared_library: + @case `uname -sr` in \ + HP-UX*) \ + $(MAKE) hpux_shared_library;; \ + IRIX*) \ + $(MAKE) irix_shared_library;; \ + Linux*) \ + $(MAKE) linux_shared_library;; \ + OSF1*) \ + $(MAKE) osf1_shared_library;; \ + 'SunOS 4'*) \ + $(MAKE) sunos4_shared_library;; \ + 'SunOS 5'*) \ + $(MAKE) sunos5_shared_library;; \ + *) \ + echo 1>&2 "Don't know how to make a shared library" \ + "on this system"; \ + exit 1;; \ + esac + +hpux_shared_library: + nm libpnetcdf.a | grep extern | grep entry | \ + awk '-F|' '{print $$1}' | sed 's/^/-u /' >symbols.log + ld -o $(LIBRARY:.a=.sl) -b -c symbols.log $(LIBRARY) + rm symbols.log +irix_shared_library: + ld -o $(LIBRARY:.a=.so) -shared -no_archive \ + -all $(LIBRARY) -none -lc -lC $(LIBS) +linux_shared_library: + ld -o $(LIBRARY:.a=.so) -shared --whole-archive $(LIBRARY) +osf1_shared_library: + ld -o $(LIBRARY:.a=.so) -shared -all $(LIBRARY) +sunos4_shared_library: + undefopts=`/bin/nm $(LIBRARY) | awk '$$2~/^T$$/{print $$3}' | \ + sed 's/^/-u /'` && \ + ld -o $(LIBRARY:.a=.so) $$undefopts $(LIBRARY) +sunos5_shared_library: + undefopts=`/usr/ccs/bin/nm $(LIBRARY) | grep GLOB | grep FUNC | \ + awk '-F|' '{print $$8}' | sed 's/^/-u /'` && \ + ld -o $(LIBRARY:.a=.so) -G $$undefopts $(LIBRARY) + + +################################################################################ +# Linking: + + +################################################################################ +# $(INSTALL)ation: + +$(INCDIR)/$(HEADER): $(INCDIR) $(HEADER) + $(INSTALL) $(srcdir)/$(HEADER) $@ +$(INCDIR)/$(HEADER1): $(INCDIR) $(HEADER1) + $(INSTALL) $(srcdir)/$(HEADER1) $@ +$(INCDIR)/$(HEADER2): $(INCDIR) $(HEADER2) + $(INSTALL) $(srcdir)/$(HEADER2) $@ +$(INCDIR)/$(HEADER3): $(INCDIR) $(HEADER3) + $(INSTALL) $(srcdir)/$(HEADER3) $@ + +$(INCDIR)/$(HEADER_GENERATED): $(INCDIR) $(HEADER_GENERATED) + cp $(HEADER_GENERATED) $@ + +$(LIBDIR)/$(LIBRARY): $(LIBDIR) $(LIBRARY) + cp $(LIBRARY) $@ + +$(BINDIR)/$(PROGRAM): $(BINDIR) $(PROGRAM) + cp $(PROGRAM) $@ + +#$(BINDIR) \ +#$(INCDIR) \ +#$(LIBDIR) \ +#$(MANDIR) : +# -test -d $@ || mkdir $@ + +#$(MANDIR)/man1 \ +#$(MANDIR)/man3 \ +#$(MANDIR)/man3f \ +#$(MANDIR)/man3f90 : $(MANDIR) +# -test -d $@ || mkdir $@ + +$(MANDIR)/man1/$(MANUAL): $(MANDIR)/man1 $(MANUAL) + $(INSTALL) $(srcdir)/$(MANUAL) $@ +$(MANDIR)/man3/$(MANUAL): $(MANDIR)/man3 $(MANUAL) + $(INSTALL) $(srcdir)/$(MANUAL) $@ +$(MANDIR)/man3f/$(MANUAL): $(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \ + $(MANDIR)/man3f + rm -f $@ + ln -s $(MANDIR)/man3/$(MANUAL) $@ +$(MANDIR)/man3f90/$(MANUAL): $(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \ + $(MANDIR)/man3f90 + rm -f $@ + ln -s $(MANDIR)/man3/$(MANUAL) $@ + +################################################################################ +# Cleanup: + +clean: FORCE + rm -f *.o *.a *.so *.sl *.i *.Z core $(GARBAGE) ncgentab.* pnetcdf.3 + +distclean: FORCE + rm -f *.o *.a *.so *.sl *.i *.Z core $(GARBAGE) \ + MANIFEST *.log $(DIST_GARBAGE) Makefile cscope.out cscope.files + rm -rf SunWS_cache + +################################################################################ +# Dependencies: + +# This target should only need to be made at the UPC. +# NOTES: +# * The target file might be a symbolic link. +# * The name of the target doesn't match the name of the created file to +# prevent constant updating of the included file `depend' by make(1). +# +deps: FORCE + $(CC_MAKEDEPEND) $(CPPFLAGS) *.c | grep -v '/usr/include' >>depend + sort -u -o depend depend + + +################################################################################ +# Distribution: + +# The following rule echoes the contents of $(PACKING_LIST) in the +# current directory and in all subdirectories. All pathnames are made +# relative to the current directory. +# +MANIFEST.echo: FORCE + @echo $(PACKING_LIST) | fmt -1 + @if [ -n "$(SUBDIRS)" ]; then \ + subdirs="$(SUBDIRS)"; \ + for subdir in $$subdirs; do \ + (cd $$subdir && \ + echo 1>&2 Creating $@ in `pwd` && \ + $(MAKE) MANIFEST.echo | sed "s|^|$$subdir/|") || exit 1; \ + done; \ + else \ + :; \ + fi + +# The following rule ensures that all files in $(PACKING_LIST) exist in +# the current directory and in all subdirectories. +# +ensure_manifest: $(PACKING_LIST) FORCE + @if [ -n "$(SUBDIRS)" ]; then \ + subdirs="$(SUBDIRS)"; \ + for subdir in $$subdirs; do \ + (cd $$subdir && \ + echo 1>&2 Creating $@ in `pwd` && \ + $(MAKE) ensure_manifest) || exit 1; \ + done; \ + else \ + :; \ + fi + + +################################################################################ +# Misc: + +FORCE: Index: /tags/v1-0-3/README.large_files =================================================================== --- /tags/v1-0-3/README.large_files (revision 418) +++ /tags/v1-0-3/README.large_files (revision 418) @@ -0,0 +1,48 @@ +==== BACKGROUND + +The "traditonal" netcdf file format (CDF-1) uses a 4-byte value to hold +the offset into the file where one can find a variable's data + +Recently (October 2003), Greg Sjaardema proposed a +new file format (CDF-2) which uses an 8-byte value for the offset. +We use his approach in parallel netcdf, though we have modified his +patch against netcdf-3.5-beta1 to apply to our codebase. + +I couldn't find a URL to Greg's original message, but here's Russ Rew's +followup: +http://www.unidata.ucar.edu/projects/coohl/mhonarc/MailArchives/netcdf/msg04811.html + +This means there are two different but compatable implementations of the +CDF-2 file format. We (the parallel netcdf developers) will make our +best effort to keep our implementation compatable with the serial netcdf +implementation. Please report any incompatabilities to the developers +at parallel-netcdf@mcs.anl.gov. + +==== PRELIMINARIES + +First, it is important that your MPI-IO implementation uses an 8 byte +type to represent the 'MPI_Offset' + +Second, your platform should use an 8 byte type to represent the 'off_t' +type. On linux, solaris, IRIX64 (and quite possibly others), parallel-netcdf +will automatically add the right options to the compiler to make this +happen. + +Run configure as you normally would. Let the developers know if +configure says your 'off_t' is 4 bytes. Proceed to compile and install +the library. + +==== USAGE + +By default, parallel-netcdf will create CDF-1 formatted files. This +will ensure that datasets created by our library will be compatable with +the large body of applications which expect NetCDF files to be CDF-1 +formatted. + +To write a CDF-2 formatted file, add the flag 'NC_64BIT_OFFSET' to the +ncmpi_create() function call ( or nfmpi_create() if using the Fortran +interface) + +The parallel-netcdf library will detect the format of the dataset. +There are no special options needed to read back files created with the +NC_64BIT_OFFSET flag set. Index: /tags/v1-0-3/COPYRIGHT =================================================================== --- /tags/v1-0-3/COPYRIGHT (revision 16) +++ /tags/v1-0-3/COPYRIGHT (revision 16) @@ -0,0 +1,30 @@ +Copyright 1993-1999 University Corporation for Atmospheric Research/Unidata + +Portions of this software were developed by the Unidata Program at the +University Corporation for Atmospheric Research. + +Access and use of this software shall impose the following obligations +and understandings on the user. The user is granted the right, without +any fee or cost, to use, copy, modify, alter, enhance and distribute +this software, and any derivative works thereof, and its supporting +documentation for any purpose whatsoever, provided that this entire +notice appears in all copies of the software, derivative works and +supporting documentation. Further, UCAR requests that the user credit +UCAR/Unidata in any publications that result from the use of this +software or in any product that includes this software. The names UCAR +and/or Unidata, however, may not be used in any advertising or publicity +to endorse or promote any products or commercial entity unless specific +written permission is obtained from UCAR/Unidata. The user also +understands that UCAR/Unidata is not obligated to provide the user with +any support, consulting, training or assistance of any kind with regard +to the use, operation and performance of this software nor to provide +the user with any updates, revisions, new versions or "bug fixes." + +THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. Index: /tags/v1-0-3/README.jazz =================================================================== --- /tags/v1-0-3/README.jazz (revision 171) +++ /tags/v1-0-3/README.jazz (revision 171) @@ -0,0 +1,32 @@ +# ;cat ~/.soft +# # +# # This is the .soft file. +# # It is used to customize your environment by setting up environment +# # variables such as PATH and MANPATH. +# # To learn what can be in this file, use 'man softenv'. +# # +# # +# @default +# +pbs +# +intel-7.0 +# +# --- +# +# ;which mpicc +# /soft/apps/packages/mpich-gm-1.2.5..9-pre6-gm-1.6.3-intel-7.0/bin/mpicc +# ;which mpif77 +# /soft/apps/packages/mpich-gm-1.2.5..9-pre6-gm-1.6.3-intel-7.0/bin/mpif77 +# ;which icc +# /soft/com/packages/intel-7/compiler70/ia32/bin/icc +# ;which ifc +# /soft/com/packages/intel-7/compiler70/ia32/bin/ifc +# +# --- + +setenv CC icc +setenv FC ifc +setenv F90 ifc +setenv CXX icc +setenv MPICC mpicc +setenv MPIF77 mpif77 + Index: /tags/v1-0-3/man/netcdf.m4 =================================================================== --- /tags/v1-0-3/man/netcdf.m4 (revision 538) +++ /tags/v1-0-3/man/netcdf.m4 (revision 538) @@ -0,0 +1,1207 @@ +divert(-1) + +changequote(<<,>>) +define(<>, defn(index)) + +define(<>, <<\fB$1\fR>>) + +define(<>, <<\fI$1\fP>>) + +define(<>, + <>) + +define(<>, + <> "HEADER_FILE($1)", + <<<>>> HEADER_FILE($1))>>) + +define(<>, + <>) + +define(<>, + <>) + +define(<>, + <>) + +define(<>, + <>) + +define(<>, + <>) + +define(<>, + <>) + +dnl AQUAL(io, rank) +define(<>, <>)>>)>>) + +dnl CTYPE(type) +define(<>, + <>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>) + +dnl CSTAR(io, rank) +define(<>, <>)>>) + +dnl FTYPE(type, rank) +define(<>, + <>, + <>)>>)>>)>>)>>)>>)>>)>>)>>)>>) + +dnl ATYPE(io,rank,type) +define(<>, <>CSTAR($1,$2)>>, + <>)>>) + +dnl AID(name, rank, type) +define(<>, <>ifelse(API,C, + <>, + <>)>>)>>) + +dnl ADECL(io, rank, type, name) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) + +dnl CCOMP(type) +define(<>, + <>)>>)>>)>>)>>)>>)>>)>>) + +dnl FCOMP(type) +define(<>, + <>)>>)>>)>>)>>)>>) + +dnl COMP(type) +define(<>, <>,<>)>>) + +define(<>, + <>) + +dnl DECL(return-type, name, argument-list) +define(<>, <>) + +dnl FDECL(name, argument-list) +define(<>, <>) + +dnl IODECL(name, type, argument-list) +define(<>, <>COMP($2), $3)>>) + +dnl FREF(name) +define(<>, <>) + +dnl FOLD(cname, fname) +define(<>, <>) + +dnl Function Input Arguments: +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>)>>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, ITEXTV(path)) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, <>) +define(<>, <>) + +dnl Function Output Arguments: +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>)>>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +dnl Argument References: +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>)>>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>>>)>>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) +define(<>, <>) + +define(<>, +<>) + +dnl Variable "Put" Functions: +define(<>, <>UPCASE($1)<<>>ifelse($2,1,,V)(ifelse($2,1,*)out)>>) +define(<>, <>) +define(<>, <>) +define(<>,<>)>>) +define(<>,<>)>>) +define(<>,<>)>>) +define(<>,<>)>>) + +dnl Variable "Get" Functions: +define(<>, <>UPCASE($1)<<>>ifelse($2,1,,V)(in)>>) +define(<>, <>) +define(<>, <>) +define(<>,<>)>>) +define(<>,<>)>>) +define(<>,<>)>>) +define(<>,<>)>>) + +dnl Attribute "Put" Functions: +define(<>, <>UPCASE($1)<<>>V(out)>>) +define(<>,<>) + +dnl Attribute "Get" Functions: +define(<>, <>UPCASE($1)<<>>V(in)>>) +define(<>,<>) + +dnl Function Family Listing: +define(<>, +<<.HP +$1(text) +ifelse(API,C, +<<.HP +$1(uchar)>>) +.HP +$1(schar) +.HP +$1(short) +.HP +$1(int) +ifelse(API,C, +<<.HP +$1(long)>>) +.HP +$1(float) +.HP +$1(double)>>) + +divert(0)dnl +.TH PNETCDF 1.0 "Printed: \n(yr.\n(mo.\n(dy" "UNIDATA LIBRARY FUNCTIONS" +.SH N<<>>AME +pnetcdf \- Parallel Network Common Data Form (P-netCDF) library, version 3 interface +.SH SYNOPSIS +.ft B +.na +.nh +INCLUDE(pnetcdf) +.sp +ifelse(API,C,, +.SS Most Systems:) +COMPILER() ... -lpnetcdf +ifelse(API,C,, +.sp +.SS CRAY PVP Systems: +f90 -dp -i64 ... -lpnetcdf +) +.ad +.hy +.SH "LIBRARY VERSION" +.LP +This document describes the Parallel-NetCDF interface, a parallel version of Unidata's netCDF data-access interface +for the LANGUAGE() programming language. +.HP +DECL(RETSTR(), inq_libvers, (VOID_ARG)) +.sp +Returns a string identifying the version of the pnetCDF library, and +when it was built, like: "3.1a of Aug 22 1996 12:57:47 $". +.LP +The RCS \fBident(1)\fP command will find a string like +"$\|Id: @\|(#) pnetcdf library version 3.1a of Sep 6 1996 15:56:26 $" +in the library. The SCCS \fBwhat(1)\fP command will find a string like +"pnetcdf library version 3.1a of Aug 23 1996 16:07:40 $". +.SH "RETURN VALUES" +.LP +All pnetCDF functions (except +FREF(inq_libvers) and FREF(strerror)) return an integer status. +This behavior replaces the +ifelse(API,C, <>, <> argument) +used in previous versions of the library. +If this returned status value is not equal to +MACRO(NOERR) (zero), it +indicates that an error occurred. The possible status values are defined in +ifelse(API,C, system <<<>>> file and in )<<>>dnl +ifelse(API,C,")HEADER_FILE(pnetcdf)<<>>ifelse(API,C,"). +.HP +DECL(RETSTR(), strerror, (ISTATUS())) +.sp +Returns a string textual translation of the \fIstatus\fP +value, like "Attribute or variable name contains illegal characters" +or "No such file or directory". +.HP +FDECL(create, (ICOMM(), IPATH(), ICMODE(), IINFO(), +ONCID())) +.sp +(Corresponds to FOLD(create, cre) in version 2) +.sp +Creates a new netCDF dataset at ARG(path), +returning a netCDF ID in ARG(ncid). +The argument ARG(cmode) may <> the bitwise-or +of the following flags: +MACRO(NOCLOBBER) +to protect existing datasets (default +silently blows them away), +MACRO(SHARE) +for synchronous dataset updates +(default is to buffer accesses), and +MACRO(LOCK) +(not yet implemented). +When a netCDF dataset is created, is is opened +MACRO(WRITE). +The new netCDF dataset is in <> mode. +.HP +FDECL(_create, (IPATH(), ICMODE(), IINITSIZE(), OCHUNKSIZE(), ONCID())) +.sp +Like FREF(create) but has additional performance tuning parameters. +.sp +The argument ARG(initialsize) sets the initial size of the file at +creation time. +.sp +See FREF(_open) below for an explanation of the ARG(chunksize) +parameter. +.HP +FDECL(open, (ICOMM(), IPATH(), IMODE(), IINFO(), ONCID())) +.sp +(Corresponds to FOLD(open, opn) in version 2) +.sp +Opens a existing netCDF dataset at ARG(path) +returning a netCDF ID +in ARG(ncid). +The type of access is described by the ARG(mode) parameter, +which may <> the bitwise-or +of the following flags: +MACRO(WRITE) +for read-write access (default +read-only), +MACRO(SHARE) +for synchronous dataset updates (default is +to buffer accesses), and +MACRO(LOCK) +(not yet implemented). +.HP +FDECL(_open, (IPATH(), IMODE(), OCHUNKSIZE(), ONCID())) +.sp +Like FREF(open) but has an additional performance tuning parameter. +.sp +The argument referenced by ARG(chunksize) controls a space versus time +tradeoff, memory allocated in the netcdf library versus number of system +calls. +Because of internal requirements, the value may not be set to exactly +the value requested. +The actual value chosen is returned by reference. +Using the value MACRO(SIZEHINT_DEFAULT) causes the library to choose a +default. +How the system choses the default depends on the system. +On many systems, the "preferred I/O block size" is available from the +CODE(stat()) system call, CODE(struct stat) member CODE(st_blksize). +If this is available it is used. Lacking that, twice the system pagesize +is used. +Lacking a call to discover the system pagesize, we just set default +chunksize to 8192. +.sp +The chunksize is a property of a given open netcdf descriptor +ARG(ncid), it is not a persistent property of the netcdf dataset. +.HP +FDECL(redef, (INCID())) +.sp +(Corresponds to FOLD(redef, redf) in version 2) +.sp +Puts an open netCDF dataset into <> mode, +so dimensions, variables, and attributes can be added or renamed and +attributes can be deleted. +.HP +FDECL(enddef, (INCID())) +.sp +(Corresponds to FOLD(endef, endf) in version 2) +.sp +Takes an open netCDF dataset out of <> mode. +The changes made to the netCDF dataset +while it was in <> mode are checked and committed to disk if no +problems occurred. Some data values may be written as well, +see "VARIABLE PREFILLING" below. +After a successful call, variable data can be read or written to the dataset. +.HP +FDECL(_enddef, (INCID(), IH_MINFREE(), IV_ALIGN(), IV_MINFREE(), IR_ALIGN())) +.sp +Like FREF(enddef) but has additional performance tuning parameters. +.sp +Caution: this function exposes internals of the netcdf version 1 file +<>. +It may not be available on future netcdf implementations. +.sp +The current netcdf file <> has three sections, +the "header" section, the data section for fixed size variables, and +the data section for variables which have an unlimited dimension (record +variables). +The header begins at the beginning of the file. The index +(offset) of the beginning of the other two sections is contained in the +header. Typically, there is no space between the sections. This causes +copying overhead to accrue if one wishes to change the size of the +sections, +as may happen when changing names of things, text attribute values, +adding +attributes or adding variables. Also, for buffered i/o, there may be +advantages +to aligning sections in certain ways. +.sp +The minfree parameters allow one to control costs of future calls +to FREF(redef), FREF(enddef) by requesting that ARG(minfree) bytes be +available at the end of the section. +The ARG(h_minfree) parameter sets the pad +at the end of the "header" section. The ARG(v_minfree) parameter sets +the pad at the end of the data section for fixed size variables. +.sp +The align parameters allow one to set the alignment of the beginning of +the corresponding sections. The beginning of the section is rounded up +to an index which is a multiple of the align parameter. The flag value +MACRO(ALIGN_CHUNK) tells the library to use the chunksize (see above) +as the align parameter. +The ARG(v_align) parameter controls the alignment of the beginning of +the data section for fixed size variables. +The ARG(r_align) parameter controls the alignment of the beginning of +the data section for variables which have an unlimited dimension (record +variables). +.sp +The file <> requires mod 4 alignment, so the align parameters +are silently rounded up to multiples of 4. The usual call, +CODE(FNAME(enddef)(NCID())) +is equivalent to +CODE(FNAME(_enddef)(NCID(), 0, 4, 0, 4)). +.sp +The file <> does not contain a "record size" value, this is +calculated from the sizes of the record variables. This unfortunate fact +prevents us from providing minfree and alignment control of the +"records" +in a netcdf file. If you add a variable which has an unlimited +dimension, +the third section will always be copied with the new variable added. +.HP +FDECL(sync, (INCID())) +.sp +(Corresponds to FOLD(sync, snc) in version 2) +.sp +Unless the +MACRO(SHARE) +bit is set in +FREF(open) or FREF(create), +accesses to the underlying netCDF dataset are +buffered by the library. This function synchronizes the state of +the underlying dataset and the library. +This is done automatically by +FREF(close) and FREF(enddef). +.HP +FDECL(abort, (INCID())) +.sp +(Corresponds to FOLD(abort, abor) in version 2) +.sp +You don't need to call this function. +This function is called automatically by +FREF(close) +if the netCDF was in <> mode and something goes wrong with the commit. +If the netCDF dataset isn't in <> mode, then this function is equivalent to +FREF(close). +If it is called after +FREF(redef), +but before +FREF(enddef), +the new definitions are not committed and the dataset is closed. +If it is called after +FREF(create) +but before +FREF(enddef), +the dataset disappears. +.HP +FDECL(close, (INCID())) +.sp +(Corresponds to +FOLD(close, clos) in version 2) +.sp +Closes an open netCDF dataset. +If the dataset is in <> mode, +FREF(enddef) +will be called before closing. +After a dataset is closed, its ID may be reassigned to another dataset. +.HP +FDECL(inq, (INCID(), ONDIMS(), ONVARS(), +ONATTS(), OUNLIMDIMID())) +.HP +FDECL(inq_ndims, (INCID(), ONDIMS())) +.HP +FDECL(inq_nvars, (INCID(), ONVARS())) +.HP +FDECL(inq_natts, (INCID(), ONATTS())) +.HP +FDECL(inq_unlimdim, (INCID(), OUNLIMDIMID())) +.sp +(Replace FOLD(inquire, inq) in version 2) +.sp +Use these functions to find out what is in a netCDF dataset. +Upon successful return, +NDIMS() will contain the +number of dimensions defined for this netCDF dataset, +NVARS() will contain the number of variables, +NATTS() will contain the number of attributes, and +UNLIMDIMID() will contain the +dimension ID of the unlimited dimension if one exists, or +ifelse(API,C, <<-1>>, <<0>>) otherwise. +ifelse(API,C, +<>) +.HP +FDECL(def_dim, (INCID(), INAME(), ILEN(), ODIMID())) +.sp +(Corresponds to FOLD(dimdef, ddef) in version 2) +.sp +Adds a new dimension to an open netCDF dataset, which must be +in <> mode. +NAME() is the dimension name. +ifelse(API,C,dnl +<>)<<>>dnl +DIMID() will contain the dimension ID of the newly created dimension. +.HP +FDECL(inq_dimid, (INCID(), INAME(), ODIMID())) +.sp +(Corresponds to FOLD(dimid, did) in version 2) +.sp +Given a dimension name, returns the ID of a netCDF dimension in DIMID(). +.HP +FDECL(inq_dim, (INCID(), IDIMID(), ONAME(), OLEN())) +.HP +FDECL(inq_dimname, (INCID(), IDIMID(), ONAME())) +.HP +FDECL(inq_dimlen, (INCID(), IDIMID(), OLEN())) +.sp +(Replace FOLD(diminq, dinq) in version 2) +.sp +Use these functions to find out about a dimension. +ifelse(API,C, +<>) +NAME() should be big enough (MACRO(MAX_NAME)) +to hold the dimension name as the name will be copied into your storage. +The length return parameter, LEN() +will contain the size of the dimension. +For the unlimited dimension, the returned length is the current +maximum value used for writing into any of the variables which use +the dimension. +.HP +FDECL(rename_dim, (INCID(), IDIMID(), INAME())) +.sp +(Corresponds to FOLD(dimrename, dren) in version 2) +.sp +Renames an existing dimension in an open netCDF dataset. +If the new name is longer than the old name, the netCDF dataset must be in +<> mode. +You cannot rename a dimension to have the same name as another dimension. +.HP +FDECL(def_var, (INCID(), INAME(), IXTYPE(), INDIMS(), IDIMIDS(), OVARID())) +.sp +(Corresponds to FOLD(vardef, vdef) in version 2) +.sp +Adds a new variable to a netCDF dataset. The netCDF must be in <> mode. +ifelse(API,C, <>)dnl +VARID() will be set to the netCDF variable ID. +.HP +FDECL(inq_varid, (INCID(), INAME(), OVARID())) +.sp +(Corresponds to FOLD(varid, vid) in version 2) +.sp +Returns the ID of a netCDF variable in VARID() given its name. +.HP +FDECL(inq_var, (INCID(), IVARID(), ONAME(), OXTYPE(), ONDIMS(), ODIMIDS(), +ONATTS())) +.HP +FDECL(inq_varname, (INCID(), IVARID(), ONAME())) +.HP +FDECL(inq_vartype, (INCID(), IVARID(), OXTYPE())) +.HP +FDECL(inq_varndims, (INCID(), IVARID(), ONDIMS())) +.HP +FDECL(inq_vardimid, (INCID(), IVARID(), ODIMIDS())) +.HP +FDECL(inq_varnatts, (INCID(), IVARID(), ONATTS())) +.sp +(Replace FOLD(varinq, vinq) in version 2) +.sp +Returns information about a netCDF variable, given its ID. +ifelse(API,C, +<>) +.HP +FDECL(rename_var, (INCID(), IVARID(), INAME())) +.sp +(Corresponds to FOLD(varrename, vren) in version 2) +.sp +Changes the name of a netCDF variable. +If the new name is longer than the old name, the netCDF must be in <> mode. +You cannot rename a variable to have the name of any existing variable. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(varput, vpt) in version 2) +.sp +Writes an entire netCDF variable (i.e. all the values). +The netCDF dataset must be open and in data mode. The type of the data is +specified in the function name, and it is converted to the external type +of the specified variable, if possible, otherwise an +MACRO(ERANGE) error is returned. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(varget, vgt) in version 2) +.sp +Reads an entire netCDF variable (i.e. all the values). +The netCDF dataset must be open and in data mode. +The data is converted from the external type of the specified variable, +if necessary, to the type specified in the function name. If conversion is +not possible, an MACRO(ERANGE) error is returned. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(varput1, vpt1) in version 2) +.sp +Puts a single data value into a variable at the position INDEX() of an +open netCDF dataset that is in data mode. The type of the data is +specified in the function name, and it is converted to the external type +of the specified variable, if possible, otherwise an MACRO(ERANGE) +error is returned. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(varget1, vgt1) in version 2) +.sp +Gets a single data value from a variable at the position INDEX() +of an open netCDF dataset that is in data mode. +The data is converted from the external type of the specified variable, +if necessary, to the type specified in the function name. If conversion is +not possible, an MACRO(ERANGE) error is returned. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(varput, vpt) in version 2) +.sp +Writes an array section of values into a netCDF variable of an open +netCDF dataset, which must be in data mode. The array section is specified +by the START() and COUNT() vectors, which give the starting <> +and count of values along each dimension of the specified variable. +The type of the data is +specified in the function name and is converted to the external type +of the specified variable, if possible, otherwise an MACRO(ERANGE) +error is returned. +FUNC_FAMILY(<>) +.sp +(Corresponds to FOLD(varget, vgt) in version 2) +.sp +Reads an array section of values from a netCDF variable of an open +netCDF dataset, which must be in data mode. The array section is specified +by the START() and COUNT() vectors, which give the starting <> +and count of values along each dimension of the specified variable. +The data is converted from the external type of the specified variable, +if necessary, to the type specified in the function name. If conversion is +not possible, an MACRO(ERANGE) error is returned. +FUNC_FAMILY(<>) +.sp +(Corresponds to FOLD(varputg, vptg) in version 2) +.sp +These functions are used for \fIstrided output\fP, which is like the +array section output described above, except that +the sampling stride (the interval between accessed values) is +specified for each dimension. +For an explanation of the sampling stride +vector, see COMMON ARGUMENTS DESCRIPTIONS below. +FUNC_FAMILY(<>) +.sp +(Corresponds to FOLD(vargetg, vgtg) in version 2) +.sp +These functions are used for \fIstrided input\fP, which is like the +array section input described above, except that +the sampling stride (the interval between accessed values) is +specified for each dimension. +For an explanation of the sampling stride +vector, see COMMON ARGUMENTS DESCRIPTIONS below. +FUNC_FAMILY(<>) +.sp +(Corresponds to FOLD(varputg, vptg) in version 2) +.sp +These functions are used for \fImapped output\fP, which is like +strided output described above, except that an additional <> mapping +vector is provided to specify the in-memory arrangement of the data +values. +For an explanation of the <> +mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below. +FUNC_FAMILY(<>) +.sp +(Corresponds to FOLD(vargetg, vgtg) in version 2) +.sp +These functions are used for \fImapped input\fP, which is like +strided input described above, except that an additional <> mapping +vector is provided to specify the in-memory arrangement of the data +values. +For an explanation of the <> +mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(attput, apt) in version 2) +.sp +Unlike variables, attributes do not have +separate functions for defining and writing values. +This family of functions defines a new attribute with a value or changes +the value of an existing attribute. +If the attribute is new, or if the space required to +store the attribute value is greater than before, +the netCDF dataset must be in <> mode. +The parameter LEN() is the number of values from OUT() to transfer. +It is often one, except that for +FREF(put_att_text) it will usually be +ifelse(API,C, <>, <>) +.sp +For these functions, the type component of the function name refers to +the in-memory type of the value, whereas the XTYPE() argument refers to the +external type for storing the value. An MACRO(ERANGE) +error results if +a conversion between these types is not possible. In this case the value +is represented with the appropriate fill-value for the associated +external type. +.HP +FDECL(inq_attname, (INCID(), IVARID(), IATTNUM(), ONAME())) +.sp +(Corresponds to FOLD(attname, anam) in version 2) +.sp +Gets the +name of an attribute, given its variable ID and attribute number. +This function is useful in generic applications that +need to get the names of all the attributes associated with a variable, +since attributes are accessed by name rather than number in all other +attribute functions. The number of an attribute is more volatile than +the name, since it can change when other attributes of the same variable +are deleted. The attributes for each variable are numbered +from ifelse(API,C,0,1) (the first attribute) to +NVATTS()<<>>ifelse(API,C,-1), +where NVATTS() is +the number of attributes for the variable, as returned from a call to +FREF(inq_varnatts). +ifelse(API,C, +<>) +.HP +FDECL(inq_att, (INCID(), IVARID(), INAME(), OXTYPE(), OLEN())) +.HP +FDECL(inq_attid, (INCID(), IVARID(), INAME(), OATTNUM())) +.HP +FDECL(inq_atttype, (INCID(), IVARID(), INAME(), OXTYPE())) +.HP +FDECL(inq_attlen, (INCID(), IVARID(), INAME(), OLEN())) +.sp +(Corresponds to FOLD(attinq, ainq) in version 2) +.sp +These functions return information about a netCDF attribute, +given its variable ID and name. The information returned is the +external type in XTYPE() +and the number of elements in the attribute as LEN(). +ifelse(API,C, +<>) +.HP +FDECL(copy_att, (INCID(), IVARIDIN(), INAME(), INCIDOUT(), IVARIDOUT())) +.sp +(Corresponds to FOLD(attcopy, acpy) in version 2) +.sp +Copies an +attribute from one netCDF dataset to another. It can also be used to +copy an attribute from one variable to another within the same netCDF. +NCIDIN() is the netCDF ID of an input netCDF dataset from which the +attribute will be copied. +VARIDIN() +is the ID of the variable in the input netCDF dataset from which the +attribute will be copied, or MACRO(GLOBAL) +for a global attribute. +NAME() +is the name of the attribute in the input netCDF dataset to be copied. +NCIDOUT() +is the netCDF ID of the output netCDF dataset to which the attribute will be +copied. +It is permissible for the input and output netCDF ID's to be the same. The +output netCDF dataset should be in <> mode if the attribute to be +copied does not already exist for the target variable, or if it would +cause an existing target attribute to grow. +VARIDOUT() +is the ID of the variable in the output netCDF dataset to which the attribute will +be copied, or MACRO(GLOBAL) to copy to a global attribute. +.HP +FDECL(rename_att, (INCID(), IVARID(), INAME(), INEWNAME())) +.sp +(Corresponds to FOLD(attrename, aren) +.sp +Changes the +name of an attribute. If the new name is longer than the original name, +the netCDF must be in <> mode. You cannot rename an attribute to +have the same name as another attribute of the same variable. +NAME() is the original attribute name. +NEWNAME() +is the new name to be assigned to the specified attribute. If the new name +is longer than the old name, the netCDF dataset must be in <> mode. +.HP +FDECL(del_att, (INCID(), IVARID(), INAME())) +.sp +(Corresponds to FOLD(attdel, adel) in version 2) +.sp +Deletes an attribute from a netCDF dataset. The dataset must be in +<> mode. +FUNC_FAMILY(<>) +.sp +(Replace FOLD(attget, agt) in version 2) +.sp +Gets the value(s) of a netCDF attribute, given its +variable ID and name. Converts from the external type to the type +specified in +the function name, if possible, otherwise returns an MACRO(ERANGE) +error. +All elements of the vector of attribute +values are returned, so you must allocate enough space to hold +them. If you don't know how much space to reserve, call +FREF(inq_attlen) +first to find out the length of the attribute. +.SH "COMMON ARGUMENT DESCRIPTIONS" +.LP +In this section we <> some common arguments which are used in the +"FUNCTION DESCRIPTIONS" section. +.TP +INCID() +is the netCDF ID returned from a previous, successful call to +FREF(open) or FREF(create) +.TP +ONAME() +is the name of a dimension, variable, or attribute. +It shall begin with an alphabetic character, followed by +zero or more alphanumeric characters including the underscore +(`_') or hyphen (`-'). Case is significant. +ifelse(API,C,<>) +The maximum allowable number of characters +ifelse(API,C,(excluding the terminating 0)) is MACRO(MAX_NAME). +Names that begin with an underscore (`_') are reserved for use +by the netCDF interface. +.TP +IXTYPE() +specifies the external data type of a netCDF variable or attribute and +is one of the following: +MACRO(BYTE), MACRO(CHAR), MACRO(SHORT), MACRO(INT), +MACRO(FLOAT), or MACRO(DOUBLE). +These are used to specify 8-bit integers, +characters, 16-bit integers, 32-bit integers, 32-bit IEEE floating point +numbers, and 64-bit IEEE floating-point numbers, respectively. +ifelse(API,C, +<<(MACRO(INT) corresponds to MACRO(LONG) in version 2, to specify a +32-bit integer).>>) +.TP +ODIMIDS() +is a vector of dimension ID's and defines the shape of a netCDF variable. +The size of the vector shall be greater than or equal to the +rank (i.e. the number of dimensions) of the variable (NDIMS()). +The vector shall be ordered by the speed with which a dimension varies: +DIMIDS()<<>>ifelse(API,C,<<[NDIMS()-1]>>,<<(1)>>) +shall be the dimension ID of the most rapidly +varying dimension and +DIMIDS()<<>>ifelse(API,C,<<[0]>>,<<(NDIMS())>>) +shall be the dimension ID of the most slowly +varying dimension. +The maximum possible number of +dimensions for a variable is given by the symbolic constant +MACRO(MAX_VAR_DIMS). +.TP +IDIMID() +is the ID of a netCDF dimension. +netCDF dimension ID's are allocated sequentially from the +ifelse(API,C,non-negative, positive) +integers beginning with ifelse(API,C,0,1). +.TP +INDIMS() +is either the total number of dimensions in a netCDF dataset or the rank +(i.e. the number of dimensions) of a netCDF variable. +The value shall not be negative or greater than the symbolic constant +MACRO(MAX_VAR_DIMS). +.TP +IVARID() +is the ID of a netCDF variable or (for the attribute-access functions) +the symbolic constant +MACRO(GLOBAL), +which is used to reference global attributes. +netCDF variable ID's are allocated sequentially from the +ifelse(API,C,non-negative,positive) +integers beginning with ifelse(API,C,0,1). +.TP +ONATTS() +is the number of global attributes in a netCDF dataset for the +FREF(inquire) +function or the number +of attributes associated with a netCDF variable for the +FREF(varinq) +function. +.TP +IINDEX() +specifies the indicial coordinates of the netCDF data value to be accessed. +The indices start at ifelse(API,C,0,1); +thus, for example, the first data value of a +two-dimensional variable is ifelse(API,C,(0,0),(1,1)). +The size of the vector shall be at least the rank of the associated +netCDF variable and its elements shall correspond, in order, to the +variable's dimensions. +.TP +ISTART() +specifies the starting point +for accessing a netCDF variable's data values +in terms of the indicial coordinates of +the corner of the array section. +The indices start at ifelse(API,C,0,1); +thus, the first data +value of a variable is ifelse(API,C,(0, 0, ..., 0),(1, 1, ..., 1)). +The size of the vector shall be at least the rank of the associated +netCDF variable and its elements shall correspond, in order, to the +variable's dimensions. +.TP +ICOUNT() +specifies the number of indices selected along each dimension of the +array section. +Thus, to access a single value, for example, specify COUNT() as +(1, 1, ..., 1). +Note that, for strided I/O, this argument must be adjusted +to be compatible with the STRIDE() and START() arguments so that +the interaction of the +three does not attempt to access an invalid data co-ordinate. +The elements of the +COUNT() vector correspond, in order, to the variable's dimensions. +.TP +ISTRIDE() +specifies the sampling interval along each dimension of the netCDF +variable. The elements of the stride vector correspond, in order, +to the netCDF variable's dimensions (ARG(stride)<<>>ifelse(API,C,[0],<<(1)>>)) +gives the sampling interval along the most ifelse(API,C,slowly,rapidly) +varying dimension of the netCDF variable). Sampling intervals are +specified in type-independent units of elements (a value of 1 selects +consecutive elements of the netCDF variable along the corresponding +dimension, a value of 2 selects every other element, etc.). +ifelse(API,C,<>) +.TP +IMAP() +specifies the mapping between the dimensions of a netCDF variable and +the in-memory structure of the internal data array. The elements of +the <> mapping vector correspond, in order, to the netCDF variable's +dimensions (ARG(imap)<<>>ifelse(API,C,[0],<<(1)>>) gives the distance +between elements of the internal array corresponding to the most +ifelse(API,C,slowly,rapidly) varying dimension of the netCDF variable). +Distances between elements are specified in type-independent units of +elements (the distance between internal elements that occupy adjacent +memory locations is 1 and not the element's byte-length as in netCDF 2). +ifelse(API,C,<>) +.SH "VARIABLE PREFILLING" +.LP +By default, the netCDF interface sets the values of +all newly-defined variables of finite length (i.e. those that do not have +an unlimited, dimension) to the type-dependent fill-value associated with each +variable. This is done when FREF(enddef) +is called. The +fill-value for a variable may be changed from the default value by +defining the attribute `CODE(_FillValue)' for the variable. This +attribute must have the same type as the variable and be of length one. +.LP +Variables with an unlimited dimension are also prefilled, but on +an `as needed' basis. For example, if the first write of such a +variable is to position 5, then +positions +ifelse(API,C,0 through 4, 1 through 4) +(and no others) +would be set to the fill-value at the same time. +.LP +This default prefilling of data values may be disabled by +or'ing the +MACRO(NOFILL) +flag into the mode parameter of FREF(open) or FREF(create), +or, by calling the function FREF(set_fill) +with the argument MACRO(NOFILL). +For variables that do not use the unlimited dimension, +this call must +be made before +FREF(enddef). +For variables that +use the unlimited dimension, this call +may be made at any time. +.LP +One can obtain increased performance of the netCDF interface by using +this feature, but only at the expense of requiring the application to set +every single data value. The performance +enhancing behavior of this function is dependent on the particulars of +the implementation and dataset <>. +The flag value controlled by FREF(set_fill) +is per netCDF ID, +not per variable or per write. +Allowing this to change affects the degree to which +a program can be effectively parallelized. +Given all of this, we state that the use +of this feature may not be available (or even needed) in future +releases. Programmers are cautioned against heavy reliance upon this +feature. +.HP +FDECL(setfill, (INCID(), IFILLMODE(), OOLDFILLMODE())) +ifelse(API,C, +<<.sp +(Corresponds to FOLD(setfill) in version 2)>>) +.sp +Determines whether or not variable prefilling will be done (see +above). +The netCDF dataset shall be writable. +FILLMODE() is either MACRO(FILL) +to enable prefilling (the +default) or MACRO(NOFILL) +to disable prefilling. +This function returns the previous setting in OLDFILLMODE(). +.SH "MPP FUNCTION DESCRIPTIONS" +.LP +Additional functions for use on SGI/Cray MPP machines (_CRAYMPP). +These are used to set and inquire which PE is the base for MPP +for a particular netCDF. These are only relevant when +using the SGI/Cray ``global'' +Flexible File I/O layer and desire to have +only a subset of PEs to open the specific netCDF file. +For technical reasons, these functions are available on all platforms. +On a platform other than SGI/Cray MPP, it is as if +only processor available were processor 0. +.LP +To use this feature, you need to specify a communicator group and call +CODE(glio_group_mpi(\|)) or CODE(glio_group_shmem(\|)) prior to the netCDF +FREF(open) and FREF(create) calls. +.HP +FDECL(_create_mp, (IPATH(), ICMODE(), IINITSIZE(), IPE(), OCHUNKSIZE(), ONCID())) +.sp +Like FREF(_create) but allows the base PE to be set. +.sp +The argument ARG(pe) sets the base PE at creation time. In the MPP +environment, FREF(_create) and FREF(create) set the base PE to processor +zero by default. +.HP +FDECL(_open_mp, (IPATH(), IMODE(), IPE(), OCHUNKSIZE(), ONCID())) +.sp +Like FREF(_open) but allows the base PE to be set. +The argument ARG(pe) sets the base PE at creation time. In the MPP +environment, FREF(_open) and FREF(open) set the base PE to processor +zero by default. +.HP +FDECL(inq_base_pe, (INCID(), OPE())) +.sp +Inquires of the netCDF dataset which PE is being used as the base for MPP use. +This is safe to use at any time. +.HP +FDECL(set_base_pe, (INCID(), IPE())) +.sp +Resets the base PE for the netCDF dataset. +Only perform this operation when the affected communicator group +synchronizes before and after the call. +This operation is very risky and should only be contemplated +under only the most extreme cases. +.SH "ENVIRONMENT VARIABLES" +.TP 4 +.B NETCDF_FFIOSPEC +Specifies the Flexible File I/O buffers for netCDF I/O when executing +under the UNICOS operating system (the variable is ignored on other +operating systems). +An appropriate specification can greatly increase the efficiency of +netCDF I/O -- to the extent that it can actually surpass FORTRAN binary +I/O. +This environment variable has been made a little more generalized, +such that other FFIO option specifications can now be added. +The default specification is \fBbufa:336:2\fP, +unless a current FFIO specification is in operation, +which will be honored. +See UNICOS Flexible File I/O for more information. +.SH "MAILING-LISTS" +.LP +Both a mailing list and a digest are available for +discussion of the netCDF interface and announcements about netCDF bugs, +fixes, and enhancements. +To begin or change your subscription to either the mailing-list or the +digest, send one of the following in the body (not +the subject line) of an email message to "majordomo@unidata.ucar.edu". +Use your email address in place of \fIjdoe@host.inst.domain\fP. +.sp +To subscribe to the netCDF mailing list: +.RS +\fBsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR +.RE +To unsubscribe from the netCDF mailing list: +.RS +\fBunsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR +.RE +To subscribe to the netCDF digest: +.RS +\fBsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR +.RE +To unsubscribe from the netCDF digest: +.RS +\fBunsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR +.RE +To retrieve the general introductory information for the mailing list: +.RS +\fBinfo netcdfgroup\fR +.RE +To get a synopsis of other majordomo commands: +.RS +\fBhelp\fR +.RE +.SH "SEE ALSO" +.LP +.BR ncdump (1), +.BR ncgen (1), +.BR netcdf (3<<>>ifelse(API,C,,f)). +.LP +\fInetCDF User's Guide\fP, published +by the Unidata Program Center, University Corporation for Atmospheric +Research, located in Boulder, Colorado. Index: /tags/v1-0-3/man/Makefile =================================================================== --- /tags/v1-0-3/man/Makefile (revision 2) +++ /tags/v1-0-3/man/Makefile (revision 2) @@ -0,0 +1,19 @@ +# $Id$ +# +# Makefile for netcdf man +# + +include ../macros.make + +PACKING_LIST = Makefile \ + netcdf.m4 + +all: + +test: + +install: + +uninstall: + +include ../rules.make Index: /tags/v1-0-3/README.ifc_linux =================================================================== --- /tags/v1-0-3/README.ifc_linux (revision 486) +++ /tags/v1-0-3/README.ifc_linux (revision 486) @@ -0,0 +1,18 @@ +# here are the steps John Tannahill used when +# building pnetcdf on the "mcr" cluster at LLNL. It is a linux cluster +# with the intel compilers. + + setenv MPICC mpiicc + setenv MPIF77 mpiifc + setenv F77 ifc + setenv FC ifc + setenv CC icc + +# then run the usual "configure; make ; make install" + +On 5 October 2005, Richard Hedges reported that FFLAGS and CFLAGS needed the -O +and -mp options or the test suite would report errors in the +n[c,f]mpi_put_var*_float routines: + +FFLAGS = -O -mp +CFLAGS = -O -mp Index: /tags/v1-0-3/aclocal.m4 =================================================================== --- /tags/v1-0-3/aclocal.m4 (revision 563) +++ /tags/v1-0-3/aclocal.m4 (revision 563) @@ -0,0 +1,972 @@ +dnl $Id$ +dnl UD macros for netcdf configure + + +dnl Convert a string to all uppercase. +dnl +define([uppercase], +[translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)]) + +dnl +dnl Check for an m4(1) preprocessor utility. +dnl +AC_DEFUN(UD_PROG_M4, +[ + AC_CHECKING(for m4 preprocessor) + case "${M4-unset}" in + unset) AC_CHECK_PROGS(M4, m4 gm4, m4) ;; + *) AC_CHECK_PROGS(M4, $M4 m4 gm4, m4) ;; + esac + AC_MSG_CHECKING(m4 flags) + case "${M4FLAGS-unset}" in + unset) M4FLAGS=-B10000 ;; + esac + AC_MSG_RESULT($M4FLAGS) + AC_SUBST(M4FLAGS) +]) + +dnl +dnl Check for an ar(1) utility. +dnl +AC_DEFUN(UD_PROG_AR, +[ + AC_CHECKING(for ar utility) + case "${AR-unset}" in + unset) AC_CHECK_PROGS(AR, ar, ar) ;; + *) AC_CHECK_PROGS(AR, $AR ar, ar) ;; + esac + AC_MSG_CHECKING(ar flags) + case "${ARFLAGS-unset}" in + unset) ARFLAGS=cru ;; + esac + AC_MSG_RESULT($ARFLAGS) + AC_SUBST(ARFLAGS) +]) + +dnl +dnl Check for an nm(1) utility. +dnl +AC_DEFUN(UD_PROG_NM, +[ + AC_CHECKING(for nm utility) + case "${NM-unset}" in + unset) AC_CHECK_PROGS(NM, nm, nm) ;; + *) AC_CHECK_PROGS(NM, $NM nm, nm) ;; + esac + AC_MSG_CHECKING(nm flags) + case "${NMFLAGS-unset}" in + unset) NMFLAGS= ;; + esac + AC_MSG_RESULT($NMFLAGS) + AC_SUBST(NMFLAGS) +]) + +dnl +dnl Set the top-level source-directory. +dnl +AC_DEFUN(UD_SRCDIR, +[ + AC_MSG_CHECKING(for top-level source-directory) + SRCDIR=`(cd $srcdir && pwd)` + AC_MSG_RESULT($SRCDIR) + AC_SUBST(SRCDIR) +]) + +dnl +dnl Check for a Standard C compiler. Prefer a native one over the +dnl GNU one to reduce the chance that the environment variable LIBS +dnl will have to be set to reference the GNU C runtime library. +dnl +AC_DEFUN(UD_PROG_CC, +[ + # Because we must have a C compiler, we treat an unset CC + # the same as an empty CC. + case "${CC}" in + '') + case `uname` in + ULTRIX) + # The native ULTRIX C compiler isn't standard. + ccs='gcc cc' + ;; + *) + # xlc is before c89 because AIX's sizeof(long long) + # differs between the two. + # + ccs='xlc c89 acc cc gcc' + ;; + esac + for cc in $ccs; do + AC_CHECK_PROG(CC, $cc, $cc) + case "$CC" in + '') ;; + *) break + ;; + esac + done + case "${CC}" in + '') + AC_MSG_ERROR("Could not find C compiler") + ;; + esac + ;; + esac + # + # On some systems, a discovered compiler nevertheless won't + # work (due to licensing, for example); thus, we check the + # compiler with a test program. + # + AC_MSG_CHECKING(C compiler \"$CC\") + AC_TRY_COMPILE(, , + AC_MSG_RESULT(works), + AC_MSG_RESULT(failed to compile test program)) + AC_SUBST(CC) + case "$CC" in + *gcc*) + GCC=yes # Expected by autoconf(1) macros + ;; + esac + case `uname -sr` in + 'HP-UX A.09'*) + AC_DEFINE(_HPUX_SOURCE) + ;; + esac +]) + +dnl +dnl Check for a C++ compiler. Prefer a native one over the +dnl GNU one to reduce the chance that the environment variable LIBS +dnl will have to be set to reference the GNU C runtime library. +dnl +AC_DEFUN(UD_PROG_CXX, +[ + case "${CXX-unset}" in + unset) + case `uname` in + AIX) + preferred_cxx='xlC' + ;; + esac + possible_cxxs="${preferred_cxx} CC cxx c++ g++ gcc" + ;; + '') AC_MSG_WARN("Empty CXX variable") + possible_cxxs= + ;; + *) possible_cxxs=$CXX + ;; + esac + case "${possible_cxxs}" in + '') CXX= + ;; + *) AC_LANG_SAVE() + AC_LANG_CPLUSPLUS() + for cxx in $possible_cxxs; do + AC_CHECK_PROG(CXX, $cxx, $cxx) + case "$CXX" in + '') ;; + *) # On some systems, a discovered compiler nevertheless + # won't work (because it's a script to a non-existant + # executable, for example); thus, we check the + # compiler with a test program. We also test + # for and the standard C++ library + # because we need these to work. + # + AC_MSG_CHECKING(C++ compiler \"$CXX\") + AC_TRY_RUN( + [ + #include + int main() { + cout << ""; + return 0; + } + ], + [ + AC_MSG_RESULT(works) + break + ], + [ + AC_MSG_WARN($CXX failed on test program) + CXX= + unset ac_cv_prog_CXX + ]) + ;; + esac + done + AC_LANG_RESTORE() + case "${CXX}" in + '') AC_MSG_WARN("Could not find working C++ compiler") + AC_MSG_WARN(Setting CXX to the empty string) + ;; + esac + ;; + esac + case "${CXX}" in + '') AC_MSG_WARN(The C++ interface will not be built) + ;; + esac + AC_SUBST(CXX) + case `uname` in + 'HP-UX A.09'*) + AC_DEFINE(_HPUX_SOURCE) + ;; + esac +]) + + +dnl +dnl like AC_LONG_DOUBLE, except checks for 'long long' +dnl +AC_DEFUN(UD_C_LONG_LONG, +[AC_MSG_CHECKING(for long long) +AC_CACHE_VAL(ac_cv_c_long_long, +[if test "$GCC" = yes; then + ac_cv_c_long_long=yes +else +AC_TRY_RUN([int main() { +long long foo = 0; +exit(sizeof(long long) < sizeof(long)); }], +ac_cv_c_long_long=yes, ac_cv_c_long_long=no, :) +fi])dnl +AC_MSG_RESULT($ac_cv_c_long_long) +if test $ac_cv_c_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG) +fi +]) + +dnl +dnl UD_CHECK_IEEE +dnl If the 'double' is not an IEEE double +dnl or the 'float' is not and IEEE single, +dnl define NO_IEEE_FLOAT +dnl +AC_DEFUN(UD_CHECK_IEEE, +[ +AC_MSG_CHECKING(for IEEE floating point format) +AC_TRY_RUN([#ifndef NO_FLOAT_H +#include +#endif + +#define EXIT_NOTIEEE 1 +#define EXIT_MAYBEIEEE 0 + +int +main() +{ +#if defined(FLT_RADIX) && FLT_RADIX != 2 + return EXIT_NOTIEEE; +#elif defined(DBL_MAX_EXP) && DBL_MAX_EXP != 1024 + return EXIT_NOTIEEE; +#elif defined(DBL_MANT_DIG) && DBL_MANT_DIG != 53 + return EXIT_NOTIEEE; +#elif defined(FLT_MAX_EXP) && !(FLT_MAX_EXP == 1024 || FLT_MAX_EXP == 128) + return EXIT_NOTIEEE; +#elif defined(FLT_MANT_DIG) && !(FLT_MANT_DIG == 53 || FLT_MANT_DIG == 24) + return EXIT_NOTIEEE; +#else + /* (assuming eight bit char) */ + if(sizeof(double) != 8) + return EXIT_NOTIEEE; + if(!(sizeof(float) == 4 || sizeof(float) == 8)) + return EXIT_NOTIEEE; + + return EXIT_MAYBEIEEE; +#endif +}],ac_cv_c_ieeefloat=yes, ac_cv_c_ieeefloat=no, :) +AC_MSG_RESULT($ac_cv_c_ieeefloat) +if test x$ac_cv_c_ieeefloat = xno; then + AC_DEFINE(NO_IEEE_FLOAT) +fi +]) + +dnl Check for utility for generating makefile dependencies. +dnl Should only be used at the UPC. +dnl +AC_DEFUN(UD_PROG_CC_MAKEDEPEND, +[ + AC_MSG_CHECKING(how to make dependencies) + case `uname -s` in + IRIX*|OSF1) + CC_MAKEDEPEND='cc -M' + ;; + SunOS) + case `uname -r` in + 4*) + CC_MAKEDEPEND='cc -M' + ;; + 5*|*) + CC_MAKEDEPEND='cc -xM' + ;; + esac + ;; + ULTRIX) + case `uname -m` in + RISC) + CC_MAKEDEPEND='cc -M' + ;; + VAX) # Can't handle prototypes in netcdf.h + ;; + esac + ;; + AIX) # Writes to .u files rather than standard out + ;; + HP-UX) # Writes escaped newlines to standard error + ;; + esac + case "${CC_MAKEDEPEND}" in + '') + CC_MAKEDEPEND=false + ;; + esac + AC_MSG_RESULT($CC_MAKEDEPEND) + AC_SUBST(CC_MAKEDEPEND) +]) + + +dnl Check for Fortran-90 compiler. +dnl +AC_DEFUN(UD_PROG_F90, +[ + case "${F90+set}" in + set) + AC_MSG_CHECKING(user-defined Fortran-90 compiler \"$F90\") + cat <conftest.f90 + subroutine foo(bar) + integer, intent(in) :: bar + end subroutine foo +EOF + doit='$F90 -c ${F90FLAGS} conftest.f90' + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT(works) + else + AC_MSG_RESULT(failed to compile test program) + unset F90 + fi + rm -f conftest.* + ;; + *) + case "${FC+set}" in + set) + F90=$FC + F90FLAGS="${F90FLAGS-${FFLAGS--O}}" + F90LIBS="${F90LIBS-${FLIBS}}" + cat <conftest.f90 + program foo + call bar(1) + end program foo + subroutine bar(bof) + integer, intent(in) :: bof + end subroutine bar +EOF + AC_MSG_CHECKING(\"$F90\" as Fortran-90 compiler) + doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}' + if AC_TRY_EVAL(doit); then + doit=./conftest + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT(works) + else + AC_MSG_RESULT(failed to build executable program) + unset F90 + fi + else + AC_MSG_RESULT(failed to build test program) + unset F90 + fi + rm -f conftest* + ;; + esac + case "${F90-unset}" in + unset) + cat <conftest.f90 + program foo + call bar(1) + end program foo + subroutine bar(bof) + integer, intent(in) :: bof + end subroutine bar +EOF + for f90 in xlf90 pgf90 f90; do + AC_CHECK_PROG(F90, $f90, $f90) + case "${F90}" in + '') + ;; + *) + AC_MSG_CHECKING(Fortran-90 compiler \"$F90\") + doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}' + if AC_TRY_EVAL(doit); then + doit=./conftest + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT(works) + break; + else + AC_MSG_RESULT( + failed to build executable program) + unset F90 + unset ac_cv_prog_F90 + fi + else + AC_MSG_RESULT(failed to build test program) + unset F90 + unset ac_cv_prog_F90 + fi + ;; + esac + done + rm -f conftest* + case "${F90}" in + '') AC_MSG_WARN( + "Could not find working Fortran-90 compiler") + ;; + esac + ;; + esac + ;; + esac + case "${F90}" in + '') + AC_MSG_WARN("The Fortran-90 interface will not be built") + ;; + *f90*) + case `uname -s` in + IRIX*) + NETCDF_MOD=NETCDF.mod + ;; + *) + NETCDF_MOD=netcdf.mod + ;; + esac + AC_SUBST(NETCDF_MOD) + ;; + esac + AC_SUBST(F90) + AC_SUBST(F90FLAGS) + AC_SUBST(F90LIBS) +]) + +dnl Check for Fortran-77 compiler. +dnl +AC_DEFUN(UD_PROG_FC, +[ + AC_BEFORE([UD_FORTRAN_TYPES]) + case "${FC+set}" in + set) + case "$FC" in + '') + AC_MSG_WARN(Fortran-77 compiler is explicitly null) + ;; + *) + AC_MSG_CHECKING(user-defined Fortran-77 compiler \"$FC\") + cat <conftest.f + CALL FOO + END +EOF + doit='$FC -c ${FFLAGS} conftest.f' + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT(works) + else + AC_MSG_RESULT(failed to compile test program) + FC= + fi + rm -f conftest.* + ;; + esac + ;; + *) + case "${F90+set}" in + set) + FC=$F90 + FFLAGS="${FFLAGS-${F90FLAGS--O}}" + FLIBS="${FLIBS-${F90LIBS-}}" + AC_MSG_CHECKING(\"$FC\" as Fortran-77 compiler) + cat <conftest.f + CALL FOO + END +EOF + doit='$FC -c ${FFLAGS} conftest.f' + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT(works) + else + AC_MSG_RESULT(failed to compile test program) + unset FC + fi + rm -f conftest.* + ;; + esac + case "${FC-unset}" in + unset) + case `uname -sr` in + AIX*) + # xlf90(1) thinks fortran/ftest.F has bad syntax. + forts="xlf f77 gfortran" + ;; + BSD/OS*|FreeBSD*) + forts="f77 fort77 g77 gfortran" + ;; + HP-UX*) + # f77(1) doesn't have the -L option. + forts=fort77 + FLIBS=-lU77 + ;; + IRIX*) + # f90(1) can't link with c89(1)-compiled objects + forts=f77 + ;; + IRIX64*) + forts='f77 g77 gfortran fort77 ' + ;; + Linux*) + forts="pgf90 f77 fort77 g77 gfortran" + ;; + OSF1*) + # The use of f90(1) results in the following for + # an unknown reason (`make' works in the fortran/ + # directory): + # f90 -c -I../libsrc ftest.F + # Last chance handler: pc = 0xa971b8, + # sp = 0x3fece0, ra = 0xa971b8 + # Last chance handler: internal exception: unwinding + forts="f77 gfortran" + ;; + 'SunOS 4'*) + forts='f77 g77 gfortran fort77' + ;; + 'SunOS 5'*) + # SunOS's f90(1) has problems passing a C `char' + # as a Fortran `integer*1' => use f77(1) + forts="pgf90 f77" + ;; + sn*|UNICOS*|unicos*) + forts="fort77 cf77 f77 g77 gfortran f90" + ;; + *) + forts="xlf fort77 ghf77 f77 cf77 g77 gfortran xlf90 f90" + ;; + esac + for fc in $forts; do + AC_CHECK_PROG(FC, $fc, $fc) + case "${FC}" in + '') + ;; + *) + # + # On some systems, a discovered compiler + # nevertheless won't work (due to licensing, + # for example); thus, we check the compiler + # with a test program. + # + cat <conftest.f + CALL FOO + END +EOF + doit='$FC -c ${FFLAGS} conftest.f' + if AC_TRY_EVAL(doit); then + break + else + AC_MSG_RESULT( + failed to compile test program) + unset FC + unset ac_cv_prog_FC + fi + ;; + esac + done + rm -f conftest.* + case "${FC}" in + '') AC_MSG_WARN( + "Could not find working Fortran-77 compiler") + ;; + esac + ;; + esac + ;; + esac + case "${FC}" in + '') AC_MSG_WARN("The Fortran-77 interface will not be built") + ;; + esac + AC_SUBST(FC) + AC_SUBST(FFLAGS) + AC_SUBST(FLIBS) + # + # Set the make(1) macro for compiling a .F file. + # + case "${FPP-}" in + '') + AC_MSG_CHECKING(for Fortran .F compiler) + AC_MSG_RESULT($COMPILE_F) + case "${COMPILE_F-unset}" in + unset) + case "${FC}" in + '') + COMPILE_F= + ;; + *) + AC_MSG_CHECKING(if Fortran-77 compiler handles *.F files) + cat >conftest.h <<\EOF +#define J 1 +EOF + cat >conftest.F <<\EOF +#include "conftest.h" +#define N 5 + real r(J,N) + end +EOF + doit='$FC -o conftest ${FFLAGS} conftest.F ${FLIBS}' + if AC_TRY_EVAL(doit); then + COMPILE_F='$(COMPILE.f) $(FPPFLAGS)' + AC_MSG_RESULT(yes) + else + COMPILE_F= + AC_MSG_RESULT(no) + fi + rm -f conftest* + ;; + esac + ;; + esac + ;; + *) + unset COMPILE_F + ;; + esac + case "${COMPILE_F-}" in + '') UD_PROG_FPP;; + esac + AC_SUBST(COMPILE_F) + FPPFLAGS=${FPPFLAGS-} + AC_SUBST(FPPFLAGS) +]) + + +dnl Check for Fortran preprocessor. +dnl +AC_DEFUN(UD_PROG_FPP, +[ + AC_MSG_CHECKING(for Fortran preprocessor) + case "$FPP" in + '') + AC_REQUIRE([AC_PROG_CPP]) + FPP="$CPP" + ;; + esac + AC_MSG_RESULT($FPP) + AC_SUBST(FPP) +]) + + +dnl Check for a Fortran type equivalent to a netCDF type. +dnl +dnl UD_CHECK_FORTRAN_NCTYPE(forttype, possibs, nctype) +dnl +AC_DEFUN(UD_CHECK_FORTRAN_NCTYPE, +[ + AC_MSG_CHECKING(for Fortran-equivalent to netCDF \"$3\") + for type in $2; do + cat >conftest.f <conftest.f <conftest.c < +#include +void main() +{ +$3 values[[]] = {0, $4, 0, $5, 0}; +$3 minval, maxval; +void $FCALLSCSUB($3*, $3*, $3*); +$FCALLSCSUB(values, &minval, &maxval); +exit(!(minval == $4 && maxval == $5)); +} +EOF + doit='$CC -o conftest ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} conftest.c conftestf.o ${LIBS}' + if AC_TRY_EVAL(doit); then + doit=./conftest + if AC_TRY_EVAL(doit); then + AC_MSG_RESULT($2) + $1=$2 + AC_DEFINE_UNQUOTED($1,$2) + else + AC_MSG_RESULT(no equivalent type) + unset $1 + fi + else + AC_MSG_ERROR(Could not compile-and-link conftest.c and conftestf.o) + fi + else + AC_MSG_ERROR(Could not compile conftest.f) + fi + rm -f conftest* +]) + + +dnl Check for a Fortran data type. +dnl +dnl UD_CHECK_FORTRAN_TYPE(varname, ftypes) +dnl +AC_DEFUN(UD_CHECK_FORTRAN_TYPE, +[ + for ftype in $2; do + AC_MSG_CHECKING(for Fortran \"$ftype\") + cat >conftest.f <conftest.f <<\EOF + call sub() + end +EOF + doit='$FC -c ${FFLAGS} conftest.f' + if AC_TRY_EVAL(doit); then + FCALLSCSUB=`$NM $NMFLAGS conftest.o | awk ' + /SUB_/{print "SUB_";exit} + /SUB/ {print "SUB"; exit} + /sub_/{print "sub_";exit} + /sub/ {print "sub"; exit}'` + case "$FCALLSCSUB" in + '') AC_MSG_ERROR(not found) + ;; + *) AC_MSG_RESULT($FCALLSCSUB) + ;; + esac + else + AC_MSG_ERROR(Could not compile conftest.f) + fi + rm -f conftest* + ;; + esac +]) + + +dnl Check for a C type equivalent to a Fortran type. +dnl +dnl UD_CHECK_CTYPE_FORTRAN(ftype, ctypes, fmacro_root) +dnl +AC_DEFUN(UD_CHECK_CTYPE_FORTRAN, +[ + cat >conftestf.f <conftest.c < reported success building +# parallel-netcdf on the 'seaborg' cluster (an IBM-SP at NERSC) and Tyce +# Mclarty reported success on LLNL's 'frost' cluster by +# setting these environment variables: + + setenv MPICC mpcc_r + setenv MPIF77 mpxlf_r + setenv F77 xlf + setenv FC xlf + setenv CC xlc + setenv CXX xlC + +# after setting these variables, configure/make/make install should "just work" + + +# We also successfully tested 64-bit mode on 'DataStar' (an IBM-SP at SDSC) +# with environment variables: + + setenv OBJECT_MODE 64 + setenv MPICC mpcc_r + setenv MPIF77 mpxlf_r + setenv F77 xlf + setenv FC xlf + setenv CC xlc + setenv CXX xlC + setenv CFLAGS -q64 + setenv FFLAGS -q64 + setenv F90FLAGS -q64 + setenv CXXFLAGS -q64